diff options
author | Marino Faggiana <ios@nextcloud.com> | 2022-08-03 17:46:38 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-03 17:46:38 +0300 |
commit | bff743352374df7f7e6dedcdcdb7dfcb08f5e058 (patch) | |
tree | b0a623e7828505e1918e1a77fe3b220773166e6f /iOSClient | |
parent | f3e10a5cf4e0ee476dee185a8c95418b575dface (diff) | |
parent | 0b680554c1ebad0b2d1cac061b7c7e87e94443e5 (diff) |
Merge pull request #2101 from nextcloud/fix/441
Fix/441
Diffstat (limited to 'iOSClient')
21 files changed, 278 insertions, 296 deletions
diff --git a/iOSClient/AppDelegate.swift b/iOSClient/AppDelegate.swift index e051af989..fc1380fe7 100644 --- a/iOSClient/AppDelegate.swift +++ b/iOSClient/AppDelegate.swift @@ -42,11 +42,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD var deletePasswordSession: Bool = false var activeAppConfigView: NCAppConfigView? - var activeFiles: NCFiles? - var activeFileViewInFolder: NCFileViewInFolder? var activeLogin: NCLogin? var activeLoginWeb: NCLoginWeb? - @objc var activeMedia: NCMedia? var activeServerUrl: String = "" @objc var activeViewController: UIViewController? var mainTabBar: NCMainTabBar? @@ -868,7 +865,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD } DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { - NCFunctionCenter.shared.openFileViewInFolder(serverUrl: serverUrl, fileName: fileName) + NCFunctionCenter.shared.openFileViewInFolder(serverUrl: serverUrl, fileNameBlink: fileName) } } else { diff --git a/iOSClient/Extensions/UINavigationController+Extension.swift b/iOSClient/Extensions/UINavigationController+Extension.swift new file mode 100644 index 000000000..e0e987df6 --- /dev/null +++ b/iOSClient/Extensions/UINavigationController+Extension.swift @@ -0,0 +1,32 @@ +// +// UINavigationController+Extension.swift +// Nextcloud +// +// Created by Marino Faggiana on 02/08/2022. +// Copyright © 2022 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana <marino.faggiana@nextcloud.com> +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +import Foundation + +extension UINavigationController { + + // https://stackoverflow.com/questions/6131205/how-to-find-topmost-view-controller-on-ios + override func topMostViewController() -> UIViewController { + return self.visibleViewController!.topMostViewController() + } +} diff --git a/iOSClient/Extensions/UITabBarController+Extension.swift b/iOSClient/Extensions/UITabBarController+Extension.swift new file mode 100644 index 000000000..66e57c535 --- /dev/null +++ b/iOSClient/Extensions/UITabBarController+Extension.swift @@ -0,0 +1,32 @@ +// +// UITabBarController+Extension.swift +// Nextcloud +// +// Created by Marino Faggiana on 02/08/2022. +// Copyright © 2022 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana <marino.faggiana@nextcloud.com> +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +import Foundation + +extension UITabBarController { + + // https://stackoverflow.com/questions/6131205/how-to-find-topmost-view-controller-on-ios + override func topMostViewController() -> UIViewController { + return self.selectedViewController!.topMostViewController() + } +} diff --git a/iOSClient/Extensions/UIViewController+Extension.swift b/iOSClient/Extensions/UIViewController+Extension.swift new file mode 100644 index 000000000..172dccb03 --- /dev/null +++ b/iOSClient/Extensions/UIViewController+Extension.swift @@ -0,0 +1,64 @@ +// +// UIViewController+Extension.swift +// Nextcloud +// +// Created by Marino Faggiana on 02/08/2022. +// Copyright © 2022 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana <marino.faggiana@nextcloud.com> +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +import Foundation + +extension UIViewController { + + // https://stackoverflow.com/questions/6131205/how-to-find-topmost-view-controller-on-ios + @objc func topMostViewController() -> UIViewController { + // Handling Modal views + if let presentedViewController = self.presentedViewController { + return presentedViewController.topMostViewController() + } + // Handling UIViewController's added as subviews to some other views. + else { + for view in self.view.subviews { + // Key property which most of us are unaware of / rarely use. + if let subViewController = view.next { + if subViewController is UIViewController { + if let viewController = subViewController as? UIViewController { + return viewController.topMostViewController() + } + } + } + } + return self + } + } + + // https://stackoverflow.com/questions/23620276/how-to-check-if-a-view-controller-is-presented-modally-or-pushed-on-a-navigation + var isModal: Bool { + if let index = navigationController?.viewControllers.firstIndex(of: self), index > 0 { + return false + } else if presentingViewController != nil { + return true + } else if navigationController?.presentingViewController?.presentedViewController == navigationController { + return true + } else if tabBarController?.presentingViewController is UITabBarController { + return true + } else { + return false + } + } +} diff --git a/iOSClient/FileViewInFolder/NCFileViewInFolder.storyboard b/iOSClient/FileViewInFolder/NCFileViewInFolder.storyboard deleted file mode 100644 index 95d7bd36e..000000000 --- a/iOSClient/FileViewInFolder/NCFileViewInFolder.storyboard +++ /dev/null @@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="EFX-fO-Oip"> - <device id="retina5_9" orientation="portrait" appearance="light"/> - <dependencies> - <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17125"/> - <capability name="Safe area layout guides" minToolsVersion="9.0"/> - <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> - </dependencies> - <scenes> - <!--File View In Folder--> - <scene sceneID="X4W-6b-l7s"> - <objects> - <viewController storyboardIdentifier="NCFileViewInFolder.storyboard" extendedLayoutIncludesOpaqueBars="YES" id="EFX-fO-Oip" customClass="NCFileViewInFolder" customModule="Nextcloud" customModuleProvider="target" sceneMemberID="viewController"> - <view key="view" contentMode="scaleToFill" id="QEs-gO-Cmp"> - <rect key="frame" x="0.0" y="0.0" width="375" height="812"/> - <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <subviews> - <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="Zaz-Cl-qpZ"> - <rect key="frame" x="0.0" y="0.0" width="375" height="812"/> - <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> - <collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="0.0" minimumInteritemSpacing="0.0" id="fF1-wd-0xN"> - <size key="itemSize" width="0.0" height="0.0"/> - <size key="headerReferenceSize" width="0.0" height="0.0"/> - <size key="footerReferenceSize" width="0.0" height="0.0"/> - <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/> - </collectionViewFlowLayout> - <cells/> - <connections> - <outlet property="dataSource" destination="EFX-fO-Oip" id="2On-qP-zuG"/> - <outlet property="delegate" destination="EFX-fO-Oip" id="s3n-CL-8X2"/> - </connections> - </collectionView> - </subviews> - <viewLayoutGuide key="safeArea" id="Meh-VD-wWh"/> - <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> - <constraints> - <constraint firstItem="Zaz-Cl-qpZ" firstAttribute="leading" secondItem="Meh-VD-wWh" secondAttribute="leading" id="1bp-sm-u0X"/> - <constraint firstItem="Meh-VD-wWh" firstAttribute="trailing" secondItem="Zaz-Cl-qpZ" secondAttribute="trailing" id="aNd-UL-hmu"/> - <constraint firstItem="Meh-VD-wWh" firstAttribute="bottom" secondItem="Zaz-Cl-qpZ" secondAttribute="bottom" constant="-34" id="aNr-tf-2AH"/> - <constraint firstItem="Zaz-Cl-qpZ" firstAttribute="top" secondItem="QEs-gO-Cmp" secondAttribute="top" id="tji-wt-R7s"/> - </constraints> - </view> - <connections> - <outlet property="collectionView" destination="Zaz-Cl-qpZ" id="8oA-Gx-z7T"/> - </connections> - </viewController> - <placeholder placeholderIdentifier="IBFirstResponder" id="JJ0-Le-6eT" userLabel="First Responder" sceneMemberID="firstResponder"/> - </objects> - <point key="canvasLocation" x="256.80000000000001" y="228.32512315270938"/> - </scene> - </scenes> -</document> diff --git a/iOSClient/FileViewInFolder/NCFileViewInFolder.swift b/iOSClient/FileViewInFolder/NCFileViewInFolder.swift deleted file mode 100644 index fde4d488d..000000000 --- a/iOSClient/FileViewInFolder/NCFileViewInFolder.swift +++ /dev/null @@ -1,160 +0,0 @@ -// -// NCFileViewInFolder.swift -// Nextcloud -// -// Created by Marino Faggiana on 01/10/2020. -// Copyright © 2020 Marino Faggiana. All rights reserved. -// -// Author Marino Faggiana <marino.faggiana@nextcloud.com> -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -// - -import UIKit -import NCCommunication - -class NCFileViewInFolder: NCCollectionViewCommon { - - internal var fileName: String? - - // MARK: - View Life Cycle - - required init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - - appDelegate.activeFileViewInFolder = self - titleCurrentFolder = NCBrandOptions.shared.brand - layoutKey = NCGlobal.shared.layoutViewViewInFolder - enableSearchBar = false - headerMenuButtonsCommand = false - headerMenuButtonsView = true - headerRichWorkspaceDisable = true - emptyImage = UIImage(named: "folder")?.image(color: NCBrandColor.shared.brandElement, size: UIScreen.main.bounds.width) - emptyTitle = "_files_no_files_" - emptyDescription = "_no_file_pull_down_" - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - - appDelegate.activeViewController = self - - if serverUrl == NCUtilityFileSystem.shared.getHomeServer(account: appDelegate.account) { - self.navigationItem.title = NCBrandOptions.shared.brand - } else { - self.navigationItem.title = (serverUrl as NSString).lastPathComponent - } - - presentationController?.delegate = self - - layoutForView = NCUtility.shared.getLayoutForView(key: layoutKey, serverUrl: serverUrl) - gridLayout.itemForLine = CGFloat(layoutForView?.itemForLine ?? 3) - - if layoutForView?.layout == NCGlobal.shared.layoutList { - collectionView?.collectionViewLayout = listLayout - } else { - collectionView?.collectionViewLayout = gridLayout - } - - self.navigationItem.leftBarButtonItem = nil - self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_close_", comment: ""), style: .plain, target: self, action: #selector(tapClose(sender:))) - } - - // MARK: - TAP EVENT - - @objc func tapClose(sender: Any) { - dismiss(animated: true) - } - - // MARK: - DataSource + NC Endpoint - - override func reloadDataSource(forced: Bool = true) { - super.reloadDataSource() - - DispatchQueue.global().async { - let metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl)) - if self.metadataFolder == nil { - self.metadataFolder = NCManageDatabase.shared.getMetadataFolder(account: self.appDelegate.account, urlBase: self.appDelegate.urlBase, serverUrl: self.serverUrl) - } - - self.dataSource = NCDataSource(metadatas: metadatas, - account: self.appDelegate.account, - sort: self.layoutForView?.sort, - ascending: self.layoutForView?.ascending, - directoryOnTop: self.layoutForView?.directoryOnTop, - favoriteOnTop: true, - filterLivePhoto: true, - groupByField: self.groupByField, - providers: self.providers, - searchResults: self.searchResults) - - DispatchQueue.main.async { - self.refreshControl.endRefreshing() - self.collectionView.reloadData() - // Blink file - if self.fileName != nil { - if let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", self.appDelegate.account, self.serverUrl, self.fileName!)) { - let (indexPath, _) = self.dataSource.getIndexPathMetadata(ocId: metadata.ocId) - if let indexPath = indexPath { - DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { - UIView.animate(withDuration: 0.3) { - self.collectionView.scrollToItem(at: indexPath, at: .centeredVertically, animated: false) - } completion: { _ in - if let cell = self.collectionView.cellForItem(at: indexPath) { - cell.backgroundColor = .darkGray - UIView.animate(withDuration: 2) { - cell.backgroundColor = .clear - self.fileName = nil - } - } - } - } - } - } - } - } - } - } - - override func reloadDataSourceNetwork(forced: Bool = false) { - super.reloadDataSourceNetwork(forced: forced) - - if isSearching { - networkSearch() - return - } - - isReloadDataSourceNetworkInProgress = true - collectionView?.reloadData() - - networkReadFolder(forced: forced) { tableDirectory, metadatas, _, _, errorCode, _ in - if errorCode == 0 { - for metadata in metadatas ?? [] { - if !metadata.directory { - if NCManageDatabase.shared.isDownloadMetadata(metadata, download: false) { - NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorDownloadFile) - } - } - } - } - - DispatchQueue.main.async { - self.refreshControl.endRefreshing() - self.isReloadDataSourceNetworkInProgress = false - self.richWorkspaceText = tableDirectory?.richWorkspace - self.reloadDataSource() - } - } - } -} diff --git a/iOSClient/Files/NCFiles.swift b/iOSClient/Files/NCFiles.swift index 7dc2be74c..790f37d18 100644 --- a/iOSClient/Files/NCFiles.swift +++ b/iOSClient/Files/NCFiles.swift @@ -27,13 +27,13 @@ import NCCommunication class NCFiles: NCCollectionViewCommon { internal var isRoot: Bool = true + internal var fileNameBlink: String? // MARK: - View Life Cycle required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) - appDelegate.activeFiles = self titleCurrentFolder = NCBrandOptions.shared.brand layoutKey = NCGlobal.shared.layoutViewFiles enableSearchBar = true @@ -54,6 +54,12 @@ class NCFiles: NCCollectionViewCommon { super.viewWillAppear(animated) } + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + + fileNameBlink = nil + } + // MARK: - NotificationCenter override func initialize(_ notification: NSNotification) { @@ -76,6 +82,7 @@ class NCFiles: NCCollectionViewCommon { // // forced: do no make the etag of directory test (default) // + override func reloadDataSource(forced: Bool = true) { super.reloadDataSource() @@ -92,7 +99,7 @@ class NCFiles: NCCollectionViewCommon { self.richWorkspaceText = directory?.richWorkspace // FORCED false: test the directory.etag - if !forced, let directory = directory, directory.etag == self.dataSource.directory?.etag, metadataTransfer == nil { + if !forced, let directory = directory, directory.etag == self.dataSource.directory?.etag, metadataTransfer == nil, self.fileNameBlink == nil { return } @@ -109,7 +116,13 @@ class NCFiles: NCCollectionViewCommon { providers: self.providers, searchResults: self.searchResults) - DispatchQueue.main.async { self.collectionView.reloadData() } + DispatchQueue.main.async { + self.collectionView.reloadData() + if !self.dataSource.metadatas.isEmpty { + self.blinkCell(fileName: self.fileNameBlink) + self.fileNameBlink = nil + } + } } } @@ -136,7 +149,30 @@ class NCFiles: NCCollectionViewCommon { if metadatasUpdate?.count ?? 0 > 0 || metadatasDelete?.count ?? 0 > 0 || forced { self.reloadDataSource(forced: false) } else if self.dataSource.getMetadataSourceForAllSections().isEmpty { - DispatchQueue.main.async { self.collectionView.reloadData() } + DispatchQueue.main.async { + self.collectionView.reloadData() + } + } + } + } + + func blinkCell(fileName: String?) { + + if let fileName = fileName, let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", self.appDelegate.account, self.serverUrl, fileName)) { + let (indexPath, _) = self.dataSource.getIndexPathMetadata(ocId: metadata.ocId) + if let indexPath = indexPath { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { + UIView.animate(withDuration: 0.3) { + self.collectionView.scrollToItem(at: indexPath, at: .centeredVertically, animated: false) + } completion: { _ in + if let cell = self.collectionView.cellForItem(at: indexPath) { + cell.backgroundColor = .darkGray + UIView.animate(withDuration: 2) { + cell.backgroundColor = .clear + } + } + } + } } } } diff --git a/iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift b/iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift index 940389d16..c7835f016 100644 --- a/iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift +++ b/iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift @@ -63,6 +63,10 @@ class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate { super.viewWillAppear(animated) } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + } + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) } diff --git a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift index f5adadb27..c76d90dcc 100644 --- a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift +++ b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift @@ -883,7 +883,8 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS if let viewerRichWorkspace = navigationController.topViewController as? NCViewerRichWorkspace { viewerRichWorkspace.richWorkspaceText = richWorkspaceText ?? "" viewerRichWorkspace.serverUrl = serverUrl - + viewerRichWorkspace.delegate = self + navigationController.modalPresentationStyle = .fullScreen self.present(navigationController, animated: true, completion: nil) } @@ -1214,18 +1215,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS } } - // VIEW IN FOLDER - if layoutKey == NCGlobal.shared.layoutViewViewInFolder && !pushed { - - if let viewController: NCFileViewInFolder = UIStoryboard(name: "NCFileViewInFolder", bundle: nil).instantiateInitialViewController() as? NCFileViewInFolder { - - viewController.serverUrl = serverUrlPush - viewController.titleCurrentFolder = metadata.fileNameView - - pushViewController(viewController: viewController) - } - } - // SHARES ( for push use Files ... he he he ) if layoutKey == NCGlobal.shared.layoutViewShares && !pushed { @@ -1282,7 +1271,7 @@ extension NCCollectionViewCommon: UICollectionViewDelegate { pushMetadata(metadata) - } else if !(self is NCFileViewInFolder) { + } else { let imageIcon = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) diff --git a/iOSClient/Main/NCFunctionCenter.swift b/iOSClient/Main/NCFunctionCenter.swift index bf67cdda1..9c5551305 100644 --- a/iOSClient/Main/NCFunctionCenter.swift +++ b/iOSClient/Main/NCFunctionCenter.swift @@ -454,49 +454,58 @@ import Photos // MARK: - - func openFileViewInFolder(serverUrl: String, fileName: String) { + func openFileViewInFolder(serverUrl: String, fileNameBlink: String?) { - let viewController = UIStoryboard(name: "NCFileViewInFolder", bundle: nil).instantiateInitialViewController() as! NCFileViewInFolder - let navigationController = UINavigationController(rootViewController: viewController) + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { + var topNavigationController: UINavigationController? + var pushServerUrl = NCUtilityFileSystem.shared.getHomeServer(account: self.appDelegate.account) + var mostViewController = UIApplication.shared.keyWindow!.rootViewController!.topMostViewController() - let topViewController = viewController - var listViewController = [NCFileViewInFolder]() - var serverUrl = serverUrl - let homeUrl = NCUtilityFileSystem.shared.getHomeServer(account: appDelegate.account) - - while true { + if mostViewController.isModal { + mostViewController.dismiss(animated: false) + mostViewController = UIApplication.shared.keyWindow!.rootViewController!.topMostViewController() + } + mostViewController.navigationController?.popToRootViewController(animated: false) - var viewController: NCFileViewInFolder? - if serverUrl != homeUrl { - viewController = UIStoryboard(name: "NCFileViewInFolder", bundle: nil).instantiateInitialViewController() as? NCFileViewInFolder - if viewController == nil { - return + if let tabBarController = self.appDelegate.window?.rootViewController as? UITabBarController { + tabBarController.selectedIndex = 0 + if let navigationController = tabBarController.viewControllers?.first as? UINavigationController { + navigationController.popToRootViewController(animated: false) + topNavigationController = navigationController } - viewController!.titleCurrentFolder = (serverUrl as NSString).lastPathComponent - } else { - viewController = topViewController } - guard let vc = viewController else { return } + if pushServerUrl == serverUrl { + let viewController = topNavigationController?.topViewController as? NCFiles + viewController?.blinkCell(fileName: fileNameBlink) + return + } + guard let topNavigationController = topNavigationController else { return } - vc.serverUrl = serverUrl - vc.fileName = fileName + let diffDirectory = serverUrl.replacingOccurrences(of: pushServerUrl, with: "") + var subDirs = diffDirectory.split(separator: "/") - vc.navigationItem.backButtonTitle = vc.titleCurrentFolder - listViewController.insert(vc, at: 0) + while pushServerUrl != serverUrl, subDirs.count > 0 { - if serverUrl != homeUrl { - serverUrl = NCUtilityFileSystem.shared.deletingLastPathComponent(account: appDelegate.account, serverUrl: serverUrl) - } else { - break - } - } + guard let dir = subDirs.first, let viewController = UIStoryboard(name: "NCFiles", bundle: nil).instantiateInitialViewController() as? NCFiles else { return } + pushServerUrl = pushServerUrl + "/" + dir - navigationController.setViewControllers(listViewController, animated: false) - navigationController.modalPresentationStyle = .formSheet + viewController.serverUrl = pushServerUrl + viewController.isRoot = false + viewController.titleCurrentFolder = String(dir) + if pushServerUrl == serverUrl { + viewController.fileNameBlink = fileNameBlink + } + self.appDelegate.listFilesVC[serverUrl] = viewController - appDelegate.window?.rootViewController?.present(navigationController, animated: true, completion: nil) + viewController.navigationItem.backButtonTitle = viewController.titleCurrentFolder + topNavigationController.pushViewController(viewController, animated: false) + + subDirs.remove(at: 0) + } + } } + // MARK: - NCSelect + Delegate func dismissSelect(serverUrl: String?, metadata: tableMetadata?, type: String, items: [Any], overwrite: Bool, copy: Bool, move: Bool) { @@ -633,7 +642,7 @@ import Photos } let viewInFolder = UIAction(title: NSLocalizedString("_view_in_folder_", comment: ""), image: UIImage(systemName: "arrow.forward.square")) { _ in - self.openFileViewInFolder(serverUrl: metadata.serverUrl, fileName: metadata.fileName) + self.openFileViewInFolder(serverUrl: metadata.serverUrl, fileNameBlink: metadata.fileName) } let openIn = UIAction(title: NSLocalizedString("_open_in_", comment: ""), image: UIImage(systemName: "square.and.arrow.up") ) { _ in diff --git a/iOSClient/Main/Section Header Footer/NCSectionFooter.xib b/iOSClient/Main/Section Header Footer/NCSectionFooter.xib index 86d9bb416..296af0fb7 100644 --- a/iOSClient/Main/Section Header Footer/NCSectionFooter.xib +++ b/iOSClient/Main/Section Header Footer/NCSectionFooter.xib @@ -29,7 +29,7 @@ <action selector="touchUpInsideButton:" destination="Vin-9E-7nW" eventType="touchUpInside" id="XSh-0v-WHJ"/> </connections> </button> - <activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="qWG-SR-Qly"> + <activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" style="medium" translatesAutoresizingMaskIntoConstraints="NO" id="qWG-SR-Qly"> <rect key="frame" x="177.5" y="5" width="20" height="20"/> </activityIndicatorView> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="s2m-yO-4x0" userLabel="separator"> diff --git a/iOSClient/Media/NCMedia.swift b/iOSClient/Media/NCMedia.swift index 92fd31896..d486e32df 100644 --- a/iOSClient/Media/NCMedia.swift +++ b/iOSClient/Media/NCMedia.swift @@ -71,8 +71,6 @@ class NCMedia: UIViewController, NCEmptyDataSetDelegate, NCSelectDelegate { override func viewDidLoad() { super.viewDidLoad() - appDelegate.activeMedia = self - view.backgroundColor = NCBrandColor.shared.systemBackground collectionView.register(UINib(nibName: "NCGridMediaCell", bundle: nil), forCellWithReuseIdentifier: "gridCell") diff --git a/iOSClient/Menu/NCCollectionViewCommon+Menu.swift b/iOSClient/Menu/NCCollectionViewCommon+Menu.swift index 6410c3888..9339cd17c 100644 --- a/iOSClient/Menu/NCCollectionViewCommon+Menu.swift +++ b/iOSClient/Menu/NCCollectionViewCommon+Menu.swift @@ -281,13 +281,7 @@ extension NCCollectionViewCommon { title: NSLocalizedString("_modify_", comment: ""), icon: NCUtility.shared.loadImage(named: "pencil.tip.crop.circle"), action: { menuAction in - if self is NCFileViewInFolder { - self.dismiss(animated: true) { - NCFunctionCenter.shared.openDownload(metadata: metadata, selector: NCGlobal.shared.selectorLoadFileQuickLook) - } - } else { - NCFunctionCenter.shared.openDownload(metadata: metadata, selector: NCGlobal.shared.selectorLoadFileQuickLook) - } + NCFunctionCenter.shared.openDownload(metadata: metadata, selector: NCGlobal.shared.selectorLoadFileQuickLook) } ) ) diff --git a/iOSClient/Menu/NCMenuAction.swift b/iOSClient/Menu/NCMenuAction.swift index 6aff1a224..66543d53e 100644 --- a/iOSClient/Menu/NCMenuAction.swift +++ b/iOSClient/Menu/NCMenuAction.swift @@ -154,13 +154,7 @@ extension NCMenuAction { title: NSLocalizedString("_open_in_", comment: ""), icon: NCUtility.shared.loadImage(named: "square.and.arrow.up"), action: { _ in - if viewController is NCFileViewInFolder { - viewController.dismiss(animated: true) { - NCFunctionCenter.shared.openActivityViewController(selectedMetadata: selectedMetadatas) - } - } else { - NCFunctionCenter.shared.openActivityViewController(selectedMetadata: selectedMetadatas) - } + NCFunctionCenter.shared.openActivityViewController(selectedMetadata: selectedMetadatas) completion?() } ) diff --git a/iOSClient/Menu/NCViewer+Menu.swift b/iOSClient/Menu/NCViewer+Menu.swift index 5b18d6a6f..160d9fef1 100644 --- a/iOSClient/Menu/NCViewer+Menu.swift +++ b/iOSClient/Menu/NCViewer+Menu.swift @@ -192,7 +192,7 @@ extension NCViewer { title: NSLocalizedString("_view_in_folder_", comment: ""), icon: NCUtility.shared.loadImage(named: "arrow.forward.square"), action: { menuAction in - NCFunctionCenter.shared.openFileViewInFolder(serverUrl: metadata.serverUrl, fileName: metadata.fileName) + NCFunctionCenter.shared.openFileViewInFolder(serverUrl: metadata.serverUrl, fileNameBlink: metadata.fileName) } ) ) diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift index 1aae7d4fb..180a3edb1 100644 --- a/iOSClient/NCGlobal.swift +++ b/iOSClient/NCGlobal.swift @@ -373,4 +373,5 @@ class NCGlobal: NSObject { let tipNCViewerPDFThumbnail = "tipncviewerpdfthumbnail" let tipNCCollectionViewCommonAccountRequest = "tipnccollectionviewcommonaccountrequest" let tipNCScanAddImage = "tipncscanaddimage" + let tipNCViewerMediaDetailView = "tipncviewermediadetailview" } diff --git a/iOSClient/RichWorkspace/NCViewerRichWorkspace.swift b/iOSClient/RichWorkspace/NCViewerRichWorkspace.swift index fa4d104dc..652005b76 100644 --- a/iOSClient/RichWorkspace/NCViewerRichWorkspace.swift +++ b/iOSClient/RichWorkspace/NCViewerRichWorkspace.swift @@ -34,8 +34,9 @@ import MarkdownKit private var markdownParser = MarkdownParser() private var textViewColor: UIColor? - @objc public var richWorkspaceText: String = "" - @objc public var serverUrl: String = "" + var richWorkspaceText: String = "" + var serverUrl: String = "" + var delegate: NCCollectionViewCommon? // MARK: - View Life Cycle @@ -66,7 +67,7 @@ import MarkdownKit guard let metadata = metadata else { return } NCManageDatabase.shared.setDirectory(serverUrl: self.serverUrl, richWorkspace: metadata.richWorkspace, account: account) if self.richWorkspaceText != metadata.richWorkspace && metadata.richWorkspace != nil { - self.appDelegate.activeFiles?.richWorkspaceText = self.richWorkspaceText + self.delegate?.richWorkspaceText = self.richWorkspaceText self.richWorkspaceText = metadata.richWorkspace! DispatchQueue.main.async { self.textView.attributedText = self.markdownParser.parse(metadata.richWorkspace!) diff --git a/iOSClient/Settings/CCAdvanced.m b/iOSClient/Settings/CCAdvanced.m index b0bfc5352..a32c5f827 100755 --- a/iOSClient/Settings/CCAdvanced.m +++ b/iOSClient/Settings/CCAdvanced.m @@ -403,9 +403,6 @@ // Inizialized home [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:NCGlobal.shared.notificationCenterInitialize object:nil userInfo:nil]; - // Clear Media - [appDelegate.activeMedia reloadDataSourceWithCompletion:^(NSArray *metadatas) { }]; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void) { [[NCUtility shared] stopActivityIndicator]; [self calculateSize]; diff --git a/iOSClient/Supporting Files/en.lproj/Localizable.strings b/iOSClient/Supporting Files/en.lproj/Localizable.strings index 96e4aea8c..24f78a4c5 100644 --- a/iOSClient/Supporting Files/en.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/en.lproj/Localizable.strings @@ -903,6 +903,7 @@ "_tip_pdf_thumbnails_" = "Swipe left from the right edge of the screen to show the thumbnails."; "_tip_accountrequest_" = "Touch here to change account or to add a new one"; "_tip_addcopyimage_" = "Long press to paste a copied image"; +"_tip_open_mediadetail_" = "Swipe up to show the details"; // MARK: Accessibility diff --git a/iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift b/iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift index e4a13be55..5374ab823 100644 --- a/iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift +++ b/iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift @@ -24,6 +24,8 @@ import UIKit import SVGKit import NCCommunication +import EasyTipView +import SwiftUI class NCViewerMedia: UIViewController { @@ -38,6 +40,7 @@ class NCViewerMedia: UIViewController { @IBOutlet weak var detailView: NCViewerMediaDetailView! private var _autoPlay: Bool = false + private var tipView: EasyTipView? let appDelegate = UIApplication.shared.delegate as! AppDelegate weak var viewerMediaPage: NCViewerMediaPage? @@ -73,6 +76,7 @@ class NCViewerMedia: UIViewController { deinit { print("deinit NCViewerMedia") + self.tipView?.dismiss() NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterOpenMediaDetail), object: nil) } @@ -111,7 +115,23 @@ class NCViewerMedia: UIViewController { self.ncplayer = NCPlayer.init(url: url, autoPlay: self.autoPlay, isProxy: urlVideo.isProxy, imageVideoContainer: self.imageVideoContainer, playerToolBar: self.playerToolBar, metadata: self.metadata, detailView: self.detailView, viewController: self) } } - + + // TIP + var preferences = EasyTipView.Preferences() + preferences.drawing.foregroundColor = .white + preferences.drawing.backgroundColor = NCBrandColor.shared.nextcloud + preferences.drawing.textAlignment = .left + preferences.drawing.arrowPosition = .top + preferences.drawing.cornerRadius = 10 + + preferences.animating.dismissTransform = CGAffineTransform(translationX: 0, y: 100) + preferences.animating.showInitialTransform = CGAffineTransform(translationX: 0, y: -100) + preferences.animating.showInitialAlpha = 0 + preferences.animating.showDuration = 0.5 + preferences.animating.dismissDuration = 0 + + tipView = EasyTipView(text: NSLocalizedString("_tip_open_mediadetail_", comment: ""), preferences: preferences, delegate: self) + detailViewTopConstraint.constant = 0 detailView.hide() @@ -172,16 +192,25 @@ class NCViewerMedia: UIViewController { viewerMediaPage?.clearCommandCenter() } + // TIP + if !NCManageDatabase.shared.tipExists(NCGlobal.shared.tipNCViewerMediaDetailView), let view = self.navigationController?.navigationBar { + self.tipView?.show(forView: view) + } + NotificationCenter.default.addObserver(self, selector: #selector(openDetail(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterOpenMediaDetail), object: nil) } - override func viewDidDisappear(_ animated: Bool) { - super.viewDidDisappear(animated) + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + + self.tipView?.dismiss() } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) + self.tipView?.dismiss() + coordinator.animate(alongsideTransition: { context in // back to the original size self.scrollView.zoom(to: CGRect(x: 0, y: 0, width: self.scrollView.bounds.width, height: self.scrollView.bounds.height), animated: false) @@ -423,6 +452,8 @@ extension NCViewerMedia { private func openDetail() { + self.dismissTip() + CCUtility.setExif(metadata) { latitude, longitude, location, date, lensModel in if latitude != -1 && latitude != 0 && longitude != -1 && longitude != 0 { @@ -539,6 +570,21 @@ extension NCViewerMedia: NCViewerMediaDetailViewDelegate { } } +extension NCViewerMedia: EasyTipViewDelegate { + + // TIP + func easyTipViewDidTap(_ tipView: EasyTipView) { + NCManageDatabase.shared.addTip(NCGlobal.shared.tipNCViewerMediaDetailView) + } + + func easyTipViewDidDismiss(_ tipView: EasyTipView) { } + + func dismissTip() { + NCManageDatabase.shared.addTip(NCGlobal.shared.tipNCViewerMediaDetailView) + self.tipView?.dismiss() + } +} + // MARK: - class imageVideoContainerView: UIImageView { diff --git a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.storyboard b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.storyboard index 329daf6cc..a9377104d 100644 --- a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.storyboard +++ b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.storyboard @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="ne8-hS-cp3"> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="ne8-hS-cp3"> <device id="retina5_5" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/> <capability name="Safe area layout guides" minToolsVersion="9.0"/> <capability name="System colors in document resources" minToolsVersion="11.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> |