marinofaggiana 4 years ago
parent
commit
535430e119

+ 4 - 0
Nextcloud.xcodeproj/project.pbxproj

@@ -211,6 +211,7 @@
 		F787704F22E7019900F287A9 /* NCShareLinkCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F787704E22E7019900F287A9 /* NCShareLinkCell.xib */; };
 		F78A18B623CDD07D00F681F3 /* NCViewerRichWorkspaceWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78A18B523CDD07D00F681F3 /* NCViewerRichWorkspaceWebView.swift */; };
 		F78A18B823CDE2B300F681F3 /* NCViewerRichWorkspace.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78A18B723CDE2B300F681F3 /* NCViewerRichWorkspace.swift */; };
+		F78A807A25095B3D006D2193 /* NCOffline+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78A807925095B3C006D2193 /* NCOffline+Menu.swift */; };
 		F78AA20621F783E900D0F205 /* SwiftRichString.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F78AA20521F783E900D0F205 /* SwiftRichString.framework */; };
 		F78ACD4021903CC20088454D /* NCGridCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD3F21903CC20088454D /* NCGridCell.swift */; };
 		F78ACD4221903CE00088454D /* NCListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD4121903CE00088454D /* NCListCell.swift */; };
@@ -561,6 +562,7 @@
 		F787704E22E7019900F287A9 /* NCShareLinkCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCShareLinkCell.xib; sourceTree = "<group>"; };
 		F78A18B523CDD07D00F681F3 /* NCViewerRichWorkspaceWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCViewerRichWorkspaceWebView.swift; sourceTree = "<group>"; };
 		F78A18B723CDE2B300F681F3 /* NCViewerRichWorkspace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCViewerRichWorkspace.swift; sourceTree = "<group>"; };
+		F78A807925095B3C006D2193 /* NCOffline+Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCOffline+Menu.swift"; sourceTree = "<group>"; };
 		F78AA20521F783E900D0F205 /* SwiftRichString.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftRichString.framework; path = Carthage/Build/iOS/SwiftRichString.framework; sourceTree = "<group>"; };
 		F78ACD3F21903CC20088454D /* NCGridCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCGridCell.swift; sourceTree = "<group>"; };
 		F78ACD4121903CE00088454D /* NCListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCListCell.swift; sourceTree = "<group>"; };
@@ -796,6 +798,7 @@
 			children = (
 				3781B9AF23DB2B7E006B4B1D /* AppDelegate+Menu.swift */,
 				3781B9B323DB2BC9006B4B1D /* NCFavorite+Menu.swift */,
+				F78A807925095B3C006D2193 /* NCOffline+Menu.swift */,
 				3781B9B123DB2B9F006B4B1D /* CCMain+Menu.swift */,
 				F7CBC31B24F78E79004D3812 /* NCSortMenu.swift */,
 				F710D2012405826100A6033D /* NCDetailNavigationController+Menu.swift */,
@@ -2080,6 +2083,7 @@
 				F7BAADCB1ED5A87C00B7EAD4 /* NCManageDatabase.swift in Sources */,
 				F79018B9240962C7007C9B6D /* NCViewerImageContentTransformers.swift in Sources */,
 				F70968A424212C4E00ED60E5 /* NCLivePhoto.swift in Sources */,
+				F78A807A25095B3D006D2193 /* NCOffline+Menu.swift in Sources */,
 				F704FA5C232A343F00BBA952 /* IMImagemeterViewer.swift in Sources */,
 				370D26B1248A3E1A00121797 /* CCCellMain.swift in Sources */,
 				F7CA1ED220E7E3FE002CC65E /* PKCircleView.m in Sources */,

+ 18 - 469
iOSClient/Favorites/NCFavorite.swift

@@ -23,297 +23,35 @@
 
 import Foundation
 
-class NCFavorite: UIViewController, UIGestureRecognizerDelegate, NCListCellDelegate, NCGridCellDelegate, NCSectionHeaderMenuDelegate, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate  {
+class NCFavorite: NCCollectionViewCommon  {
     
-    @IBOutlet weak var collectionView: UICollectionView!
-
-    var titleCurrentFolder = NSLocalizedString("_favorites_", comment: "")
-    @objc var serverUrl = ""
-    
-    private let appDelegate = UIApplication.shared.delegate as! AppDelegate
-   
-    private var metadataPush: tableMetadata?
-    private var isEditMode = false
-    private var selectocId: [String] = []
-    
-    private var dataSource: NCDataSource?
-    
-    private var layout = ""
-    private var groupBy = ""
-    private var titleButton = ""
-    private var itemForLine = 0
-
-    private var autoUploadFileName = ""
-    private var autoUploadDirectory = ""
-    
-    private var listLayout: NCListLayout!
-    private var gridLayout: NCGridLayout!
-        
-    private let headerMenuHeight: CGFloat = 50
-    private let sectionHeaderHeight: CGFloat = 20
-    private let footerHeight: CGFloat = 50
-    
-    private let refreshControl = UIRefreshControl()
-
     required init?(coder aDecoder: NSCoder) {
         super.init(coder: aDecoder)
         
         appDelegate.activeFavorite = self
-    }
-    
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        
-        // Cell
-        collectionView.register(UINib.init(nibName: "NCListCell", bundle: nil), forCellWithReuseIdentifier: "listCell")
-        collectionView.register(UINib.init(nibName: "NCGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell")
-        
-        // Header
-        collectionView.register(UINib.init(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu")
-        collectionView.register(UINib.init(nibName: "NCSectionHeader", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeader")
-        
-        // Footer
-        collectionView.register(UINib.init(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter")
-        
-        collectionView.alwaysBounceVertical = true
-
-        listLayout = NCListLayout()
-        gridLayout = NCGridLayout()
-        
-        // Refresh Control
-        collectionView.addSubview(refreshControl)
-        refreshControl.tintColor = NCBrandColor.sharedInstance.brandText
-        refreshControl.backgroundColor = NCBrandColor.sharedInstance.brandElement
-        refreshControl.addTarget(self, action: #selector(reloadDataSourceNetwork), for: .valueChanged)
-        
-        // empty Data Source
-        self.collectionView.emptyDataSetDelegate = self
-        self.collectionView.emptyDataSetSource = self
-        
-        // 3D Touch peek and pop
-        if traitCollection.forceTouchCapability == .available {
-            registerForPreviewing(with: self, sourceView: view)
-        }
-        
-        NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: k_notificationCenter_changeTheming), object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSource), name: NSNotification.Name(rawValue: k_notificationCenter_reloadDataSource), object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(deleteFile(_:)), name: NSNotification.Name(rawValue: k_notificationCenter_deleteFile), object: nil)
-        
-        NotificationCenter.default.addObserver(self, selector: #selector(downloadStartFile(_:)), name: NSNotification.Name(rawValue: k_notificationCenter_downloadStartFile), object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(downloadedFile(_:)), name: NSNotification.Name(rawValue: k_notificationCenter_downloadedFile), object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(downloadCancelFile(_:)), name: NSNotification.Name(rawValue: k_notificationCenter_downloadCancelFile), object: nil)
-
-        NotificationCenter.default.addObserver(self, selector: #selector(uploadStartFile(_:)), name: NSNotification.Name(rawValue: k_notificationCenter_uploadStartFile), object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(uploadedFile(_:)), name: NSNotification.Name(rawValue: k_notificationCenter_uploadedFile), object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(uploadCancelFile(_:)), name: NSNotification.Name(rawValue: k_notificationCenter_uploadCancelFile), object: nil)
-
-        NotificationCenter.default.addObserver(self, selector: #selector(triggerProgressTask(_:)), name: NSNotification.Name(rawValue: k_notificationCenter_progressTask), object:nil)
-
-        changeTheming()
-    }
-    
-    override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-
-        self.navigationItem.title = titleCurrentFolder
-                
-        // get auto upload folder
-        autoUploadFileName = NCManageDatabase.sharedInstance.getAccountAutoUploadFileName()
-        autoUploadDirectory = NCManageDatabase.sharedInstance.getAccountAutoUploadDirectory(urlBase: appDelegate.urlBase, account: appDelegate.account)
-        
-        (layout, _, _, groupBy, _, titleButton, itemForLine) = NCUtility.shared.getLayoutForView(key: k_layout_view_favorite)
-        gridLayout.itemForLine = CGFloat(itemForLine)
-        
-        if layout == k_layout_list {
-            collectionView?.collectionViewLayout = listLayout
-        } else {
-            collectionView?.collectionViewLayout = gridLayout
-        }
-        
-        reloadDataSource()
-    }
-    
-    override func viewDidAppear(_ animated: Bool) {
-        super.viewDidAppear(animated)
-        
-        reloadDataSourceNetwork()
-    }
-    
-    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
-        super.viewWillTransition(to: size, with: coordinator)
-        
-        coordinator.animate(alongsideTransition: nil) { _ in
-            self.collectionView?.collectionViewLayout.invalidateLayout()
-        }
-    }
-    
-    // MARK: - NotificationCenter
-
-    @objc func changeTheming() {
-        appDelegate.changeTheming(self, tableView: nil, collectionView: collectionView, form: false)
-    }
-    
-    @objc func deleteFile(_ notification: NSNotification) {
-        if self.view?.window == nil { return }
-        
-        if let userInfo = notification.userInfo as NSDictionary? {
-            if let metadata = userInfo["metadata"] as? tableMetadata, let onlyLocal = userInfo["onlyLocal"] as? Bool, let errorCode = userInfo["errorCode"] as? Int, let errorDescription = userInfo["errorDescription"] as? String {
-                NCCollectionCommon.shared.notificationDeleteFile(collectionView: collectionView, dataSource: dataSource, metadata: metadata, errorCode: errorCode, errorDescription: errorDescription, onlyLocal: onlyLocal)
-            }
-        }
-    }
-    
-    @objc func downloadStartFile(_ notification: NSNotification) {
-        if self.view?.window == nil { return }
-        
-        if let userInfo = notification.userInfo as NSDictionary? {
-            if let metadata = userInfo["metadata"] as? tableMetadata {
-                NCCollectionCommon.shared.notificationDownloadStartFile(collectionView: collectionView, dataSource: dataSource, metadata: metadata)
-            }
-        }
-    }
-    
-    @objc func downloadedFile(_ notification: NSNotification) {
-        if self.view?.window == nil { return }
-        
-        if let userInfo = notification.userInfo as NSDictionary? {
-            if let metadata = userInfo["metadata"] as? tableMetadata, let _ = userInfo["errorCode"] as? Int {
-                NCCollectionCommon.shared.notificationDownloadedFile(collectionView: collectionView, dataSource: dataSource, metadata: metadata)
-            }
-        }
-    }
-    
-    @objc func downloadCancelFile(_ notification: NSNotification) {
-        if self.view?.window == nil { return }
-        
-        if let userInfo = notification.userInfo as NSDictionary? {
-            if let metadata = userInfo["metadata"] as? tableMetadata {
-                NCCollectionCommon.shared.notificationDownloadCancelFile(collectionView: collectionView, dataSource: dataSource, metadata: metadata)
-            }
-        }
-    }
-    
-    @objc func uploadStartFile(_ notification: NSNotification) {
-        if self.view?.window == nil { return }
-        
-        if let userInfo = notification.userInfo as NSDictionary? {
-            if let metadata = userInfo["metadata"] as? tableMetadata {
-                NCCollectionCommon.shared.notificationUploadStartFile(collectionView: collectionView, dataSource: dataSource, metadata: metadata, serverUrl: serverUrl, account: appDelegate.account)
-            }
-        }
-    }
-    
-    @objc func uploadedFile(_ notification: NSNotification) {
-        if self.view?.window == nil { return }
-        
-        if let userInfo = notification.userInfo as NSDictionary? {
-            if let metadata = userInfo["metadata"] as? tableMetadata, let ocIdTemp = userInfo["ocIdTemp"] as? String, let _ = userInfo["errorCode"] as? Int {
-                NCCollectionCommon.shared.notificationUploadedFile(collectionView: collectionView, dataSource: dataSource, metadata: metadata, ocIdTemp:ocIdTemp, serverUrl: serverUrl, account: appDelegate.account)
-            }
-        }
-    }
-    
-    @objc func uploadCancelFile(_ notification: NSNotification) {
-        if self.view?.window == nil { return }
-        
-        if let userInfo = notification.userInfo as NSDictionary? {
-            if let metadata = userInfo["metadata"] as? tableMetadata {
-                NCCollectionCommon.shared.notificationUploadCancelFile(collectionView: collectionView, dataSource: dataSource, metadata: metadata, serverUrl: serverUrl, account: appDelegate.account)
-            }
-        }
-    }
-    
-    @objc func triggerProgressTask(_ notification: NSNotification) {
-        if self.view?.window == nil { return }
-        
-        if let userInfo = notification.userInfo as NSDictionary? {
-            if let ocId = userInfo["ocId"] as? String {
-                let progressNumber = userInfo["progress"] as? NSNumber ?? 0
-                let progress = progressNumber.floatValue
-                NCCollectionCommon.shared.notificationTriggerProgressTask(collectionView: collectionView, dataSource: dataSource, ocId: ocId, progress: progress)
-            }
-        }
+        titleCurrentFolder = NSLocalizedString("_favorites_", comment: "")
+        layoutKey = k_layout_view_favorite
     }
     
     // MARK: DZNEmpty
-    
-    func backgroundColor(forEmptyDataSet scrollView: UIScrollView) -> UIColor? {
-        return NCBrandColor.sharedInstance.backgroundView
-    }
-    
-    func image(forEmptyDataSet scrollView: UIScrollView) -> UIImage? {
+        
+    override func image(forEmptyDataSet scrollView: UIScrollView) -> UIImage? {
         return CCGraphics.changeThemingColorImage(UIImage.init(named: "favorite"), width: 300, height: 300, color: NCBrandColor.sharedInstance.yellowFavorite)
     }
     
-    func title(forEmptyDataSet scrollView: UIScrollView) -> NSAttributedString? {
+    override func title(forEmptyDataSet scrollView: UIScrollView) -> NSAttributedString? {
         let text = "\n"+NSLocalizedString("_favorite_no_files_", comment: "")
         let attributes = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 20), NSAttributedString.Key.foregroundColor: UIColor.lightGray]
         return NSAttributedString.init(string: text, attributes: attributes)
     }
     
-    func description(forEmptyDataSet scrollView: UIScrollView!) -> NSAttributedString! {
+    override func description(forEmptyDataSet scrollView: UIScrollView!) -> NSAttributedString! {
         let text = "\n"+NSLocalizedString("_tutorial_favorite_view_", comment: "")
         let attributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14), NSAttributedString.Key.foregroundColor: UIColor.lightGray]
         return NSAttributedString.init(string: text, attributes: attributes)
     }
-    
-    func emptyDataSetShouldAllowScroll(_ scrollView: UIScrollView) -> Bool {
-        return true
-    }
-    
-    // MARK: TAP EVENT
-    
-    func tapSwitchHeader(sender: Any) {
-        
-        if collectionView.collectionViewLayout == gridLayout {
-            // list layout
-            UIView.animate(withDuration: 0.0, animations: {
-                self.collectionView.collectionViewLayout.invalidateLayout()
-                self.collectionView.setCollectionViewLayout(self.listLayout, animated: false, completion: { (_) in
-                    self.collectionView.reloadData()
-                    self.collectionView.setContentOffset(CGPoint(x:0,y:0), animated: false)
-                })
-            })
-            layout = k_layout_list
-            NCUtility.shared.setLayoutForView(key: k_layout_view_favorite, layout: layout)
-        } else {
-            // grid layout
-            UIView.animate(withDuration: 0.0, animations: {
-                self.collectionView.collectionViewLayout.invalidateLayout()
-                self.collectionView.setCollectionViewLayout(self.gridLayout, animated: false, completion: { (_) in
-                    self.collectionView.reloadData()
-                    self.collectionView.setContentOffset(CGPoint(x:0,y:0), animated: false)
-                })
-            })
-            layout = k_layout_grid
-            NCUtility.shared.setLayoutForView(key: k_layout_view_favorite, layout: layout)
-        }
-    }
-    
-    func tapOrderHeader(sender: Any) {
-        
-        let sortMenu = NCSortMenu()
-        sortMenu.toggleMenu(viewController: self, key: k_layout_view_favorite, sortButton: sender as? UIButton, serverUrl: serverUrl)
-    }
-    
-    func tapMoreHeader(sender: Any) {
-        
-    }
-    
-    func tapMoreListItem(with objectId: String, namedButtonMore: String, sender: Any) {
-        tapMoreGridItem(with: objectId, namedButtonMore: namedButtonMore, sender: sender)
-    }
-    
-    func tapShareListItem(with objectId: String, sender: Any) {
-        
-        guard let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "ocId == %@", objectId)) else {
-            return
-        }
-        
-        NCMainCommon.shared.openShare(ViewController: self, metadata: metadata, indexPage: 2)
-    }
-    
-    func tapMoreGridItem(with objectId: String, namedButtonMore: String, sender: Any) {
+
+    override func tapMoreGridItem(with objectId: String, namedButtonMore: String, sender: Any) {
         
         guard let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "ocId == %@", objectId)) else { return }
         guard let tabBarController = self.tabBarController else { return }
@@ -325,74 +63,9 @@ class NCFavorite: UIViewController, UIGestureRecognizerDelegate, NCListCellDeleg
         }
     }
     
-    // MARK: SEGUE
-    
-    @objc func segue(metadata: tableMetadata) {
-        self.metadataPush = metadata
-        performSegue(withIdentifier: "segueDetail", sender: self)
-    }
-    
-    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
-        
-        let photoDataSource: NSMutableArray = []
-        
-        for metadata in (dataSource?.metadatas ?? [tableMetadata]()) {
-            if metadata.typeFile == k_metadataTypeFile_image || metadata.typeFile == k_metadataTypeFile_video {
-                photoDataSource.add(metadata)
-            }
-        }
-        
-        if let segueNavigationController = segue.destination as? UINavigationController {
-            if let segueViewController = segueNavigationController.topViewController as? NCDetailViewController {
-                segueViewController.metadata = metadataPush
-            }
-        }
-    }
-}
-
-// MARK: - 3D Touch peek and pop
-
-extension NCFavorite: UIViewControllerPreviewingDelegate {
-    
-    func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
-        
-        guard let point = collectionView?.convert(location, from: collectionView?.superview) else { return nil }
-        guard let indexPath = collectionView?.indexPathForItem(at: point) else { return nil }
-        guard let metadata = dataSource?.cellForItemAt(indexPath: indexPath) else { return nil }
-        guard let viewController = UIStoryboard(name: "CCPeekPop", bundle: nil).instantiateViewController(withIdentifier: "PeekPopImagePreview") as? CCPeekPop else { return nil }
-
-        viewController.metadata = metadata
-
-        if layout == k_layout_grid {
-            guard let cell = collectionView?.cellForItem(at: indexPath) as? NCGridCell else { return nil }
-            previewingContext.sourceRect = cell.frame
-            viewController.imageFile = cell.imageItem.image
-        } else {
-            guard let cell = collectionView?.cellForItem(at: indexPath) as? NCListCell else { return nil }
-            previewingContext.sourceRect = cell.frame
-            viewController.imageFile = cell.imageItem.image
-        }
-        
-        viewController.showOpenIn = true
-        viewController.showOpenQuickLook = NCUtility.shared.isQuickLookDisplayable(metadata: metadata)
-        viewController.showShare = false
-        
-        return viewController
-    }
+    // MARK: - Collection View
     
-    func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
-        
-        guard let indexPath = collectionView?.indexPathForItem(at: previewingContext.sourceRect.origin) else { return }
-        
-        collectionView(collectionView, didSelectItemAt: indexPath)
-    }
-}
-
-// MARK: - Collection View
-
-extension NCFavorite: UICollectionViewDelegate {
-
-    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
+    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
         
         guard let metadata = dataSource?.cellForItemAt(indexPath: indexPath) else { return }
         metadataPush = metadata
@@ -426,141 +99,16 @@ extension NCFavorite: UICollectionViewDelegate {
             }
         }
     }
-}
-
-extension NCFavorite: UICollectionViewDataSource {
-
-    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
-        
-        if (indexPath.section == 0) {
-            
-            if kind == UICollectionView.elementKindSectionHeader {
-                
-                let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionHeaderMenu", for: indexPath) as! NCSectionHeaderMenu
-                
-                if collectionView.collectionViewLayout == gridLayout {
-                    header.buttonSwitch.setImage(CCGraphics.changeThemingColorImage(UIImage.init(named: "switchList"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), for: .normal)
-                } else {
-                    header.buttonSwitch.setImage(CCGraphics.changeThemingColorImage(UIImage.init(named: "switchGrid"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), for: .normal)
-                }
-                
-                header.delegate = self
-                header.backgroundColor = NCBrandColor.sharedInstance.backgroundView
-                header.separator.backgroundColor = NCBrandColor.sharedInstance.separator
-                header.setStatusButton(count: dataSource?.metadatas.count ?? 0)
-                header.setTitleSorted(datasourceTitleButton: titleButton)
-                
-                if groupBy == "none" {
-                    header.labelSection.isHidden = true
-                    header.labelSectionHeightConstraint.constant = 0
-                } else {
-                    header.labelSection.isHidden = false
-                    header.setTitleLabel(title: "")
-                    header.labelSectionHeightConstraint.constant = sectionHeaderHeight
-                }
-                
-                return header
-                
-            } else {
-                
-                let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as! NCSectionFooter
-                
-                let info = dataSource?.getFilesInformation()
-                footer.setTitleLabel(directories: info?.directories ?? 0, files: info?.files ?? 0, size: info?.size ?? 0)
-                
-                return footer
-            }
-            
-        } else {
-            
-            if kind == UICollectionView.elementKindSectionHeader {
-                
-                let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionHeader", for: indexPath) as! NCSectionHeader
-                
-                header.setTitleLabel(title: "")
-                
-                return header
-                
-            } else {
-                
-                let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as! NCSectionFooter
-                
-                let info = dataSource?.getFilesInformation()
-                footer.setTitleLabel(directories: info?.directories ?? 0, files: info?.files ?? 0, size: info?.size ?? 0)
-                
-                return footer
-            }
-        }
-    }
-    
-    func numberOfSections(in collectionView: UICollectionView) -> Int {
-        return dataSource?.sections ?? 1
-    }
     
-    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-        return dataSource?.numberOfItemsInSection(section: section) ?? 1
-    }
+    // MARK: - NC API & Algorithm
     
-    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
-        
-        let cell: UICollectionViewCell
-        
-        guard let metadata = dataSource?.cellForItemAt(indexPath: indexPath) else {
-            return collectionView.dequeueReusableCell(withReuseIdentifier: "listCell", for: indexPath) as! NCListCell
-        }
-        
-        if layout == k_layout_grid {
-            
-            cell = collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as! NCGridCell
-           
-        } else {
-            
-            cell = collectionView.dequeueReusableCell(withReuseIdentifier: "listCell", for: indexPath) as! NCListCell
-        }
-        
-        let shares = NCManageDatabase.sharedInstance.getTableShares(account: metadata.account, serverUrl: metadata.serverUrl, fileName: metadata.fileName)
-        
-        NCCollectionCommon.shared.cellForItemAt(indexPath: indexPath, collectionView: collectionView, cell: cell, metadata: metadata, metadataFolder: nil, serverUrl: metadata.serverUrl, isEditMode: isEditMode, selectocId: selectocId, autoUploadFileName: autoUploadFileName, autoUploadDirectory: autoUploadDirectory, hideButtonMore: false, downloadThumbnail: true, shares: shares, source: self)
-        
-        return cell
-    }
-}
-
-extension NCFavorite: UICollectionViewDelegateFlowLayout {
-
-    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
-        if section == 0 {
-            if groupBy == "none" {
-                return CGSize(width: collectionView.frame.width, height: headerMenuHeight)
-            } else {
-                return CGSize(width: collectionView.frame.width, height: headerMenuHeight + sectionHeaderHeight)
-            }
-        } else {
-            return CGSize(width: collectionView.frame.width, height: sectionHeaderHeight)
-        }
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
-        let sections = dataSource?.sections ?? 1
-        if (section == sections - 1) {
-            return CGSize(width: collectionView.frame.width, height: footerHeight)
-        } else {
-            return CGSize(width: collectionView.frame.width, height: 0)
-        }
-    }
-}
-
-// MARK: - NC API & Algorithm
-
-extension NCFavorite {
-
-    @objc func reloadDataSource() {
+    override func reloadDataSource() {
         
         var sort: String
         var ascending: Bool
         var directoryOnTop: Bool
         
-        (layout, sort, ascending, groupBy, directoryOnTop, titleButton, itemForLine) = NCUtility.shared.getLayoutForView(key: k_layout_view_favorite)
+        (layout, sort, ascending, groupBy, directoryOnTop, titleButton, itemForLine) = NCUtility.shared.getLayoutForView(key: layoutKey)
         
         if serverUrl == "" {
             
@@ -577,8 +125,8 @@ extension NCFavorite {
         collectionView.reloadData()
     }
     
-    @objc func reloadDataSourceNetwork() {
-        
+    override func reloadDataSourceNetwork() {
+     
         if serverUrl == "" {
             
             NCNetworking.shared.listingFavoritescompletion(selector: selectorListingFavorite) { (account, metadatas, errorCode, errorDescription) in
@@ -600,7 +148,7 @@ extension NCFavorite {
             NCNetworking.shared.readFolder(serverUrl: serverUrl, account: appDelegate.account) { (account, metadataFolder, metadatas, metadatasUpdate, metadatasLocalUpdate, errorCode, errorDescription) in
                 if errorCode == 0 {
                     for metadata in metadatas ?? [] {
-                        if !metadata.directory && CCUtility.getFavoriteOffline() {                            
+                        if !metadata.directory && CCUtility.getFavoriteOffline() {
                             let localFile = NCManageDatabase.sharedInstance.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
                             if localFile == nil || localFile?.etag != metadata.etag {
                                 NCOperationQueue.shared.download(metadata: metadata, selector: selectorDownloadFile, setFavorite: false)
@@ -613,3 +161,4 @@ extension NCFavorite {
         }
     }
 }
+

+ 101 - 0
iOSClient/Main/Menu/NCOffline+Menu.swift

@@ -0,0 +1,101 @@
+//
+//  NCOffline+Menu.swift
+//  Nextcloud
+//
+//  Created by Philippe Weidmann on 24.01.20.
+//  Copyright © 2020 Philippe Weidmann. All rights reserved.
+//  Copyright © 2020 Marino Faggiana All rights reserved.
+//
+//  Author Philippe Weidmann
+//  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 FloatingPanel
+
+extension NCOffline {
+
+    func toggleMoreMenu(viewController: UIViewController, metadata: tableMetadata) {
+        
+        if let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) {
+            
+            let mainMenuViewController = UIStoryboard.init(name: "NCMenu", bundle: nil).instantiateViewController(withIdentifier: "NCMainMenuTableViewController") as! NCMainMenuTableViewController
+            mainMenuViewController.actions = self.initMoreMenu(metadata: metadata, viewController: viewController)
+
+            let menuPanelController = NCMenuPanelController()
+            menuPanelController.parentPresenter = viewController
+            menuPanelController.delegate = mainMenuViewController
+            menuPanelController.set(contentViewController: mainMenuViewController)
+            menuPanelController.track(scrollView: mainMenuViewController.tableView)
+
+            viewController.present(menuPanelController, animated: true, completion: nil)
+        }
+    }
+    
+    private func initMoreMenu(metadata: tableMetadata, viewController: UIViewController) -> [NCMenuAction] {
+        var actions = [NCMenuAction]()
+        let appDelegate = UIApplication.shared.delegate as! AppDelegate
+        let isFolderEncrypted = CCUtility.isFolderEncrypted(metadata.serverUrl+"/"+metadata.fileName, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase)
+        
+        var iconHeader: UIImage!
+        if let icon = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) {
+            iconHeader = icon
+        } else {
+            if metadata.directory {
+                iconHeader = CCGraphics.changeThemingColorImage(UIImage(named: "folder"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon)
+            } else {
+                iconHeader = UIImage(named: metadata.iconName)
+            }
+        }
+
+        actions.append(
+            NCMenuAction(
+                title: metadata.fileNameView,
+                icon: iconHeader,
+                action: nil
+            )
+        )
+
+        if self.serverUrl == "" {
+            actions.append(
+                NCMenuAction(
+                    title: NSLocalizedString("_remove_available_offline_", comment: ""),
+                    icon: CCGraphics.changeThemingColorImage(UIImage(named: "offline"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon),
+                    action: { menuAction in
+                        if metadata.directory {
+                            NCManageDatabase.sharedInstance.setDirectory(serverUrl: CCUtility.stringAppendServerUrl(metadata.serverUrl, addFileName: metadata.fileName)!, offline: false, account: self.appDelegate.account)
+                        } else {
+                            NCManageDatabase.sharedInstance.setLocalFile(ocId: metadata.ocId, offline: false)
+                        }
+                        self.reloadDataSource()
+                    }
+                )
+            )
+        }
+        
+        actions.append(
+            NCMenuAction(
+                title: NSLocalizedString("_details_", comment: ""),
+                icon: CCGraphics.changeThemingColorImage(UIImage(named: "details"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon),
+                action: { menuAction in
+                    NCMainCommon.shared.openShare(ViewController: self, metadata: metadata, indexPage: 0)
+                }
+            )
+        )
+
+        return actions
+    }
+}
+

+ 19 - 79
iOSClient/Main/NCCollectionCommon.swift

@@ -554,18 +554,18 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, NCL
 
     @objc var serverUrl = ""
         
-    private let appDelegate = UIApplication.shared.delegate as! AppDelegate
+    let appDelegate = UIApplication.shared.delegate as! AppDelegate
        
-    private var metadataPush: tableMetadata?
-    private var isEditMode = false
-    private var selectocId: [String] = []
+    internal var metadataPush: tableMetadata?
+    internal var isEditMode = false
+    internal var selectocId: [String] = []
         
-    private var dataSource: NCDataSource?
+    internal var dataSource: NCDataSource?
         
-    private var layout = ""
-    private var groupBy = ""
-    private var titleButton = ""
-    private var itemForLine = 0
+    internal var layout = ""
+    internal var groupBy = ""
+    internal var titleButton = ""
+    internal var itemForLine = 0
 
     private var autoUploadFileName = ""
     private var autoUploadDirectory = ""
@@ -577,11 +577,11 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, NCL
     private let sectionHeaderHeight: CGFloat = 20
     private let footerHeight: CGFloat = 50
         
-    private let refreshControl = UIRefreshControl()
+    internal let refreshControl = UIRefreshControl()
     
     // DECLARE
-    var layoutKey = ""
-    var titleCurrentFolder = NSLocalizedString("_favorites_", comment: "")
+    internal var layoutKey = ""
+    internal var titleCurrentFolder = ""
     
     required init?(coder aDecoder: NSCoder) {
         super.init(coder: aDecoder)
@@ -672,7 +672,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, NCL
             self.collectionView?.collectionViewLayout.invalidateLayout()
         }
     }
-        
+    
     // MARK: - NotificationCenter
 
     @objc func changeTheming() {
@@ -769,21 +769,14 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, NCL
     
     func image(forEmptyDataSet scrollView: UIScrollView) -> UIImage? {
         return nil
-        //return CCGraphics.changeThemingColorImage(UIImage.init(named: "favorite"), width: 300, height: 300, color: NCBrandColor.sharedInstance.yellowFavorite)
     }
     
     func title(forEmptyDataSet scrollView: UIScrollView) -> NSAttributedString? {
         return nil
-//        let text = "\n"+NSLocalizedString("_favorite_no_files_", comment: "")
-//        let attributes = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 20), NSAttributedString.Key.foregroundColor: UIColor.lightGray]
-//        return NSAttributedString.init(string: text, attributes: attributes)
     }
     
     func description(forEmptyDataSet scrollView: UIScrollView!) -> NSAttributedString! {
         return nil
-//        let text = "\n"+NSLocalizedString("_tutorial_favorite_view_", comment: "")
-//        let attributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14), NSAttributedString.Key.foregroundColor: UIColor.lightGray]
-//        return NSAttributedString.init(string: text, attributes: attributes)
     }
     
     func emptyDataSetShouldAllowScroll(_ scrollView: UIScrollView) -> Bool {
@@ -844,16 +837,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, NCL
         
     func tapMoreGridItem(with objectId: String, namedButtonMore: String, sender: Any) {
         
-        guard let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "ocId == %@", objectId)) else { return }
-        guard let tabBarController = self.tabBarController else { return }
-
-        /*
-        if namedButtonMore == "more" {
-            toggleMoreMenu(viewController: tabBarController, metadata: metadata)
-        } else if namedButtonMore == "stop" {
-            NCMainCommon.shared.cancelTransferMetadata(metadata, uploadStatusForcedStart: false)
-        }
-        */
     }
     
     // MARK: SEGUE
@@ -879,6 +862,11 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, NCL
             }
         }
     }
+    
+    // MARK: - NC API & Algorithm
+    
+    @objc func reloadDataSource() { }
+    @objc func reloadDataSourceNetwork() { }
 }
 
 // MARK: - 3D Touch peek and pop
@@ -920,45 +908,9 @@ extension NCCollectionViewCommon: UIViewControllerPreviewingDelegate {
 }
 
 // MARK: - Collection View
-
 extension NCCollectionViewCommon: UICollectionViewDelegate {
 
-    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-        
-        guard let metadata = dataSource?.cellForItemAt(indexPath: indexPath) else { return }
-        metadataPush = metadata
-        
-        if isEditMode {
-            if let index = selectocId.firstIndex(of: metadata.ocId) {
-                selectocId.remove(at: index)
-            } else {
-                selectocId.append(metadata.ocId)
-            }
-            collectionView.reloadItems(at: [indexPath])
-            return
-        }
-        
-        /*
-        if metadata.directory {
-            
-            guard let serverUrlPush = CCUtility.stringAppendServerUrl(metadataPush!.serverUrl, addFileName: metadataPush!.fileName) else { return }
-            let ncFavorite:NCFavorite = UIStoryboard(name: "NCFavorite", bundle: nil).instantiateInitialViewController() as! NCFavorite
-            
-            ncFavorite.serverUrl = serverUrlPush
-            ncFavorite.titleCurrentFolder = metadataPush!.fileNameView
-            
-            self.navigationController?.pushViewController(ncFavorite, animated: true)
-            
-        } else {
-            
-            if CCUtility.fileProviderStorageExists(metadataPush?.ocId, fileNameView: metadataPush?.fileNameView) {
-                performSegue(withIdentifier: "segueDetail", sender: self)
-            } else {
-                NCNetworking.shared.download(metadata: metadataPush!, selector: selectorLoadFileViewFavorite) { (_) in }
-            }
-        }
-        */
-    }
+    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { }
 }
 
 extension NCCollectionViewCommon: UICollectionViewDataSource {
@@ -1082,15 +1034,3 @@ extension NCCollectionViewCommon: UICollectionViewDelegateFlowLayout {
         }
     }
 }
-
-// MARK: - NC API & Algorithm
-
-extension NCCollectionViewCommon {
-
-    @objc func reloadDataSource() {
-    }
-    
-    @objc func reloadDataSourceNetwork() {
-    }
-}
-

+ 70 - 563
iOSClient/Offline/NCOffline.swift

@@ -23,366 +23,37 @@
 
 import Foundation
 
-class NCOffline: UIViewController, UIGestureRecognizerDelegate, NCListCellDelegate, NCGridCellDelegate, NCSectionHeaderMenuDelegate, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate  {
-    
-    @IBOutlet weak var collectionView: UICollectionView!
-
-    var titleCurrentFolder = NSLocalizedString("_manage_file_offline_", comment: "")
-    var serverUrl = ""
-    
-    private let appDelegate = UIApplication.shared.delegate as! AppDelegate
-   
-    private var metadataPush: tableMetadata?
-    private var isEditMode = false
-    private var selectocId: [String] = []
-    
-    private var dataSource: NCDataSource?
-
-    private var layout = ""
-    private var groupBy = ""
-    private var titleButton = ""
-    private var itemForLine = 0
-
-    private var autoUploadFileName = ""
-    private var autoUploadDirectory = ""
-    
-    private var listLayout: NCListLayout!
-    private var gridLayout: NCGridLayout!
-        
-    private let headerMenuHeight: CGFloat = 50
-    private let sectionHeaderHeight: CGFloat = 20
-    private let footerHeight: CGFloat = 50
-
-    private let refreshControl = UIRefreshControl()    
+class NCOffline: NCCollectionViewCommon  {
     
     required init?(coder aDecoder: NSCoder) {
         super.init(coder: aDecoder)
         
         appDelegate.activeOffline = self
-    }
-    
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        
-        // Cell
-        collectionView.register(UINib.init(nibName: "NCListCell", bundle: nil), forCellWithReuseIdentifier: "listCell")
-        collectionView.register(UINib.init(nibName: "NCGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell")
-        
-        // Header
-        collectionView.register(UINib.init(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu")
-        collectionView.register(UINib.init(nibName: "NCSectionHeader", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeader")
-        
-        // Footer
-        collectionView.register(UINib.init(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter")
-        
-        collectionView.alwaysBounceVertical = true
-
-        listLayout = NCListLayout()
-        gridLayout = NCGridLayout()
-        
-        // Refresh Control
-        collectionView.addSubview(refreshControl)
-        refreshControl.tintColor = NCBrandColor.sharedInstance.brandText
-        refreshControl.backgroundColor = NCBrandColor.sharedInstance.brandElement
-        refreshControl.addTarget(self, action: #selector(reloadDataSourceNetwork), for: .valueChanged)
-        
-        // empty Data Source
-        self.collectionView.emptyDataSetDelegate = self
-        self.collectionView.emptyDataSetSource = self
-        
-        // 3D Touch peek and pop
-        if traitCollection.forceTouchCapability == .available {
-            registerForPreviewing(with: self, sourceView: view)
-        }
-        
-        NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: k_notificationCenter_changeTheming), object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(deleteFile(_:)), name: NSNotification.Name(rawValue: k_notificationCenter_deleteFile), object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSource), name: NSNotification.Name(rawValue: k_notificationCenter_reloadDataSource), object: nil)
-        
-        NotificationCenter.default.addObserver(self, selector: #selector(downloadStartFile(_:)), name: NSNotification.Name(rawValue: k_notificationCenter_downloadStartFile), object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(downloadedFile(_:)), name: NSNotification.Name(rawValue: k_notificationCenter_downloadedFile), object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(downloadCancelFile(_:)), name: NSNotification.Name(rawValue: k_notificationCenter_downloadCancelFile), object: nil)
-
-        NotificationCenter.default.addObserver(self, selector: #selector(uploadStartFile(_:)), name: NSNotification.Name(rawValue: k_notificationCenter_uploadStartFile), object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(uploadedFile(_:)), name: NSNotification.Name(rawValue: k_notificationCenter_uploadedFile), object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(uploadCancelFile(_:)), name: NSNotification.Name(rawValue: k_notificationCenter_uploadCancelFile), object: nil)
-
-        NotificationCenter.default.addObserver(self, selector: #selector(triggerProgressTask(_:)), name: NSNotification.Name(rawValue: k_notificationCenter_progressTask), object:nil)
-        
-        changeTheming()
-    }
-    
-    override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-
-        self.navigationItem.title = titleCurrentFolder
-                
-        // get auto upload folder
-        autoUploadFileName = NCManageDatabase.sharedInstance.getAccountAutoUploadFileName()
-        autoUploadDirectory = NCManageDatabase.sharedInstance.getAccountAutoUploadDirectory(urlBase: appDelegate.urlBase, account: appDelegate.account)
-        
-        (layout, _, _, groupBy, _, titleButton, itemForLine) = NCUtility.shared.getLayoutForView(key: k_layout_view_offline)
-        gridLayout.itemForLine = CGFloat(itemForLine)
-        
-        if layout == k_layout_list {
-            collectionView.collectionViewLayout = listLayout
-        } else {
-            collectionView.collectionViewLayout = gridLayout
-        }
-        
-        reloadDataSource()
-    }
-    
-    override func viewDidAppear(_ animated: Bool) {
-        super.viewDidAppear(animated)
-        
-        reloadDataSourceNetwork()
-    }
-    
-    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
-        super.viewWillTransition(to: size, with: coordinator)
-        
-        coordinator.animate(alongsideTransition: nil) { _ in
-            self.collectionView?.collectionViewLayout.invalidateLayout()
-        }
-    }
-    
-    //MARK: - NotificationCenter
-
-    @objc func changeTheming() {
-        appDelegate.changeTheming(self, tableView: nil, collectionView: collectionView, form: false)
-    }
-    
-    @objc func deleteFile(_ notification: NSNotification) {
-        if self.view?.window == nil { return }
-        
-        if let userInfo = notification.userInfo as NSDictionary? {
-            if let metadata = userInfo["metadata"] as? tableMetadata, let errorCode = userInfo["errorCode"] as? Int, let errorDescription = userInfo["errorDescription"] as? String {
-                NCCollectionCommon.shared.notificationDeleteFile(collectionView: collectionView, dataSource: dataSource, metadata: metadata, errorCode: errorCode, errorDescription: errorDescription, onlyLocal: false)
-            }
-        }
-    }
-    
-    @objc func downloadStartFile(_ notification: NSNotification) {
-        if self.view?.window == nil { return }
-        
-        if let userInfo = notification.userInfo as NSDictionary? {
-            if let metadata = userInfo["metadata"] as? tableMetadata {
-                NCCollectionCommon.shared.notificationDownloadStartFile(collectionView: collectionView, dataSource: dataSource, metadata: metadata)
-            }
-        }
-    }
-    
-    @objc func downloadedFile(_ notification: NSNotification) {
-        if self.view?.window == nil { return }
-        
-        if let userInfo = notification.userInfo as NSDictionary? {
-            if let metadata = userInfo["metadata"] as? tableMetadata, let _ = userInfo["errorCode"] as? Int {
-                NCCollectionCommon.shared.notificationDownloadedFile(collectionView: collectionView, dataSource: dataSource, metadata: metadata)
-            }
-        }
-    }
-    
-    @objc func downloadCancelFile(_ notification: NSNotification) {
-        if self.view?.window == nil { return }
-        
-        if let userInfo = notification.userInfo as NSDictionary? {
-            if let metadata = userInfo["metadata"] as? tableMetadata {
-                NCCollectionCommon.shared.notificationDownloadCancelFile(collectionView: collectionView, dataSource: dataSource, metadata: metadata)
-            }
-        }
-    }
-    
-    @objc func uploadStartFile(_ notification: NSNotification) {
-        if self.view?.window == nil { return }
-        
-        if let userInfo = notification.userInfo as NSDictionary? {
-            if let metadata = userInfo["metadata"] as? tableMetadata {
-                NCCollectionCommon.shared.notificationUploadStartFile(collectionView: collectionView, dataSource: dataSource, metadata: metadata, serverUrl: serverUrl, account: appDelegate.account)
-            }
-        }
-    }
-    
-    @objc func uploadedFile(_ notification: NSNotification) {
-        if self.view?.window == nil { return }
-        
-        if let userInfo = notification.userInfo as NSDictionary? {
-            if let metadata = userInfo["metadata"] as? tableMetadata, let ocIdTemp = userInfo["ocIdTemp"] as? String, let _ = userInfo["errorCode"] as? Int {
-                NCCollectionCommon.shared.notificationUploadedFile(collectionView: collectionView, dataSource: dataSource, metadata: metadata, ocIdTemp:ocIdTemp, serverUrl: serverUrl, account: appDelegate.account)
-            }
-        }
-    }
-    
-    @objc func uploadCancelFile(_ notification: NSNotification) {
-        if self.view?.window == nil { return }
-        
-        if let userInfo = notification.userInfo as NSDictionary? {
-            if let metadata = userInfo["metadata"] as? tableMetadata {
-                NCCollectionCommon.shared.notificationUploadCancelFile(collectionView: collectionView, dataSource: dataSource, metadata: metadata, serverUrl: serverUrl, account: appDelegate.account)
-            }
-        }
-    }
-    
-    @objc func triggerProgressTask(_ notification: NSNotification) {
-        if self.view?.window == nil { return }
-        
-        if let userInfo = notification.userInfo as NSDictionary? {
-            if let ocId = userInfo["ocId"] as? String {
-                let progressNumber = userInfo["progress"] as? NSNumber ?? 0
-                let progress = progressNumber.floatValue
-                NCCollectionCommon.shared.notificationTriggerProgressTask(collectionView: collectionView, dataSource: dataSource, ocId: ocId, progress: progress)
-            }
-        }
+        titleCurrentFolder = NSLocalizedString("_manage_file_offline_", comment: "")
+        layoutKey = k_layout_view_offline
     }
     
     // MARK: DZNEmpty
     
-    func backgroundColor(forEmptyDataSet scrollView: UIScrollView) -> UIColor? {
-        return NCBrandColor.sharedInstance.backgroundView
-    }
-    
-    func image(forEmptyDataSet scrollView: UIScrollView) -> UIImage? {
+    override func image(forEmptyDataSet scrollView: UIScrollView) -> UIImage? {
         return CCGraphics.changeThemingColorImage(UIImage.init(named: "folder"), width: 300, height: 300, color: NCBrandColor.sharedInstance.brandElement)
     }
     
-    func title(forEmptyDataSet scrollView: UIScrollView) -> NSAttributedString? {
+    override func title(forEmptyDataSet scrollView: UIScrollView) -> NSAttributedString? {
         let text = "\n"+NSLocalizedString("_files_no_files_", comment: "")
         let attributes = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 20), NSAttributedString.Key.foregroundColor: UIColor.lightGray]
         return NSAttributedString.init(string: text, attributes: attributes)
     }
-    
-    func emptyDataSetShouldAllowScroll(_ scrollView: UIScrollView) -> Bool {
-        return true
-    }
-    
-    // MARK: TAP EVENT
-    
-    func tapSwitchHeader(sender: Any) {
-        
-        if collectionView.collectionViewLayout == gridLayout {
-            // list layout
-            UIView.animate(withDuration: 0.0, animations: {
-                self.collectionView.collectionViewLayout.invalidateLayout()
-                self.collectionView.setCollectionViewLayout(self.listLayout, animated: false, completion: { (_) in
-                    self.collectionView.reloadData()
-                    self.collectionView.setContentOffset(CGPoint(x:0,y:0), animated: false)
-                })
-            })
-            layout = k_layout_list
-            NCUtility.shared.setLayoutForView(key: k_layout_view_offline, layout: layout)
-        } else {
-            // grid layout
-            UIView.animate(withDuration: 0.0, animations: {
-                self.collectionView.collectionViewLayout.invalidateLayout()
-                self.collectionView.setCollectionViewLayout(self.gridLayout, animated: false, completion: { (_) in
-                    self.collectionView.reloadData()
-                    self.collectionView.setContentOffset(CGPoint(x:0,y:0), animated: false)
-                })
-            })
-            layout = k_layout_grid
-            NCUtility.shared.setLayoutForView(key: k_layout_view_offline, layout: layout)
-        }
-    }
-    
-    func tapOrderHeader(sender: Any) {
         
-        let sortMenu = NCSortMenu()
-        sortMenu.toggleMenu(viewController: self, key: k_layout_view_offline, sortButton: sender as? UIButton, serverUrl: serverUrl)
-    }
-    
-    func tapMoreHeader(sender: Any) {
+    override func tapMoreGridItem(with objectId: String, namedButtonMore: String, sender: Any) {
         
-    }
-    
-    func tapMoreListItem(with objectId: String, namedButtonMore: String, sender: Any) {
-        tapMoreGridItem(with: objectId, namedButtonMore: namedButtonMore, sender: sender)
-    }
-    
-    func tapShareListItem(with objectId: String, sender: Any) {
-        
-        guard let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "ocId == %@", objectId)) else {
-            return
-        }
-        
-        NCMainCommon.shared.openShare(ViewController: self, metadata: metadata, indexPage: 2)
-    }
-    
-    func tapMoreGridItem(with objectId: String, namedButtonMore: String, sender: Any) {
-        
-        guard let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "ocId == %@", objectId)) else {
-            return
-        }
-        
-        if !isEditMode {
-            let mainMenuViewController = UIStoryboard.init(name: "NCMenu", bundle: nil).instantiateViewController(withIdentifier: "NCMainMenuTableViewController") as! NCMainMenuTableViewController
-            var actions: [NCMenuAction] = []
-
-
-            var iconHeader: UIImage!
-            if let icon = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) {
-                iconHeader = icon
-            } else {
-                iconHeader = UIImage(named: metadata.iconName)
-            }
-
-            actions.append(
-                NCMenuAction(
-                    title: metadata.fileNameView,
-                    icon: iconHeader,
-                    action: nil
-                )
-            )
+        guard let metadata = NCManageDatabase.sharedInstance.getMetadataFromOcId(objectId) else { return }
+        guard let tabBarController = self.tabBarController else { return }
 
-            if self.serverUrl == "" {
-                actions.append(
-                    NCMenuAction(
-                        title: NSLocalizedString("_remove_available_offline_", comment: ""),
-                        icon: CCGraphics.changeThemingColorImage(UIImage(named: "offline"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon),
-                        action: { menuAction in
-                            if metadata.directory {
-                                NCManageDatabase.sharedInstance.setDirectory(serverUrl: CCUtility.stringAppendServerUrl(metadata.serverUrl, addFileName: metadata.fileName)!, offline: false, account: self.appDelegate.account)
-                            } else {
-                                NCManageDatabase.sharedInstance.setLocalFile(ocId: metadata.ocId, offline: false)
-                            }
-                            self.reloadDataSource()
-                        }
-                    )
-                )
-            }
-            
-            actions.append(
-                NCMenuAction(
-                    title: NSLocalizedString("_details_", comment: ""),
-                    icon: CCGraphics.changeThemingColorImage(UIImage(named: "details"), width: 50, height: 50, color: NCBrandColor.sharedInstance.icon),
-                    action: { menuAction in
-                        NCMainCommon.shared.openShare(ViewController: self, metadata: metadata, indexPage: 0)
-                    }
-                )
-            )
-
-            actions.append(
-                NCMenuAction(
-                    title: NSLocalizedString("_delete_", comment: ""),
-                    icon: CCGraphics.changeThemingColorImage(UIImage(named: "trash"), width: 50, height: 50, color: .red),
-                    action: { menuAction in
-                        NCNetworking.shared.deleteMetadata(metadata, account: self.appDelegate.account, urlBase: self.appDelegate.urlBase,onlyLocal: true) { (errorCode, errorDescription) in }
-                    }
-                )
-            )
-
-            mainMenuViewController.actions = actions
-            let menuPanelController = NCMenuPanelController()
-            menuPanelController.parentPresenter = self
-            menuPanelController.delegate = mainMenuViewController
-            menuPanelController.set(contentViewController: mainMenuViewController)
-            menuPanelController.track(scrollView: mainMenuViewController.tableView)
-
-            self.present(menuPanelController, animated: true, completion: nil)
-        } else {
-            
-            let buttonPosition:CGPoint = (sender as! UIButton).convert(CGPoint.zero, to:collectionView)
-            let indexPath = collectionView.indexPathForItem(at: buttonPosition)
-            collectionView(self.collectionView, didSelectItemAt: indexPath!)
+        if namedButtonMore == "more" {
+            toggleMoreMenu(viewController: tabBarController, metadata: metadata)
+        } else if namedButtonMore == "stop" {
+            NCMainCommon.shared.cancelTransferMetadata(metadata, uploadStatusForcedStart: false)
         }
     }
     
@@ -404,51 +75,10 @@ class NCOffline: UIViewController, UIGestureRecognizerDelegate, NCListCellDelega
             }
         }
     }
-}
-
-// MARK: - 3D Touch peek and pop
-
-extension NCOffline: UIViewControllerPreviewingDelegate {
     
-    func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
-        
-        guard let point = collectionView?.convert(location, from: collectionView?.superview) else { return nil }
-        guard let indexPath = collectionView?.indexPathForItem(at: point) else { return nil }
-        guard let metadata = dataSource?.cellForItemAt(indexPath: indexPath) else { return nil }
-        guard let viewController = UIStoryboard(name: "CCPeekPop", bundle: nil).instantiateViewController(withIdentifier: "PeekPopImagePreview") as? CCPeekPop else { return nil }
-
-        viewController.metadata = metadata
-
-        if layout == k_layout_grid {
-            guard let cell = collectionView?.cellForItem(at: indexPath) as? NCGridCell else { return nil }
-            previewingContext.sourceRect = cell.frame
-            viewController.imageFile = cell.imageItem.image
-        } else {
-            guard let cell = collectionView?.cellForItem(at: indexPath) as? NCListCell else { return nil }
-            previewingContext.sourceRect = cell.frame
-            viewController.imageFile = cell.imageItem.image
-        }
-        
-        viewController.showOpenIn = true
-        viewController.showOpenQuickLook = NCUtility.shared.isQuickLookDisplayable(metadata: metadata)
-        viewController.showShare = false
-        
-        return viewController
-    }
+    // MARK: - Collection View
     
-    func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
-        
-        guard let indexPath = collectionView?.indexPathForItem(at: previewingContext.sourceRect.origin) else { return }
-        
-        collectionView(collectionView, didSelectItemAt: indexPath)
-    }
-}
-
-// MARK: - Collection View
-
-extension NCOffline: UICollectionViewDelegate {
-
-    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
+    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
         
         guard let metadata = dataSource?.cellForItemAt(indexPath: indexPath) else { return }
         metadataPush = metadata
@@ -486,184 +116,61 @@ extension NCOffline: UICollectionViewDelegate {
             }
         }
     }
-}
-
-extension NCOffline: UICollectionViewDataSource {
-
-    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
-        
-        if (indexPath.section == 0) {
-            
-            if kind == UICollectionView.elementKindSectionHeader {
-                
-                let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionHeaderMenu", for: indexPath) as! NCSectionHeaderMenu
-                
-                if collectionView.collectionViewLayout == gridLayout {
-                    header.buttonSwitch.setImage(CCGraphics.changeThemingColorImage(UIImage.init(named: "switchList"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), for: .normal)
-                } else {
-                    header.buttonSwitch.setImage(CCGraphics.changeThemingColorImage(UIImage.init(named: "switchGrid"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), for: .normal)
-                }
-                
-                header.delegate = self
-                header.backgroundColor = NCBrandColor.sharedInstance.backgroundView
-                header.separator.backgroundColor = NCBrandColor.sharedInstance.separator
-                header.setStatusButton(count: dataSource?.metadatas.count ?? 0)
-                header.setTitleSorted(datasourceTitleButton: titleButton)
-                
-                if groupBy == "none" {
-                    header.labelSection.isHidden = true
-                    header.labelSectionHeightConstraint.constant = 0
-                } else {
-                    header.labelSection.isHidden = false
-                    header.setTitleLabel(title: "")
-                    header.labelSectionHeightConstraint.constant = sectionHeaderHeight
-                }
-                
-                return header
-                
-            } else {
-                
-                let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as! NCSectionFooter
-                
-                let info = dataSource?.getFilesInformation()
-                footer.setTitleLabel(directories: info?.directories ?? 0, files: info?.files ?? 0, size: info?.size ?? 0)
-                
-                return footer
-            }
-            
-        } else {
-            
-            if kind == UICollectionView.elementKindSectionHeader {
-                
-                let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionHeader", for: indexPath) as! NCSectionHeader
-                
-                header.setTitleLabel(title: "")
-                
-                return header
-                
-            } else {
-                
-                let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as! NCSectionFooter
-                
-                let info = dataSource?.getFilesInformation()
-                footer.setTitleLabel(directories: info?.directories ?? 0, files: info?.files ?? 0, size: info?.size ?? 0)
-                
-                return footer
-            }
-        }
-    }
     
-    func numberOfSections(in collectionView: UICollectionView) -> Int {
-        return dataSource?.sections ?? 1
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-        return dataSource?.numberOfItemsInSection(section: section) ?? 1
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
-        
-        let cell: UICollectionViewCell
-        
-        guard let metadata = dataSource?.cellForItemAt(indexPath: indexPath) else {
-            return collectionView.dequeueReusableCell(withReuseIdentifier: "listCell", for: indexPath) as! NCListCell
-        }
-        
-        if layout == k_layout_grid {
-            cell = collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as! NCGridCell
-        } else {
-            cell = collectionView.dequeueReusableCell(withReuseIdentifier: "listCell", for: indexPath) as! NCListCell
-            (cell as! NCListCell).separator.backgroundColor = NCBrandColor.sharedInstance.separator
-        }
-        
-        let shares = NCManageDatabase.sharedInstance.getTableShares(account: metadata.account, serverUrl: metadata.serverUrl, fileName: metadata.fileName)
-        
-        NCCollectionCommon.shared.cellForItemAt(indexPath: indexPath, collectionView: collectionView, cell: cell, metadata: metadata, metadataFolder: nil, serverUrl: metadata.serverUrl, isEditMode: isEditMode, selectocId: selectocId, autoUploadFileName: autoUploadFileName, autoUploadDirectory: autoUploadDirectory, hideButtonMore: false, downloadThumbnail: true, shares: shares, source: self)
-        
-        return cell
-    }
-}
-
-extension NCOffline: UICollectionViewDelegateFlowLayout {
-
-    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
-        if section == 0 {
-            if groupBy == "none" {
-                return CGSize(width: collectionView.frame.width, height: headerMenuHeight)
-            } else {
-                return CGSize(width: collectionView.frame.width, height: headerMenuHeight + sectionHeaderHeight)
-            }
-        } else {
-            return CGSize(width: collectionView.frame.width, height: sectionHeaderHeight)
-        }
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
-        let sections = dataSource?.sections ?? 1
-        if (section == sections - 1) {
-            return CGSize(width: collectionView.frame.width, height: footerHeight)
-        } else {
-            return CGSize(width: collectionView.frame.width, height: 0)
-        }
-    }
-}
-
-// MARK: - NC API & Algorithm
-
-extension NCOffline {
-
-    @objc func reloadDataSource() {
-        
-        var ocIds: [String] = []
-        var sort: String
-        var ascending: Bool
-        var directoryOnTop: Bool
-        
-        (layout, sort, ascending, groupBy, directoryOnTop, titleButton, itemForLine) = NCUtility.shared.getLayoutForView(key: k_layout_view_offline)
-
-        if serverUrl == "" {
-            
-            if let directories = NCManageDatabase.sharedInstance.getTablesDirectory(predicate: NSPredicate(format: "account == %@ AND offline == true", appDelegate.account), sorted: "serverUrl", ascending: true) {
-                for directory: tableDirectory in directories {
-                    ocIds.append(directory.ocId)
-                }
-            }
-            
-            let files = NCManageDatabase.sharedInstance.getTableLocalFiles(predicate: NSPredicate(format: "account == %@ AND offline == true", appDelegate.account), sorted: "fileName", ascending: true)
-            for file: tableLocalFile in files {
-                ocIds.append(file.ocId)
-            }
-            
-            let metadatasSource = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND ocId IN %@", appDelegate.account, ocIds))
-            self.dataSource = NCDataSource.init(metadatasSource: metadatasSource, sort: sort, ascending: ascending, directoryOnTop: directoryOnTop, filterLivePhoto: true)
-            
-        } else {
-            
-            let metadatasSource = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", appDelegate.account, serverUrl))
-            self.dataSource = NCDataSource.init(metadatasSource: metadatasSource, sort: sort, ascending: ascending, directoryOnTop: directoryOnTop, filterLivePhoto: true)
-        }
-        
-        refreshControl.endRefreshing()
-        collectionView.reloadData()
-    }
-    
-    @objc func reloadDataSourceNetwork() {
-        
-        if serverUrl != "" {
-        
-            NCNetworking.shared.readFolder(serverUrl: serverUrl, account: appDelegate.account) { (account, metadataFolder, metadatas, metadatasUpdate, metadatasLocalUpdate, errorCode, errorDescription) in
-                if errorCode == 0 {
-                    for metadata in metadatas ?? [] {
-                        if !metadata.directory {
-                            let localFile = NCManageDatabase.sharedInstance.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
-                            if localFile == nil || localFile?.etag != metadata.etag {
-                                NCOperationQueue.shared.download(metadata: metadata, selector: selectorDownloadFile, setFavorite: false)
-                            }
-                        }
-                    }
-                }
-                self.reloadDataSource()
-            }
-        }
-    }
+    // MARK: - NC API & Algorithm
+
+    override func reloadDataSource() {
+           
+           var ocIds: [String] = []
+           var sort: String
+           var ascending: Bool
+           var directoryOnTop: Bool
+           
+           (layout, sort, ascending, groupBy, directoryOnTop, titleButton, itemForLine) = NCUtility.shared.getLayoutForView(key: k_layout_view_offline)
+
+           if serverUrl == "" {
+               
+               if let directories = NCManageDatabase.sharedInstance.getTablesDirectory(predicate: NSPredicate(format: "account == %@ AND offline == true", appDelegate.account), sorted: "serverUrl", ascending: true) {
+                   for directory: tableDirectory in directories {
+                       ocIds.append(directory.ocId)
+                   }
+               }
+               
+               let files = NCManageDatabase.sharedInstance.getTableLocalFiles(predicate: NSPredicate(format: "account == %@ AND offline == true", appDelegate.account), sorted: "fileName", ascending: true)
+               for file: tableLocalFile in files {
+                   ocIds.append(file.ocId)
+               }
+               
+               let metadatasSource = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND ocId IN %@", appDelegate.account, ocIds))
+               self.dataSource = NCDataSource.init(metadatasSource: metadatasSource, sort: sort, ascending: ascending, directoryOnTop: directoryOnTop, filterLivePhoto: true)
+               
+           } else {
+               
+               let metadatasSource = NCManageDatabase.sharedInstance.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", appDelegate.account, serverUrl))
+               self.dataSource = NCDataSource.init(metadatasSource: metadatasSource, sort: sort, ascending: ascending, directoryOnTop: directoryOnTop, filterLivePhoto: true)
+           }
+           
+           refreshControl.endRefreshing()
+           collectionView.reloadData()
+       }
+       
+       override func reloadDataSourceNetwork() {
+           
+           if serverUrl != "" {
+           
+               NCNetworking.shared.readFolder(serverUrl: serverUrl, account: appDelegate.account) { (account, metadataFolder, metadatas, metadatasUpdate, metadatasLocalUpdate, errorCode, errorDescription) in
+                   if errorCode == 0 {
+                       for metadata in metadatas ?? [] {
+                           if !metadata.directory {
+                               let localFile = NCManageDatabase.sharedInstance.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
+                               if localFile == nil || localFile?.etag != metadata.etag {
+                                   NCOperationQueue.shared.download(metadata: metadata, selector: selectorDownloadFile, setFavorite: false)
+                               }
+                           }
+                       }
+                   }
+                   self.reloadDataSource()
+               }
+           }
+       }
 }