diff options
author | Marino Faggiana <ios@nextcloud.com> | 2022-05-04 15:46:59 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-04 15:46:59 +0300 |
commit | 43b97986c21eb04ff352d93e1c19f7a2ea9257d4 (patch) | |
tree | 43a908c665b72fd0d11b2a30ce2f4c354535989b | |
parent | 9a92d1fb43bc4ea1d1b88f89af62d5301ee4c454 (diff) | |
parent | b0d1644c4c9ef87f18327ebd2206c07dd17af9e2 (diff) |
Merge pull request #1981 from nextcloud/improved/pdfview
Improved PDF Viewer
-rw-r--r-- | Nextcloud.xcodeproj/project.pbxproj | 17 | ||||
-rw-r--r-- | iOSClient/Data/NCDatabase.swift | 5 | ||||
-rw-r--r-- | iOSClient/Data/NCManageDatabase.swift | 32 | ||||
-rw-r--r-- | iOSClient/Menu/NCViewer+Menu.swift | 25 | ||||
-rw-r--r-- | iOSClient/NCGlobal.swift | 7 | ||||
-rw-r--r-- | iOSClient/Supporting Files/en.lproj/Localizable.strings | 3 | ||||
-rw-r--r-- | iOSClient/Utility/CCUtility.h | 3 | ||||
-rw-r--r-- | iOSClient/Utility/CCUtility.m | 17 | ||||
-rw-r--r-- | iOSClient/Viewer/NCViewerPDF/NCViewerPDF.swift | 324 |
9 files changed, 305 insertions, 128 deletions
diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index 666f1af0c..a52626815 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -207,6 +207,7 @@ F74E7720277A2EF40013B958 /* XLForm in Frameworks */ = {isa = PBXBuildFile; productRef = F74E771F277A2EF40013B958 /* XLForm */; }; F7501C322212E57500FB1415 /* NCMedia.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7501C302212E57400FB1415 /* NCMedia.storyboard */; }; F7501C332212E57500FB1415 /* NCMedia.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7501C312212E57400FB1415 /* NCMedia.swift */; }; + F753BA93281FD8020015BFB6 /* EasyTipView in Frameworks */ = {isa = PBXBuildFile; productRef = F753BA92281FD8020015BFB6 /* EasyTipView */; }; F755BD9B20594AC7008C5FBB /* NCService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F755BD9A20594AC7008C5FBB /* NCService.swift */; }; F7581D1A25EFDA61004DC699 /* NCLoginWeb+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7581D1925EFDA60004DC699 /* NCLoginWeb+Menu.swift */; }; F7581D2425EFDDDF004DC699 /* NCMedia+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7581D2325EFDDDF004DC699 /* NCMedia+Menu.swift */; }; @@ -1016,6 +1017,7 @@ F758A01227A7F03E0069468B /* JGProgressHUD in Frameworks */, F76DA96F277B78AE0082465B /* TLPhotoPicker in Frameworks */, F76DA966277B76F30082465B /* UICKeyChainStore in Frameworks */, + F753BA93281FD8020015BFB6 /* EasyTipView in Frameworks */, F76DA95B277B75A90082465B /* TOPasscodeViewController.xcframework in Frameworks */, F76DA963277B760E0082465B /* Queuer in Frameworks */, F75E57BD25BF0EC1002B72C2 /* SVGKit in Frameworks */, @@ -2085,6 +2087,7 @@ F7233B3927835FA400F40A43 /* ChromaColorPicker */, F7BB7E4627A18C56009B9F29 /* Parchment */, F758A01127A7F03E0069468B /* JGProgressHUD */, + F753BA92281FD8020015BFB6 /* EasyTipView */, ); productName = "Crypto Cloud"; productReference = F7CE8AFA1DC1F8D8009CAE48 /* Nextcloud.app */; @@ -2212,6 +2215,7 @@ F7233B3827835FA300F40A43 /* XCRemoteSwiftPackageReference "ChromaColorPicker" */, F7BB7E4527A18C56009B9F29 /* XCRemoteSwiftPackageReference "Parchment" */, F72CD01027A7E92400E59476 /* XCRemoteSwiftPackageReference "JGProgressHUD" */, + F753BA91281FD8010015BFB6 /* XCRemoteSwiftPackageReference "EasyTipView" */, ); productRefGroup = F7F67B9F1A24D27800EE80DA; projectDirPath = ""; @@ -3209,6 +3213,14 @@ minimumVersion = 4.0.0; }; }; + F753BA91281FD8010015BFB6 /* XCRemoteSwiftPackageReference "EasyTipView" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/marinofaggiana/EasyTipView"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.0.0; + }; + }; F75E57A725BF0D61002B72C2 /* XCRemoteSwiftPackageReference "SVGKit" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/SVGKit/SVGKit.git"; @@ -3393,6 +3405,11 @@ package = F74E771E277A2EF40013B958 /* XCRemoteSwiftPackageReference "XLForm" */; productName = XLForm; }; + F753BA92281FD8020015BFB6 /* EasyTipView */ = { + isa = XCSwiftPackageProductDependency; + package = F753BA91281FD8010015BFB6 /* XCRemoteSwiftPackageReference "EasyTipView" */; + productName = EasyTipView; + }; F758A01127A7F03E0069468B /* JGProgressHUD */ = { isa = XCSwiftPackageProductDependency; package = F72CD01027A7E92400E59476 /* XCRemoteSwiftPackageReference "JGProgressHUD" */; diff --git a/iOSClient/Data/NCDatabase.swift b/iOSClient/Data/NCDatabase.swift index 948cb78c7..d2cd149ac 100644 --- a/iOSClient/Data/NCDatabase.swift +++ b/iOSClient/Data/NCDatabase.swift @@ -493,6 +493,11 @@ class tableTag: Object { } } +class tableTip: Object { + + @Persisted(primaryKey: true) var tipName = "" +} + class tableTrash: Object { @objc dynamic var account = "" diff --git a/iOSClient/Data/NCManageDatabase.swift b/iOSClient/Data/NCManageDatabase.swift index 1cc04ca60..39033459a 100644 --- a/iOSClient/Data/NCManageDatabase.swift +++ b/iOSClient/Data/NCManageDatabase.swift @@ -245,6 +245,7 @@ class NCManageDatabase: NSObject { self.clearTable(tablePhotoLibrary.self, account: account) self.clearTable(tableShare.self, account: account) self.clearTable(tableTag.self, account: account) + self.clearTable(tableTip.self) self.clearTable(tableTrash.self, account: account) self.clearTable(tableUserStatus.self, account: account) self.clearTable(tableVideo.self, account: account) @@ -1547,6 +1548,37 @@ class NCManageDatabase: NSObject { } // MARK: - + // MARK: Table Tip + + @objc func tipExists(_ tipName: String) -> Bool { + + let realm = try! Realm() + + guard (realm.objects(tableTip.self).where { + $0.tipName == tipName + }.first) == nil else { + return true + } + + return false + } + + @objc func addTip(_ tipName: String) { + + let realm = try! Realm() + + do { + try realm.safeWrite { + let addObject = tableTip() + addObject.tipName = tipName + realm.add(addObject, update: .all) + } + } catch let error { + NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)") + } + } + + // MARK: - // MARK: Table Trash @objc func addTrash(account: String, items: [NCCommunicationTrash]) { diff --git a/iOSClient/Menu/NCViewer+Menu.swift b/iOSClient/Menu/NCViewer+Menu.swift index e85354bce..fb49825fe 100644 --- a/iOSClient/Menu/NCViewer+Menu.swift +++ b/iOSClient/Menu/NCViewer+Menu.swift @@ -226,31 +226,6 @@ extension NCViewer { ) ) - var title = "" - var icon = UIImage() - - if CCUtility.getPDFDisplayDirection() == .horizontal { - title = NSLocalizedString("_pdf_vertical_", comment: "") - icon = UIImage(named: "pdf-vertical")!.image(color: NCBrandColor.shared.gray, size: 50) - } else { - title = NSLocalizedString("_pdf_horizontal_", comment: "") - icon = UIImage(named: "pdf-horizontal")!.image(color: NCBrandColor.shared.gray, size: 50) - } - - actions.append( - NCMenuAction( - title: title, - icon: icon, - action: { _ in - if CCUtility.getPDFDisplayDirection() == .horizontal { - NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterMenuPDFDisplayDirection, userInfo: ["direction": PDFDisplayDirection.vertical]) - } else { - NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterMenuPDFDisplayDirection, userInfo: ["direction": PDFDisplayDirection.horizontal]) - } - } - ) - ) - actions.append( NCMenuAction( title: NSLocalizedString("_go_to_page_", comment: ""), diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift index 8fa81b169..a943207e1 100644 --- a/iOSClient/NCGlobal.swift +++ b/iOSClient/NCGlobal.swift @@ -112,7 +112,7 @@ class NCGlobal: NSObject { // Database Realm // let databaseDefault = "nextcloud.realm" - let databaseSchemaVersion: UInt64 = 217 + let databaseSchemaVersion: UInt64 = 218 // Intro selector // @@ -344,7 +344,6 @@ class NCGlobal: NSObject { let notificationCenterFavoriteFile = "favoriteFile" // userInfo: ocId let notificationCenterMenuSearchTextPDF = "menuSearchTextPDF" - let notificationCenterMenuPDFDisplayDirection = "menuPDFDisplayDirection" // userInfo: direction let notificationCenterMenuGotToPageInPDF = "menuGotToPageInPDF" let notificationCenterMenuDetailClose = "menuDetailClose" @@ -360,4 +359,8 @@ class NCGlobal: NSObject { let notificationCenterReloadMediaPage = "reloadMediaPage" let notificationCenterPlayMedia = "playMedia" let notificationCenterPauseMedia = "pauseMedia" + + // Tip + // + let tipNCViewerPDFThumbnail = "tipncviewerpdfthumbnail" } diff --git a/iOSClient/Supporting Files/en.lproj/Localizable.strings b/iOSClient/Supporting Files/en.lproj/Localizable.strings index 77165a34b..0709a71d9 100644 --- a/iOSClient/Supporting Files/en.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/en.lproj/Localizable.strings @@ -857,4 +857,5 @@ "_subtitle_not_found_" = "Subtitle not found"; "_disable_" = "Disable"; "_subtitle_not_dowloaded_" = "There are subtitles not downloaded locally"; - +// Tip +"_tip_pdf_thumbnails_" = "Swipe left from the right edge of the screen to show the thumbnails."; diff --git a/iOSClient/Utility/CCUtility.h b/iOSClient/Utility/CCUtility.h index e2aee0e86..3d5eee7e8 100644 --- a/iOSClient/Utility/CCUtility.h +++ b/iOSClient/Utility/CCUtility.h @@ -180,9 +180,6 @@ + (NSInteger)getCleanUpDay; + (void)setCleanUpDay:(NSInteger)days; -+ (PDFDisplayDirection)getPDFDisplayDirection; -+ (void)setPDFDisplayDirection:(PDFDisplayDirection)direction; - + (BOOL)getPrivacyScreenEnabled; + (void)setPrivacyScreenEnabled:(BOOL)set; diff --git a/iOSClient/Utility/CCUtility.m b/iOSClient/Utility/CCUtility.m index 0a2a97a6f..df4325707 100644 --- a/iOSClient/Utility/CCUtility.m +++ b/iOSClient/Utility/CCUtility.m @@ -715,23 +715,6 @@ [UICKeyChainStore setString:daysString forKey:@"cleanUpDay" service:NCGlobal.shared.serviceShareKeyChain]; } -+ (PDFDisplayDirection)getPDFDisplayDirection -{ - NSString *direction = [UICKeyChainStore stringForKey:@"PDFDisplayDirection" service:NCGlobal.shared.serviceShareKeyChain]; - - if (direction == nil) { - return kPDFDisplayDirectionVertical; - } else { - return [direction integerValue]; - } -} - -+ (void)setPDFDisplayDirection:(PDFDisplayDirection)direction -{ - NSString *directionString = [@(direction) stringValue]; - [UICKeyChainStore setString:directionString forKey:@"PDFDisplayDirection" service:NCGlobal.shared.serviceShareKeyChain]; -} - + (BOOL)getPrivacyScreenEnabled { NSString *valueString = [UICKeyChainStore stringForKey:@"privacyScreen" service:NCGlobal.shared.serviceShareKeyChain]; diff --git a/iOSClient/Viewer/NCViewerPDF/NCViewerPDF.swift b/iOSClient/Viewer/NCViewerPDF/NCViewerPDF.swift index f00dabc1e..3e77c598f 100644 --- a/iOSClient/Viewer/NCViewerPDF/NCViewerPDF.swift +++ b/iOSClient/Viewer/NCViewerPDF/NCViewerPDF.swift @@ -23,21 +23,34 @@ import UIKit import PDFKit +import EasyTipView -class NCViewerPDF: UIViewController, NCViewerPDFSearchDelegate { +class NCViewerPDF: UIViewController, NCViewerPDFSearchDelegate, UIGestureRecognizerDelegate { - let appDelegate = UIApplication.shared.delegate as! AppDelegate var metadata = tableMetadata() var imageIcon: UIImage? + private var filePath = "" + private var pdfView = PDFView() - private var thumbnailViewHeight: CGFloat = 40 + private var pdfThumbnailScrollView = UIScrollView() private var pdfThumbnailView = PDFThumbnailView() private var pdfDocument: PDFDocument? private let pageView = UIView() private let pageViewLabel = UILabel() + private var tipView: EasyTipView? + + private let thumbnailViewHeight: CGFloat = 70 + private let thumbnailViewWidth: CGFloat = 80 + private let thumbnailPadding: CGFloat = 2 + private let animateDuration: TimeInterval = 0.3 + + private var defaultBackgroundColor: UIColor = .clear + + private var pdfThumbnailScrollViewTopAnchor: NSLayoutConstraint? + private var pdfThumbnailScrollViewTrailingAnchor: NSLayoutConstraint? + private var pdfThumbnailScrollViewWidthAnchor: NSLayoutConstraint? private var pageViewWidthAnchor: NSLayoutConstraint? - private var filePath = "" // MARK: - View Life Cycle @@ -48,80 +61,129 @@ class NCViewerPDF: UIViewController, NCViewerPDFSearchDelegate { override func viewDidLoad() { filePath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)! - - pdfView = PDFView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height)) pdfDocument = PDFDocument(url: URL(fileURLWithPath: filePath)) + let pageCount = CGFloat(pdfDocument?.pageCount ?? 0) + defaultBackgroundColor = pdfView.backgroundColor + view.backgroundColor = defaultBackgroundColor + + navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "more")!.image(color: NCBrandColor.shared.label, size: 25), style: .plain, target: self, action: #selector(self.openMenuMore)) + navigationItem.title = metadata.fileNameView + + // PDF VIEW + if UIDevice.current.userInterfaceIdiom == .phone { + pdfView = PDFView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height)) + } else { + pdfView = PDFView(frame: CGRect(x: 0, y: 0, width: view.frame.width-thumbnailViewWidth, height: view.frame.height)) + } + pdfView.autoresizingMask = [.flexibleWidth, .flexibleHeight, .flexibleTopMargin, .flexibleLeftMargin] pdfView.document = pdfDocument - pdfView.backgroundColor = NCBrandColor.shared.systemBackground - pdfView.displayMode = .singlePageContinuous pdfView.autoScales = true - pdfView.displayDirection = CCUtility.getPDFDisplayDirection() - pdfView.autoresizingMask = [.flexibleWidth, .flexibleHeight, .flexibleTopMargin, .flexibleBottomMargin] - pdfView.usePageViewController(true, withViewOptions: nil) - + pdfView.displayMode = .singlePageContinuous + pdfView.displayDirection = .vertical + pdfView.maxScaleFactor = 4.0 + pdfView.minScaleFactor = pdfView.scaleFactorForSizeToFit view.addSubview(pdfView) + // PDF THUMBNAIL + + pdfThumbnailScrollView.translatesAutoresizingMaskIntoConstraints = false + pdfThumbnailScrollView.backgroundColor = defaultBackgroundColor + pdfThumbnailScrollView.showsVerticalScrollIndicator = false + view.addSubview(pdfThumbnailScrollView) + + pdfThumbnailScrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true + pdfThumbnailScrollViewTopAnchor = pdfThumbnailScrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor) + pdfThumbnailScrollViewTopAnchor?.isActive = true + pdfThumbnailScrollViewTrailingAnchor = pdfThumbnailScrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor) + pdfThumbnailScrollViewTrailingAnchor?.isActive = true + pdfThumbnailScrollViewWidthAnchor = pdfThumbnailScrollView.widthAnchor.constraint(equalToConstant: thumbnailViewWidth) + pdfThumbnailScrollViewWidthAnchor?.isActive = true + pdfThumbnailView.translatesAutoresizingMaskIntoConstraints = false pdfThumbnailView.pdfView = pdfView - pdfThumbnailView.layoutMode = .horizontal - pdfThumbnailView.thumbnailSize = CGSize(width: 40, height: thumbnailViewHeight) + pdfThumbnailView.layoutMode = .vertical + pdfThumbnailView.thumbnailSize = CGSize(width: thumbnailViewHeight, height: thumbnailViewHeight) pdfThumbnailView.backgroundColor = .clear - // pdfThumbnailView.layer.shadowOffset.height = -5 - // pdfThumbnailView.layer.shadowOpacity = 0.25 - - view.addSubview(pdfThumbnailView) - - pdfThumbnailView.heightAnchor.constraint(equalToConstant: thumbnailViewHeight).isActive = true - pdfThumbnailView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true - pdfThumbnailView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true - pdfThumbnailView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true + if UIDevice.current.userInterfaceIdiom == .phone { + self.pdfThumbnailScrollView.isHidden = true + } else { + self.pdfThumbnailScrollView.isHidden = false + } + pdfThumbnailScrollView.addSubview(pdfThumbnailView) + + NSLayoutConstraint.activate([ + pdfThumbnailView.topAnchor.constraint(equalTo: pdfThumbnailScrollView.topAnchor), + pdfThumbnailView.bottomAnchor.constraint(equalTo: pdfThumbnailScrollView.bottomAnchor), + pdfThumbnailView.leadingAnchor.constraint(equalTo: pdfThumbnailScrollView.leadingAnchor), + pdfThumbnailView.leadingAnchor.constraint(equalTo: pdfThumbnailScrollView.trailingAnchor, constant: (UIApplication.shared.keyWindow?.safeAreaInsets.left ?? 0)), + pdfThumbnailView.widthAnchor.constraint(equalToConstant: thumbnailViewWidth) + ]) + let contentViewCenterY = pdfThumbnailView.centerYAnchor.constraint(equalTo: pdfThumbnailScrollView.centerYAnchor) + contentViewCenterY.priority = .defaultLow + let contentViewHeight = pdfThumbnailView.heightAnchor.constraint(equalToConstant: CGFloat(pageCount * thumbnailViewHeight) + CGFloat(pageCount * thumbnailPadding) + 30) + contentViewHeight.priority = .defaultLow + NSLayoutConstraint.activate([ + contentViewCenterY, + contentViewHeight + ]) + + // COUNTER PDF PAGE VIEW pageView.translatesAutoresizingMaskIntoConstraints = false pageView.layer.cornerRadius = 10 pageView.backgroundColor = NCBrandColor.shared.systemBackground.withAlphaComponent( UIAccessibility.isReduceTransparencyEnabled ? 1 : 0.5 ) - view.addSubview(pageView) - pageView.heightAnchor.constraint(equalToConstant: 30).isActive = true + NSLayoutConstraint.activate([ + pageView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10), + pageView.heightAnchor.constraint(equalToConstant: 30), + pageView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 10) + ]) pageViewWidthAnchor = pageView.widthAnchor.constraint(equalToConstant: 10) pageViewWidthAnchor?.isActive = true - pageView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 4).isActive = true - pageView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 7).isActive = true pageViewLabel.translatesAutoresizingMaskIntoConstraints = false pageViewLabel.textAlignment = .center pageViewLabel.textColor = NCBrandColor.shared.label - pageView.addSubview(pageViewLabel) - pageViewLabel.leftAnchor.constraint(equalTo: pageView.leftAnchor).isActive = true - pageViewLabel.rightAnchor.constraint(equalTo: pageView.rightAnchor).isActive = true - pageViewLabel.topAnchor.constraint(equalTo: pageView.topAnchor).isActive = true - pageViewLabel.bottomAnchor.constraint(equalTo: pageView.bottomAnchor).isActive = true + NSLayoutConstraint.activate([ + pageViewLabel.topAnchor.constraint(equalTo: pageView.topAnchor), + pageViewLabel.leftAnchor.constraint(equalTo: pageView.leftAnchor), + pageViewLabel.rightAnchor.constraint(equalTo: pageView.rightAnchor), + pageViewLabel.bottomAnchor.constraint(equalTo: pageView.bottomAnchor) + ]) - pdfView.backgroundColor = NCBrandColor.shared.systemBackground - pdfView.layoutIfNeeded() - handlePageChange() + // GESTURE - let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTap(_:))) - tapGesture.numberOfTapsRequired = 1 - pdfView.addGestureRecognizer(tapGesture) + let tapPdfView = UITapGestureRecognizer(target: self, action: #selector(tapPdfView)) + tapPdfView.numberOfTapsRequired = 1 + pdfView.addGestureRecognizer(tapPdfView) // recognize single / double tap for gesture in pdfView.gestureRecognizers! { - tapGesture.require(toFail: gesture) + tapPdfView.require(toFail: gesture) } - } - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) + let swipePdfView = UISwipeGestureRecognizer(target: self, action: #selector(gestureClosePdfThumbnail)) + swipePdfView.direction = .right + pdfView.addGestureRecognizer(swipePdfView) - appDelegate.activeViewController = self + let swipePdfThumbnailScrollView = UISwipeGestureRecognizer(target: self, action: #selector(gestureClosePdfThumbnail)) + swipePdfThumbnailScrollView.direction = .right + pdfThumbnailScrollView.addGestureRecognizer(swipePdfThumbnailScrollView) + + let edgePdfView = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(gestureOpenPdfThumbnail)) + edgePdfView.edges = .right + pdfView.addGestureRecognizer(edgePdfView) + + let edgeView = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(gestureOpenPdfThumbnail)) + edgeView.edges = .right + view.addGestureRecognizer(edgeView) - // NotificationCenter.default.addObserver(self, selector: #selector(favoriteFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterFavoriteFile), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(deleteFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDeleteFile), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(renameFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterRenameFile), object: nil) @@ -130,19 +192,62 @@ class NCViewerPDF: UIViewController, NCViewerPDFSearchDelegate { NotificationCenter.default.addObserver(self, selector: #selector(viewUnload), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMenuDetailClose), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(searchText), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMenuSearchTextPDF), object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(direction(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMenuPDFDisplayDirection), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(goToPage), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMenuGotToPageInPDF), object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(handlePageChange), name: Notification.Name.PDFViewPageChanged, object: nil) - // - navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "more")!.image(color: NCBrandColor.shared.label, size: 25), style: .plain, target: self, action: #selector(self.openMenuMore)) + // Tip + if UIDevice.current.userInterfaceIdiom == .phone && !NCManageDatabase.shared.tipExists(NCGlobal.shared.tipNCViewerPDFThumbnail){ - navigationController?.navigationBar.prefersLargeTitles = true - navigationItem.title = metadata.fileNameView + var preferences = EasyTipView.Preferences() + preferences.drawing.foregroundColor = NCBrandColor.shared.brandText + preferences.drawing.backgroundColor = NCBrandColor.shared.customer + preferences.drawing.textAlignment = .left + preferences.drawing.arrowPosition = .right + preferences.drawing.cornerRadius = 10 + + preferences.positioning.bubbleInsets.right = UIApplication.shared.keyWindow?.safeAreaInsets.right ?? 0 + + preferences.animating.dismissTransform = CGAffineTransform(translationX: 0, y: 100) + preferences.animating.showInitialTransform = CGAffineTransform(translationX: 0, y: -100) + preferences.animating.showInitialAlpha = 0 + preferences.animating.showDuration = 1.5 + preferences.animating.dismissDuration = 1.5 + + tipView = EasyTipView(text: NSLocalizedString("_tip_pdf_thumbnails_", comment: ""), preferences: preferences, delegate: self) + } + + setConstraints() + handlePageChange() + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + self.tipView?.show(forView: self.pdfThumbnailScrollView, withinSuperview: self.view) } - override func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated) + @objc func viewUnload() { + + navigationController?.popViewController(animated: true) + } + + override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { + super.viewWillTransition(to: size, with: coordinator) + + coordinator.animate(alongsideTransition: { context in + if UIDevice.current.userInterfaceIdiom == .phone { + // Close + self.tipView?.dismiss() + self.pdfThumbnailScrollViewTrailingAnchor?.constant = self.thumbnailViewWidth + (UIApplication.shared.keyWindow?.safeAreaInsets.right ?? 0) + self.pdfThumbnailScrollView.isHidden = true + } + }, completion: { context in + self.setConstraints() + }) + } + + deinit { NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterFavoriteFile), object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDeleteFile), object: nil) @@ -152,17 +257,11 @@ class NCViewerPDF: UIViewController, NCViewerPDFSearchDelegate { NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMenuDetailClose), object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMenuSearchTextPDF), object: nil) - NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMenuPDFDisplayDirection), object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMenuGotToPageInPDF), object: nil) NotificationCenter.default.removeObserver(self, name: Notification.Name.PDFViewPageChanged, object: nil) } - @objc func viewUnload() { - - navigationController?.popViewController(animated: true) - } - // MARK: - NotificationCenter @objc func uploadedFile(_ notification: NSNotification) { @@ -236,17 +335,6 @@ class NCViewerPDF: UIViewController, NCViewerPDFSearchDelegate { self.present(navigaionController, animated: true) } - @objc func direction(_ notification: NSNotification) { - - if let userInfo = notification.userInfo as NSDictionary? { - if let direction = userInfo["direction"] as? PDFDisplayDirection { - pdfView.displayDirection = direction - CCUtility.setPDFDisplayDirection(direction) - handlePageChange() - } - } - } - @objc func goToPage() { guard let pdfDocument = pdfView.document else { return } @@ -272,45 +360,112 @@ class NCViewerPDF: UIViewController, NCViewerPDFSearchDelegate { // MARK: - Action @objc func openMenuMore() { + if imageIcon == nil { imageIcon = UIImage(named: "file_pdf") } NCViewer.shared.toggleMenu(viewController: self, metadata: metadata, webView: false, imageIcon: imageIcon) } // MARK: - Gesture Recognizer - @objc func didTap(_ recognizer: UITapGestureRecognizer) { + @objc func tapPdfView(_ recognizer: UITapGestureRecognizer) { - if navigationController?.isNavigationBarHidden ?? false { + pdfThumbnailScrollViewTopAnchor?.isActive = false - navigationController?.setNavigationBarHidden(false, animated: false) - pdfThumbnailView.isHidden = false - pdfView.backgroundColor = NCBrandColor.shared.systemBackground + if navigationController?.isNavigationBarHidden ?? false { + navigationController?.setNavigationBarHidden(false, animated: true) + pdfThumbnailScrollViewTopAnchor = pdfThumbnailScrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor) } else { + navigationController?.setNavigationBarHidden(true, animated: true) + pdfThumbnailScrollViewTopAnchor = pdfThumbnailScrollView.topAnchor.constraint(equalTo: view.topAnchor) + } + + pdfThumbnailScrollViewTopAnchor?.isActive = true + + handlePageChange() + } - let point = recognizer.location(in: pdfView) - if point.y > pdfView.frame.height - thumbnailViewHeight { return } + @objc func gestureOpenPdfThumbnail(_ recognizer: UIScreenEdgePanGestureRecognizer) { - navigationController?.setNavigationBarHidden(true, animated: false) - pdfThumbnailView.isHidden = true - pdfView.backgroundColor = .black + if UIDevice.current.userInterfaceIdiom == .phone && self.pdfThumbnailScrollView.isHidden { + if let tipView = self.tipView { + tipView.dismiss() + NCManageDatabase.shared.addTip(NCGlobal.shared.tipNCViewerPDFThumbnail) + self.tipView = nil + } + self.pdfThumbnailScrollView.isHidden = false + self.pdfThumbnailScrollViewWidthAnchor?.constant = thumbnailViewWidth + (UIApplication.shared.keyWindow?.safeAreaInsets.right ?? 0) + UIView.animate(withDuration: animateDuration, animations: { + self.pdfThumbnailScrollViewTrailingAnchor?.constant = 0 + self.view.layoutIfNeeded() + }) } + } - handlePageChange() + @objc func gestureClosePdfThumbnail(_ recognizer: UIScreenEdgePanGestureRecognizer) { + + if recognizer.state == .recognized && UIDevice.current.userInterfaceIdiom == .phone && !self.pdfThumbnailScrollView.isHidden { + UIView.animate(withDuration: animateDuration) { + self.pdfThumbnailScrollViewTrailingAnchor?.constant = self.thumbnailViewWidth + (UIApplication.shared.keyWindow?.safeAreaInsets.right ?? 0) + self.view.layoutIfNeeded() + } completion: { _ in + self.pdfThumbnailScrollView.isHidden = true + } + } } // MARK: - + func setConstraints() { + + let widthThumbnail = thumbnailViewWidth + (UIApplication.shared.keyWindow?.safeAreaInsets.right ?? 0) + + UIView.animate(withDuration: animateDuration, animations: { + if UIDevice.current.userInterfaceIdiom == .phone { + // Close + self.pdfThumbnailScrollView.isHidden = true + self.pdfThumbnailScrollViewTrailingAnchor?.constant = widthThumbnail + self.pdfThumbnailScrollViewWidthAnchor?.constant = widthThumbnail + } else { + // Open + self.pdfThumbnailScrollViewTrailingAnchor?.constant = 0 + self.pdfThumbnailScrollViewWidthAnchor?.constant = widthThumbnail + } + self.view.layoutIfNeeded() + self.pdfView.autoScales = true + }) + } + @objc func handlePageChange() { guard let curPage = pdfView.currentPage?.pageRef?.pageNumber else { pageView.alpha = 0; return } guard let totalPages = pdfView.document?.pageCount else { return } + let visibleRect = CGRect(x: pdfThumbnailScrollView.contentOffset.x, y: pdfThumbnailScrollView.contentOffset.y, width: pdfThumbnailScrollView.bounds.size.width, height: pdfThumbnailScrollView.bounds.size.height) + let centerPoint = CGPoint(x: visibleRect.size.width/2, y: visibleRect.size.height/2) + let currentPageY = CGFloat(curPage) * thumbnailViewHeight + CGFloat(curPage) * thumbnailPadding + var gotoY = currentPageY - centerPoint.y + + let startY = visibleRect.origin.y < 0 ? 0 : (visibleRect.origin.y + thumbnailViewHeight) + let endY = visibleRect.origin.y + visibleRect.height + + if currentPageY < startY { + if gotoY < 0 { gotoY = 0 } + pdfThumbnailScrollView.setContentOffset(CGPoint(x: 0, y: gotoY), animated: true) + } else if currentPageY > endY { + if gotoY > pdfThumbnailView.frame.height - visibleRect.height { + gotoY = pdfThumbnailView.frame.height - visibleRect.height + } + pdfThumbnailScrollView.setContentOffset(CGPoint(x: 0, y: gotoY), animated: true) + } else { + print("visible") + } + pageView.alpha = 1 pageViewLabel.text = String(curPage) + " " + NSLocalizedString("_of_", comment: "") + " " + String(totalPages) pageViewWidthAnchor?.constant = pageViewLabel.intrinsicContentSize.width + 10 - UIView.animate(withDuration: 1.0, delay: 3.0, animations: { + UIView.animate(withDuration: 1.0, delay: 2.5, animations: { self.pageView.alpha = 0 }) } @@ -341,3 +496,12 @@ class NCViewerPDF: UIViewController, NCViewerPDFSearchDelegate { } } } + +extension NCViewerPDF: EasyTipViewDelegate { + + func easyTipViewDidTap(_ tipView: EasyTipView) { + NCManageDatabase.shared.addTip(NCGlobal.shared.tipNCViewerPDFThumbnail) + } + + func easyTipViewDidDismiss(_ tipView: EasyTipView) { } +} |