From 9c3c8ccf4d187877acdfe45b3e05eb4850d1c81a Mon Sep 17 00:00:00 2001 From: Shweta Waikar Date: Tue, 13 Jun 2023 14:33:11 +0530 Subject: [PATCH 1/6] NMC 2267 Rename file/folder customisation --- iOSClient/Rename file/NCRenameFile.storyboard | 135 +++++++++ iOSClient/Rename file/NCRenameFile.swift | 263 ++++++++++++++++++ 2 files changed, 398 insertions(+) create mode 100644 iOSClient/Rename file/NCRenameFile.storyboard create mode 100644 iOSClient/Rename file/NCRenameFile.swift diff --git a/iOSClient/Rename file/NCRenameFile.storyboard b/iOSClient/Rename file/NCRenameFile.storyboard new file mode 100644 index 0000000000..6e98f850cc --- /dev/null +++ b/iOSClient/Rename file/NCRenameFile.storyboard @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOSClient/Rename file/NCRenameFile.swift b/iOSClient/Rename file/NCRenameFile.swift new file mode 100644 index 0000000000..723e02ed3f --- /dev/null +++ b/iOSClient/Rename file/NCRenameFile.swift @@ -0,0 +1,263 @@ +// +// NCRenameFile.swift +// Nextcloud +// +// Created by Marino Faggiana on 26/02/21. +// Copyright © 2021 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana +// +// 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 . +// + +import UIKit +import NextcloudKit + +public protocol NCRenameFileDelegate: AnyObject { + func rename(fileName: String, fileNameNew: String) +} + +// optional func +public extension NCRenameFileDelegate { + func rename(fileName: String, fileNameNew: String) {} +} + +class NCRenameFile: UIViewController, UITextFieldDelegate { + + @IBOutlet weak var titleLabel: UILabel! + @IBOutlet weak var separatorHeightContraint: NSLayoutConstraint! + @IBOutlet weak var previewFile: UIImageView! + @IBOutlet weak var fileNameNoExtension: UITextField! + @IBOutlet weak var point: UILabel! + @IBOutlet weak var ext: UITextField! + @IBOutlet weak var fileNameNoExtensionTrailingContraint: NSLayoutConstraint! + @IBOutlet weak var cancelButton: UIButton! + @IBOutlet weak var renameButton: UIButton! + @IBOutlet weak var seperator: UIView! + + let width: CGFloat = 300 + let height: CGFloat = 350 + + var metadata: tableMetadata? + var indexPath: IndexPath = IndexPath() + var fileName: String? + var imagePreview: UIImage? + var disableChangeExt: Bool = false + weak var delegate: NCRenameFileDelegate? + + // MARK: - View Life Cycle + + override func viewDidLoad() { + super.viewDidLoad() + + if let metadata = self.metadata { + + if metadata.directory { + titleLabel.text = NSLocalizedString("_rename_folder_", comment: "") + } else { + titleLabel.text = NSLocalizedString("_rename_file_", comment: "") + } + separatorHeightContraint.constant = 0.3 + seperator.backgroundColor = NCBrandColor.shared.seperatorRename + fileNameNoExtension.backgroundColor = .secondarySystemGroupedBackground + fileNameNoExtension.text = (metadata.fileNameView as NSString).deletingPathExtension + fileNameNoExtension.delegate = self + fileNameNoExtension.becomeFirstResponder() + + ext.text = metadata.fileExtension + ext.delegate = self + if disableChangeExt { + ext.isEnabled = false + ext.textColor = .lightGray + } + + previewFile.image = imagePreview + previewFile.layer.cornerRadius = 10 + previewFile.layer.masksToBounds = true + + if metadata.directory { + + if imagePreview == nil { + previewFile.image = NCImageCache.images.folder + } + + ext.isHidden = true + point.isHidden = true + fileNameNoExtensionTrailingContraint.constant = 20 + + } else { + + if imagePreview == nil { + previewFile.image = NCImageCache.images.file + } + + fileNameNoExtensionTrailingContraint.constant = 90 + } + + } else if let fileName = self.fileName { + + titleLabel.text = NSLocalizedString("_rename_file_", comment: "") + + fileNameNoExtension.text = (fileName as NSString).deletingPathExtension + fileNameNoExtension.delegate = self + fileNameNoExtension.becomeFirstResponder() + fileNameNoExtensionTrailingContraint.constant = 90 + + ext.text = (fileName as NSString).pathExtension + ext.delegate = self + + if imagePreview == nil { + previewFile.image = NCImageCache.images.file + } else { + previewFile.image = imagePreview + } + previewFile.layer.cornerRadius = 10 + previewFile.layer.masksToBounds = true + } + + cancelButton.setTitle(NSLocalizedString("_cancel_", comment: ""), for: .normal) + cancelButton.setTitleColor(NCBrandColor.shared.iconColor, for: .normal) + cancelButton.layer.cornerRadius = 5 + cancelButton.layer.masksToBounds = true + cancelButton.layer.borderWidth = 0.3 + cancelButton.layer.borderColor = NCBrandColor.shared.iconColor.cgColor + + renameButton.setTitle(NSLocalizedString("_rename_", comment: ""), for: .normal) + renameButton.setTitleColor(NCBrandColor.shared.brandText, for: .normal) + renameButton.layer.cornerRadius = 5 + renameButton.layer.masksToBounds = true + renameButton.layer.backgroundColor = NCBrandColor.shared.brand.cgColor + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + if metadata == nil && fileName == nil { + dismiss(animated: true) + } + + fileNameNoExtension.selectAll(nil) + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + + textField.resignFirstResponder() + renameFile(textField) + return true + } + + // MARK: - Action + + @IBAction func cancel(_ sender: Any) { + + dismiss(animated: true) + } + + @IBAction func renameFile(_ sender: Any) { + + var fileNameNoExtensionNew = "" + var extNew = "" + var fileNameNew = "" + + if let metadata = self.metadata { + + let extCurrent = (metadata.fileNameView as NSString).pathExtension + + if fileNameNoExtension.text == nil || fileNameNoExtension.text?.count == 0 { + return self.fileNameNoExtension.text = (metadata.fileNameView as NSString).deletingPathExtension + } else { + fileNameNoExtensionNew = fileNameNoExtension.text! + } + + if metadata.directory { + + fileNameNew = fileNameNoExtensionNew + renameMetadata(metadata, fileNameNew: fileNameNew, indexPath: indexPath) + + } else { + + if ext.text == nil || ext.text?.count == 0 { + return self.ext.text = metadata.fileExtension + } else { + extNew = ext.text! + } + + if extNew != extCurrent { + + let message = String(format: NSLocalizedString("_rename_ext_message_", comment: ""), extNew, extCurrent) + let alertController = UIAlertController(title: NSLocalizedString("_rename_ext_title_", comment: ""), message: message, preferredStyle: .alert) + + var title = NSLocalizedString("_use_", comment: "") + " ." + extNew + alertController.addAction(UIAlertAction(title: title, style: .default, handler: { _ in + + fileNameNew = fileNameNoExtensionNew + "." + extNew + self.renameMetadata(metadata, fileNameNew: fileNameNew, indexPath: self.indexPath) + })) + + title = NSLocalizedString("_keep_", comment: "") + " ." + extCurrent + alertController.addAction(UIAlertAction(title: title, style: .default, handler: { _ in + self.ext.text = metadata.fileExtension + })) + + self.present(alertController, animated: true) + + } else { + + fileNameNew = fileNameNoExtensionNew + "." + extNew + renameMetadata(metadata, fileNameNew: fileNameNew, indexPath: indexPath) + } + } + + } else if let fileName = self.fileName { + + if fileNameNoExtension.text == nil || fileNameNoExtension.text?.count == 0 { + return fileNameNoExtension.text = (fileName as NSString).deletingPathExtension + } else if ext.text == nil || ext.text?.count == 0 { + return ext.text = (fileName as NSString).pathExtension + } + + fileNameNew = (fileNameNoExtension.text ?? "") + "." + (ext.text ?? "") + self.dismiss(animated: true) { + self.delegate?.rename(fileName: fileName, fileNameNew: fileNameNew) + } + } + } + + // MARK: - Networking + + func renameMetadata(_ metadata: tableMetadata, fileNameNew: String, indexPath: IndexPath) { + + // verify if already exists + if NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", metadata.account, metadata.serverUrl, fileNameNew)) != nil { + NCContentPresenter().showError(error: NKError(errorCode: 0, errorDescription: "_rename_already_exists_")) + return + } + + NCActivityIndicator.shared.start() + + NCNetworking.shared.renameMetadata(metadata, fileNameNew: fileNameNew, indexPath: indexPath, viewController: self) { error in + + NCActivityIndicator.shared.stop() + + if error == .success { + + self.dismiss(animated: true) + + } else { + + NCContentPresenter().showError(error: error) + } + } + } +} From 1ab477da9a647265a7272a52b761c7b9df4375ed Mon Sep 17 00:00:00 2001 From: Shweta Waikar Date: Wed, 14 Jun 2023 12:42:25 +0530 Subject: [PATCH 2/6] NMC 2267 - Unit test cases added for rename file --- .../NextcloudUnitTests/RenameFileTests.swift | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 Tests/NextcloudUnitTests/RenameFileTests.swift diff --git a/Tests/NextcloudUnitTests/RenameFileTests.swift b/Tests/NextcloudUnitTests/RenameFileTests.swift new file mode 100644 index 0000000000..c0aa06f029 --- /dev/null +++ b/Tests/NextcloudUnitTests/RenameFileTests.swift @@ -0,0 +1,108 @@ +// +// RenameFileTests.swift +// NextcloudTests +// +// Created by A200073704 on 14/06/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +@testable import Nextcloud +import XCTest +import NextcloudKit + +class RenameFileTests: XCTestCase { + + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + + func testStoryboardPresence() { + + let storyboard = UIStoryboard(name: "NCRenameFile", bundle: nil) + XCTAssertNotNil(storyboard, "Storyboard 'NCRenameFile' should be present") + + } + + func testRenameButtonPresence() { + let storyboard = UIStoryboard(name: "NCRenameFile", bundle: nil) + guard let viewController = storyboard.instantiateInitialViewController() as? NCRenameFile else { + XCTFail("Failed to instantiate view controller from storyboard") + return + } + + _ = viewController.view // Load the view + + let renameButton = viewController.renameButton + XCTAssertNotNil(renameButton, "Rename button should be present") + } + + func testRenameButtonBackgroundColor() { + + let storyboard = UIStoryboard(name: "NCRenameFile", bundle: nil) + guard let viewController = storyboard.instantiateInitialViewController() as? NCRenameFile else { + XCTFail("Failed to instantiate view controller from storyboard") + return + } + + _ = viewController.view // Load the view + + let color = NCBrandColor.shared.brand.cgColor + let renameButton = viewController.renameButton.layer.backgroundColor + + XCTAssertEqual(renameButton,color, "Rename Button Bcakground Color should be brand") + } + + func testCancelButtonPresence() { + let storyboard = UIStoryboard(name: "NCRenameFile", bundle: nil) + guard let viewController = storyboard.instantiateInitialViewController() as? NCRenameFile else { + XCTFail("Failed to instantiate view controller from storyboard") + return + } + + _ = viewController.view // Load the view + + let cancelButton = viewController.cancelButton + XCTAssertNotNil(cancelButton, "Cancel button should be present") + } + + func testImageViewPresence() { + + let storyboard = UIStoryboard(name: "NCRenameFile", bundle: nil) + guard let viewController = storyboard.instantiateInitialViewController() as? NCRenameFile else { + XCTFail("Failed to instantiate view controller from storyboard") + return + } + + _ = viewController.view // Load the view + + let imageView = viewController.previewFile + XCTAssertNotNil(imageView, "UIImageView should be present on the storyboard") + } + + func testTextFiledPresence() { + + let storyboard = UIStoryboard(name: "NCRenameFile", bundle: nil) + guard let viewController = storyboard.instantiateInitialViewController() as? NCRenameFile else { + XCTFail("Failed to instantiate view controller from storyboard") + return + } + + _ = viewController.view // Load the view + + let textField = viewController.fileNameNoExtension + let textFieldExt = viewController.ext + + XCTAssertNotNil(textField, "FileNameNoExtention TextFiled should be present on the storyboard") + XCTAssertNotNil(textFieldExt, "Extension TextFiled should be present on the storyboard") + + } + + + +} From 11292198a1dc52e33043a8b8fd948361da4ae228 Mon Sep 17 00:00:00 2001 From: TSI-amrutwaghmare <96108296+TSI-amrutwaghmare@users.noreply.github.com> Date: Tue, 27 Feb 2024 12:18:04 +0530 Subject: [PATCH 3/6] NMC 2267 - NMC 2880 File- Renaming file from its preview doesn't change filename --- .../NCCollectionViewCommon.swift | 21 +++++++++++++++ iOSClient/NCGlobal.swift | 27 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift index ad09d5b6f2..f31559940a 100644 --- a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift +++ b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift @@ -312,6 +312,27 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS NotificationCenter.default.removeObserver(self, name: UIApplication.willResignActiveNotification, object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: global.notificationCenterCloseRichWorkspaceWebView), object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: global.notificationCenterChangeStatusFolderE2EE), object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: global.notificationCenterChangeLayout), object: nil) + + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: global.notificationCenterDeleteFile), object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: global.notificationCenterCopyMoveFile), object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: global.notificationCenterCopyFile), object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: global.notificationCenterMoveFile), object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: global.notificationCenterRenameFile), object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: global.notificationCenterCreateFolder), object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: global.notificationCenterFavoriteFile), object: nil) + + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: global.notificationCenterDownloadStartFile), object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: global.notificationCenterDownloadedFile), object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: global.notificationCenterDownloadCancelFile), object: nil) + + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: global.notificationCenterUploadStartFile), object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: global.notificationCenterUploadedFile), object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: global.notificationCenterUploadedLivePhoto), object: nil) + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: global.notificationCenterUploadCancelFile), object: nil) + + NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: global.notificationCenterUpdateShare), object: nil) removeImageCache(metadatas: self.dataSource.getMetadatas()) } diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift index 51df24b68c..36b5b715c1 100644 --- a/iOSClient/NCGlobal.swift +++ b/iOSClient/NCGlobal.swift @@ -270,6 +270,33 @@ final class NCGlobal: Sendable { let notificationCenterCheckUserDelaultErrorDone = "checkUserDelaultErrorDone" // userInfo: account, controller let notificationCenterServerDidUpdate = "serverDidUpdate" // userInfo: account let notificationCenterNetworkReachability = "networkReachability" + let notificationCenterUpdateNotification = "updateNotification" + let notificationCenterReloadDataSource = "reloadDataSource" // userInfo: serverUrl?, clearDataSource + let notificationCenterGetServerData = "getServerData" // userInfo: serverUrl? + + let notificationCenterChangeStatusFolderE2EE = "changeStatusFolderE2EE" // userInfo: serverUrl + + let notificationCenterDownloadStartFile = "downloadStartFile" // userInfo: ocId, ocIdTransfer, session, serverUrl, account + let notificationCenterDownloadedFile = "downloadedFile" // userInfo: ocId, ocIdTransfer, session, session, serverUrl, account, selector, error + let notificationCenterDownloadCancelFile = "downloadCancelFile" // userInfo: ocId, ocIdTransfer, session, serverUrl, account + + let notificationCenterUploadStartFile = "uploadStartFile" // userInfo: ocId, ocIdTransfer, session, serverUrl, account, fileName, sessionSelector + let notificationCenterUploadedFile = "uploadedFile" // userInfo: ocId, ocIdTransfer, session, serverUrl, account, fileName, ocIdTransfer, error + let notificationCenterUploadedLivePhoto = "uploadedLivePhoto" // userInfo: ocId, ocIdTransfer, session, serverUrl, account, fileName, ocIdTransfer, error + let notificationCenterUploadCancelFile = "uploadCancelFile" // userInfo: ocId, ocIdTransfer, session, serverUrl, account + + let notificationCenterProgressTask = "progressTask" // userInfo: account, ocId, ocIdTransfer, session, serverUrl, status, chunk, e2eEncrypted, progress, totalBytes, totalBytesExpected + + let notificationCenterUpdateBadgeNumber = "updateBadgeNumber" // userInfo: counterDownload, counterUpload + + let notificationCenterCreateFolder = "createFolder" // userInfo: ocId, serverUrl, account, withPush, sceneIdentifier + let notificationCenterDeleteFile = "deleteFile" // userInfo: [ocId], error + let notificationCenterCopyMoveFile = "copyMoveFile" // userInfo: [ocId] serverUrl, account, dragdrop, type (copy, move) + let notificationCenterMoveFile = "moveFile" // userInfo: [ocId], [indexPath], error + let notificationCenterCopyFile = "copyFile" // userInfo: [ocId], [indexPath], error + let notificationCenterRenameFile = "renameFile" // userInfo: serverUrl, account, error + let notificationCenterFavoriteFile = "favoriteFile" // userInfo: ocId, serverUrl + let notificationCenterFileExists = "fileExists" // userInfo: ocId, fileExists let notificationCenterMenuSearchTextPDF = "menuSearchTextPDF" let notificationCenterMenuGotToPageInPDF = "menuGotToPageInPDF" From 1a92042856c749aa839ed082b3e3ddde612056f1 Mon Sep 17 00:00:00 2001 From: harshada-15-tsys Date: Tue, 8 Apr 2025 13:42:47 +0530 Subject: [PATCH 4/6] NMC 2267 - Rename file/folder customisation --- Nextcloud.xcodeproj/project.pbxproj | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index 8dd4c5545f..198b831dc4 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -85,6 +85,12 @@ AFCE353527E4ED5900FEA6C2 /* DateFormatter+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353427E4ED5900FEA6C2 /* DateFormatter+Extension.swift */; }; AFCE353727E4ED7B00FEA6C2 /* NCShareCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353627E4ED7B00FEA6C2 /* NCShareCells.swift */; }; AFCE353927E5DE0500FEA6C2 /* Shareable.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* Shareable.swift */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B5D45E6D2DA510E000773929 /* NCRenameFile.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B5D45E6A2DA510E000773929 /* NCRenameFile.storyboard */; }; + B5D45E6E2DA510E000773929 /* NCRenameFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D45E6B2DA510E000773929 /* NCRenameFile.swift */; }; + B5D45E702DA5119A00773929 /* RenameFileTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D45E6F2DA5119A00773929 /* RenameFileTests.swift */; }; + C04E2F232A17BB4D001BAD85 /* FilesIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C04E2F222A17BB4D001BAD85 /* FilesIntegrationTests.swift */; }; + D575039F27146F93008DC9DC /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extension.swift */; }; D5B6AA7827200C7200D49C24 /* NCActivityTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */; }; F310B1EF2BA862F1001C42F5 /* NCViewerMedia+VisionKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = F310B1EE2BA862F1001C42F5 /* NCViewerMedia+VisionKit.swift */; }; F321DA8A2B71205A00DDA0E6 /* NCTrashSelectTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = F321DA892B71205A00DDA0E6 /* NCTrashSelectTabBar.swift */; }; @@ -1221,6 +1227,10 @@ AFCE353427E4ED5900FEA6C2 /* DateFormatter+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DateFormatter+Extension.swift"; sourceTree = ""; }; AFCE353627E4ED7B00FEA6C2 /* NCShareCells.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareCells.swift; sourceTree = ""; }; AFCE353827E5DE0400FEA6C2 /* Shareable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shareable.swift; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B5D45E6A2DA510E000773929 /* NCRenameFile.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCRenameFile.storyboard; sourceTree = ""; }; + B5D45E6B2DA510E000773929 /* NCRenameFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCRenameFile.swift; sourceTree = ""; }; + B5D45E6F2DA5119A00773929 /* RenameFileTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RenameFileTests.swift; sourceTree = ""; }; C0046CDA2A17B98400D87C9D /* NextcloudUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NextcloudUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; C04E2F202A17BB4D001BAD85 /* NextcloudIntegrationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NextcloudIntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCActivityTableViewCell.swift; sourceTree = ""; }; @@ -2024,6 +2034,8 @@ isa = PBXGroup; children = ( AA52EB452D42AC5A0089C348 /* Placeholder.swift */, + B5D45E6F2DA5119A00773929 /* RenameFileTests.swift */, + AF8ED1FB2757821000B8DBC4 /* NextcloudUnitTests.swift */, ); path = NextcloudUnitTests; sourceTree = ""; @@ -2062,6 +2074,15 @@ path = Advanced; sourceTree = ""; }; + B5D45E6C2DA510E000773929 /* Rename file */ = { + isa = PBXGroup; + children = ( + B5D45E6A2DA510E000773929 /* NCRenameFile.storyboard */, + B5D45E6B2DA510E000773929 /* NCRenameFile.swift */, + ); + path = "Rename file"; + sourceTree = ""; + }; C0046CDB2A17B98400D87C9D /* NextcloudUITests */ = { isa = PBXGroup; children = ( @@ -3260,6 +3281,7 @@ F7381ED9218218A4000B1560 /* Offline */, F713418B2597513800768D21 /* PushNotification */, F765F72E25237E3F00391DBE /* Recent */, + B5D45E6C2DA510E000773929 /* Rename file */, F7CADB3D23CCDDA1000EEC78 /* RichWorkspace */, F76882042C0DD1E7001CF441 /* Settings */, F758B41E212C516300515F55 /* Scan document */, @@ -3949,6 +3971,8 @@ F7381EE5218218C9000B1560 /* NCOffline.storyboard in Resources */, F768822D2C0DD1E7001CF441 /* Acknowledgements.rtf in Resources */, F76D3CF32428B94E005DFA87 /* NCViewerPDFSearchCell.xib in Resources */, + F7CA212E25F1333300826ABB /* NCAccountRequest.storyboard in Resources */, + B5D45E6D2DA510E000773929 /* NCRenameFile.storyboard in Resources */, F717402D24F699A5000C87D5 /* NCFavorite.storyboard in Resources */, F723B3DD22FC6D1D00301EFE /* NCShareCommentsCell.xib in Resources */, F78ACD4B21903F850088454D /* NCTrashListCell.xib in Resources */, @@ -4083,6 +4107,7 @@ files = ( AA52EB472D42AC9E0089C348 /* Placeholder.swift in Sources */, F372087D2BAB4C0F006B5430 /* TestConstants.swift in Sources */, + B5D45E702DA5119A00773929 /* RenameFileTests.swift in Sources */, F78E2D6C29AF02DB0024D4F3 /* Database.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -4701,6 +4726,7 @@ F763D29D2A249C4500A3C901 /* NCManageDatabase+Capabilities.swift in Sources */, F76882252C0DD1E7001CF441 /* NCSettingsAdvancedModel.swift in Sources */, F7C7B489245EBA4100D93E60 /* NCViewerQuickLook.swift in Sources */, + B5D45E6E2DA510E000773929 /* NCRenameFile.swift in Sources */, F758B45E212C569D00515F55 /* NCScanCell.swift in Sources */, F78B87E72B62527100C65ADC /* NCMediaDataSource.swift in Sources */, F76882272C0DD1E7001CF441 /* NCManageE2EEView.swift in Sources */, From 9e4e6192e90bf6d867586c984c044295531e7009 Mon Sep 17 00:00:00 2001 From: harshada-15-tsys Date: Tue, 30 Sep 2025 18:30:21 +0530 Subject: [PATCH 5/6] NMC 2267 - Rename file/folder customisation changes --- .../NCCollectionViewCommon.swift | 718 +++++++++++++++++- iOSClient/NCGlobal.swift | 263 +++++-- 2 files changed, 890 insertions(+), 91 deletions(-) diff --git a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift index f31559940a..60e6c75e9c 100644 --- a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift +++ b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift @@ -4,10 +4,12 @@ import UIKit import SwiftUI +import Realm import RealmSwift import NextcloudKit import EasyTipView import LucidBanner +import MoEngageInApps class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UISearchResultsUpdating, UISearchControllerDelegate, UISearchBarDelegate, NCListCellDelegate, NCGridCellDelegate, NCPhotoCellDelegate, NCSectionFirstHeaderDelegate, NCSectionFooterDelegate, NCSectionFirstHeaderEmptyDataDelegate, NCAccountSettingsModelDelegate, NCTransferDelegate, UIAdaptivePresentationControllerDelegate, UIContextMenuInteractionDelegate { @@ -31,6 +33,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS var serverUrl: String = "" var isEditMode = false var isDirectoryE2EE = false + var isDirectoryEncrypted = false var fileSelect: [String] = [] var metadataFolder: tableMetadata? var richWorkspaceText: String? @@ -40,6 +43,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS var networkSearchInProgress: Bool = false var layoutForView: NCDBLayoutForView? var searchDataSourceTask: URLSessionTask? + var dataSourceTask: URLSessionTask? var providers: [NKSearchProvider]? var searchResults: [NKSearchResult]? var listLayout = NCListLayout() @@ -50,9 +54,17 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS var tabBarSelect: NCCollectionViewCommonSelectTabBar? var attributesZoomIn: UIMenuElement.Attributes = [] var attributesZoomOut: UIMenuElement.Attributes = [] + let maxImageGrid: CGFloat = 7 + // var headerMenu: NCSectionFirstHeader? + var tipViewAccounts: EasyTipView? var syncMetadatasTask: Task? - + var tipViewAutoUpload: EasyTipView? + var headerMenu: NCSectionHeaderMenu? + var headerMenuTransferView = false + var headerMenuButtonsView: Bool = true + var headerRichWorkspaceDisable: Bool = false + // DECLARE var layoutKey = "" var titleCurrentFolder = "" @@ -60,8 +72,11 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS var enableSearchBar: Bool = false var headerRichWorkspaceDisable: Bool = false + var groupByField = "name" + var emptyImageName: String? var emptyImageColors: [UIColor]? + var emptyImage: UIImage? var emptyTitle: String = "" var emptyDescription: String = "" @@ -80,6 +95,11 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS var numberOfColumns: Int = 0 var lastNumberOfColumns: Int = 0 + var isTransitioning: Bool = false + var selectableDataSource: [RealmSwiftObject] { dataSource.getMetadataSourceForAllSections() } + var pushed: Bool = false + var emptyDataSet: NCEmptyDataSet? + let heightHeaderRecommendations: CGFloat = 160 let heightHeaderSection: CGFloat = 30 @@ -126,6 +146,16 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS (self.tabBarController as? NCMainTabBarController)?.sceneIdentifier ?? "" } + var defaultPredicate: NSPredicate { + let predicate = NSPredicate(format: "account == %@ AND serverUrl == %@ AND NOT (status IN %@) AND NOT (livePhotoFile != '' AND classFile == %@)", session.account, self.serverUrl, NCGlobal.shared.metadataStatusHideInView, NKCommon.TypeClassFile.video.rawValue) + return predicate + } + + var personalFilesOnlyPredicate: NSPredicate { + let predicate = NSPredicate(format: "account == %@ AND serverUrl == %@ AND (ownerId == %@ || ownerId == '') AND mountType == '' AND NOT (status IN %@) AND NOT (livePhotoFile != '' AND classFile == %@)", session.account, self.serverUrl, session.userId, global.metadataStatusHideInView, NKCommon.TypeClassFile.video.rawValue) + return predicate + } + var isNumberOfItemsInAllSectionsNull: Bool { var totalItems = 0 for section in 0.. Bool { + let appVersion = Bundle.main.infoDictionary?["CFBundleInfoDictionaryVersion"] as? String ?? "" + let currentVersion = UserDefaults.standard.string(forKey: "CurrentAppVersion") + return currentVersion != appVersion + } + + func redirectToPrivacyViewController() { + let storyBoard: UIStoryboard = UIStoryboard(name: "NCSettings", bundle: nil) + let newViewController = storyBoard.instantiateViewController(withIdentifier: "privacySettingsNavigation") as! UINavigationController + newViewController.modalPresentationStyle = .fullScreen + self.present(newViewController, animated: true, completion: nil) + } func presentationControllerDidDismiss( _ presentationController: UIPresentationController) { let viewController = presentationController.presentedViewController @@ -532,6 +652,413 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS self.present(alertController, animated: true) } } + + override func viewWillLayoutSubviews() { + super.viewWillLayoutSubviews() + + if let frame = tabBarController?.tabBar.frame { + tabBarSelect?.hostingController?.view.frame = frame + } + } + + // MARK: - NotificationCenter + +// @objc func applicationWillResignActive(_ notification: NSNotification) { +// self.resetPlusButtonAlpha() +// self.refreshControl.endRefreshing() +// } + + @objc func reloadAvatar(_ notification: NSNotification) { + DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { + self.showTipAccounts() + } + guard let userInfo = notification.userInfo as NSDictionary?, + let error = userInfo["error"] as? NKError, + error.errorCode != global.errorNotModified else { return } + /// Magentacloud branding changes hide user account button on left navigation bar + setNavigationLeftItems() + } + + @objc func changeTheming(_ notification: NSNotification) { + self.reloadDataSource() + } + + @objc func changeLayout(_ notification: NSNotification) { + guard let userInfo = notification.userInfo as NSDictionary?, + let account = userInfo["account"] as? String, + let serverUrl = userInfo["serverUrl"] as? String, + let layoutForView = userInfo["layoutForView"] as? NCDBLayoutForView, + account == session.account, + serverUrl == self.serverUrl + else { return } + + if self.layoutForView?.layout == layoutForView.layout { + self.layoutForView = self.database.setLayoutForView(layoutForView: layoutForView) + self.reloadDataSource() + return + } + + self.layoutForView = self.database.setLayoutForView(layoutForView: layoutForView) + layoutForView.layout = layoutForView.layout + self.layoutType = layoutForView.layout + + collectionView.reloadData() + + switch layoutForView.layout { + case global.layoutList: + self.collectionView.setCollectionViewLayout(self.listLayout, animated: true) + case global.layoutGrid: + self.collectionView.setCollectionViewLayout(self.gridLayout, animated: true) + case global.layoutPhotoSquare, global.layoutPhotoRatio: + self.collectionView.setCollectionViewLayout(self.mediaLayout, animated: true) + default: + break + } + + self.collectionView.collectionViewLayout.invalidateLayout() + +// (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() + } + + @objc func reloadDataSource(_ notification: NSNotification) { + if let userInfo = notification.userInfo as? NSDictionary { + if let serverUrl = userInfo["serverUrl"] as? String { + if serverUrl != self.serverUrl { + return + } + } + + if let clearDataSource = userInfo["clearDataSource"] as? Bool, clearDataSource { + self.dataSource.removeAll() + } + } + + reloadDataSource() + } + + @objc func getServerData(_ notification: NSNotification) { + if let userInfo = notification.userInfo as NSDictionary?, + let serverUrl = userInfo["serverUrl"] as? String { + if serverUrl != self.serverUrl { + return + } + } + + getServerData() + } + + @objc func reloadHeader(_ notification: NSNotification) { + guard let userInfo = notification.userInfo as NSDictionary?, + let account = userInfo["account"] as? String, + account == session.account + else { return } + + self.collectionView.reloadData() + } + + @objc func changeStatusFolderE2EE(_ notification: NSNotification) { + reloadDataSource() + } + + @objc func closeRichWorkspaceWebView() { + reloadDataSource() + } + + @objc func deleteFile(_ notification: NSNotification) { + guard let userInfo = notification.userInfo as NSDictionary?, + let error = userInfo["error"] as? NKError else { return } + + if error == .success { + if isSearchingMode { + return networkSearch() + } + + if isRecommendationActived { + Task.detached { + await NCNetworking.shared.createRecommendations(session: self.session) + } + } + } else { + NCContentPresenter().showError(error: error) + } + + reloadDataSource() + } + + @objc func copyMoveFile(_ notification: NSNotification) { + guard let userInfo = notification.userInfo as NSDictionary?, + let serverUrl = userInfo["serverUrl"] as? String, + let account = userInfo["account"] as? String, + account == session.account else { return } + + if isSearchingMode { + return networkSearch() + } + + if isRecommendationActived { + Task.detached { + await NCNetworking.shared.createRecommendations(session: self.session) + } + } + + if serverUrl == self.serverUrl { + reloadDataSource() + } + } + + @objc func renameFile(_ notification: NSNotification) { + guard let userInfo = notification.userInfo as NSDictionary?, + let account = userInfo["account"] as? String, + let serverUrl = userInfo["serverUrl"] as? String, + let error = userInfo["error"] as? NKError, + account == session.account + else { return } + + if error == .success { + if isSearchingMode { + return networkSearch() + } + + if isRecommendationActived { + Task.detached { + await NCNetworking.shared.createRecommendations(session: self.session) + } + } + } + + if serverUrl == self.serverUrl { + if error != .success { + NCContentPresenter().showError(error: error) + } + reloadDataSource() + } else { + collectionView.reloadData() + } + } + + @objc func createFolder(_ notification: NSNotification) { + guard let userInfo = notification.userInfo as NSDictionary?, + let ocId = userInfo["ocId"] as? String, + let account = userInfo["account"] as? String, + account == session.account, + let withPush = userInfo["withPush"] as? Bool, + let metadata = database.getMetadataFromOcId(ocId) + else { return } + + if isSearchingMode { + return networkSearch() + } + + if metadata.serverUrl + "/" + metadata.fileName == self.serverUrl { + reloadDataSource() + } else if withPush, metadata.serverUrl == self.serverUrl { + reloadDataSource() + if let sceneIdentifier = userInfo["sceneIdentifier"] as? String { + if sceneIdentifier == controller?.sceneIdentifier { + pushMetadata(metadata) + } + } else { + pushMetadata(metadata) + } + } + } + + @objc func favoriteFile(_ notification: NSNotification) { + if isSearchingMode { + return networkSearch() + } + + if self is NCFavorite { + return reloadDataSource() + } + + guard let userInfo = notification.userInfo as NSDictionary?, + let serverUrl = userInfo["serverUrl"] as? String, + serverUrl == self.serverUrl + else { return } + + reloadDataSource() + } + + @objc func downloadStartFile(_ notification: NSNotification) { + guard let userInfo = notification.userInfo as NSDictionary?, + let serverUrl = userInfo["serverUrl"] as? String, + let account = userInfo["account"] as? String + else { return } + + if account == self.session.account, serverUrl == self.serverUrl { + reloadDataSource() + } else { + collectionView?.reloadData() + } + } + + @objc func downloadedFile(_ notification: NSNotification) { + guard let userInfo = notification.userInfo as NSDictionary?, + let serverUrl = userInfo["serverUrl"] as? String, + let account = userInfo["account"] as? String + else { return } + + if account == self.session.account, serverUrl == self.serverUrl { + reloadDataSource() + } else { + collectionView?.reloadData() + } + } + + @objc func downloadCancelFile(_ notification: NSNotification) { + guard let userInfo = notification.userInfo as NSDictionary?, + let serverUrl = userInfo["serverUrl"] as? String, + let account = userInfo["account"] as? String + else { return } + + if account == self.session.account, serverUrl == self.serverUrl { + reloadDataSource() + } else { + collectionView?.reloadData() + } + } + + @objc func uploadStartFile(_ notification: NSNotification) { + guard let userInfo = notification.userInfo as NSDictionary?, + let ocId = userInfo["ocId"] as? String, + let serverUrl = userInfo["serverUrl"] as? String, + let account = userInfo["account"] as? String, + !isSearchingMode, + let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) + else { return } + + // Header view trasfer + if metadata.isTransferInForeground { + NCNetworking.shared.transferInForegorund = NCNetworking.TransferInForegorund(ocId: ocId, progress: 0) + DispatchQueue.main.async { self.collectionView?.reloadData() } + } + + if account == self.session.account, serverUrl == self.serverUrl { + reloadDataSource() + } else { + collectionView?.reloadData() + } + } + + @objc func uploadedFile(_ notification: NSNotification) { + guard let userInfo = notification.userInfo as NSDictionary?, + let serverUrl = userInfo["serverUrl"] as? String, + let account = userInfo["account"] as? String + else { return } + + if account == self.session.account, serverUrl == self.serverUrl { + reloadDataSource() + } else { + collectionView?.reloadData() + } + } + + @objc func uploadedLivePhoto(_ notification: NSNotification) { + guard let userInfo = notification.userInfo as NSDictionary?, + let serverUrl = userInfo["serverUrl"] as? String, + let account = userInfo["account"] as? String + else { return } + + if account == self.session.account, serverUrl == self.serverUrl { + reloadDataSource() + } else { + collectionView?.reloadData() + } + } + + @objc func uploadCancelFile(_ notification: NSNotification) { + guard let userInfo = notification.userInfo as NSDictionary?, + let serverUrl = userInfo["serverUrl"] as? String, + let account = userInfo["account"] as? String + else { return } + + if account == self.session.account, serverUrl == self.serverUrl { + reloadDataSource() + } else { + collectionView?.reloadData() + } + } + + @objc func triggerProgressTask(_ notification: NSNotification) { + guard let userInfo = notification.userInfo as NSDictionary?, + let progressNumber = userInfo["progress"] as? NSNumber, + let totalBytes = userInfo["totalBytes"] as? Int64, + let totalBytesExpected = userInfo["totalBytesExpected"] as? Int64, + let ocId = userInfo["ocId"] as? String, + let ocIdTransfer = userInfo["ocIdTransfer"] as? String, + let session = userInfo["session"] as? String + else { return } + + let chunk: Int = userInfo["chunk"] as? Int ?? 0 + let e2eEncrypted: Bool = userInfo["e2eEncrypted"] as? Bool ?? false + + let transfer = NCTransferProgress.shared.append(NCTransferProgress.Transfer(ocId: ocId, ocIdTransfer: ocIdTransfer, session: session, chunk: chunk, e2eEncrypted: e2eEncrypted, progressNumber: progressNumber, totalBytes: totalBytes, totalBytesExpected: totalBytesExpected)) + +// DispatchQueue.main.async { + if self.headerMenuTransferView && (chunk > 0 || e2eEncrypted) { + if NCNetworking.shared.transferInForegorund?.ocId == ocId { + NCNetworking.shared.transferInForegorund?.progress = progressNumber.floatValue + } else { + NCNetworking.shared.transferInForegorund = NCNetworking.TransferInForegorund(ocId: ocId, progress: progressNumber.floatValue) + self.collectionView.reloadData() + } + self.headerMenu?.progressTransfer.progress = transfer.progressNumber.floatValue + } else { + guard let indexPath = self.dataSource.getIndexPathMetadata(ocId: ocId), + let cell = self.collectionView?.cellForItem(at: indexPath), + let cell = cell as? NCCellProtocol else { return } + if progressNumber.floatValue == 1 && !(cell is NCTransferCell) { + cell.fileProgressView?.isHidden = true + cell.fileProgressView?.progress = .zero + cell.setButtonMore(named: NCGlobal.shared.buttonMoreMore, image: NCImageCache.images.buttonMore) + if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) { + cell.writeInfoDateSize(date: metadata.date, size: metadata.size) + } else { + cell.fileInfoLabel?.text = "" + cell.fileSubinfoLabel?.text = "" + } + } else { + cell.fileProgressView?.isHidden = false + cell.fileProgressView?.progress = progressNumber.floatValue + cell.setButtonMore(named: NCGlobal.shared.buttonMoreStop, image: NCImageCache.images.buttonStop) + let status = userInfo["status"] as? Int ?? NCGlobal.shared.metadataStatusNormal + if status == NCGlobal.shared.metadataStatusDownloading { + cell.fileInfoLabel?.text = self.utilityFileSystem.transformedSize(totalBytesExpected) + cell.fileSubinfoLabel?.text = self.infoLabelsSeparator + "↓ " + self.utilityFileSystem.transformedSize(totalBytes) + } else if status == NCGlobal.shared.metadataStatusUploading { + if totalBytes > 0 { + cell.fileInfoLabel?.text = self.utilityFileSystem.transformedSize(totalBytesExpected) + cell.fileSubinfoLabel?.text = self.infoLabelsSeparator + "↑ " + self.utilityFileSystem.transformedSize(totalBytes) + } else { + cell.fileInfoLabel?.text = self.utilityFileSystem.transformedSize(totalBytesExpected) + cell.fileSubinfoLabel?.text = self.infoLabelsSeparator + "↑ …" + } + } + } + } +// } + } + + @objc func updateShare(_ notification: NSNotification) { + if isSearchingMode { + networkSearch() + } else { +// self.dataSource.removeAll() + getServerData() + } + } + + @objc func updateIcons() { + collectionView.reloadData() +// reloadDataSource() + } + + // MARK: - Layout + + func setNavigationLeftItems() { + navigationItem.title = titleCurrentFolder + } func getNavigationTitle() -> String { let tblAccount = self.database.getTableAccount(predicate: NSPredicate(format: "account == %@", session.account)) @@ -577,6 +1104,42 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS self.navigationItem.titleView = nil self.navigationItem.title = self.titleCurrentFolder } + + func accountSettingsDidDismiss(tableAccount: tableAccount?, controller: NCMainTabBarController?) { } + + func resetPlusButtonAlpha(animated: Bool = true) { } + + func isHiddenPlusButton(_ isHidden: Bool) { } + + // MARK: - Empty + + func emptyDataSetView(_ view: NCEmptyView) { + + self.emptyDataSet?.setOffset(getHeaderHeight()) + if isSearchingMode { + view.emptyImage.image = UIImage(named: "search")?.image(color: .gray, size: UIScreen.main.bounds.width) + if self.dataSourceTask?.state == .running { + view.emptyTitle.text = NSLocalizedString("_search_in_progress_", comment: "") + } else { + view.emptyTitle.text = NSLocalizedString("_search_no_record_found_", comment: "") + } + view.emptyDescription.text = NSLocalizedString("_search_instruction_", comment: "") + } else if self.dataSourceTask?.state == .running { + view.emptyImage.image = UIImage(named: "networkInProgress")?.image(color: .gray, size: UIScreen.main.bounds.width) + view.emptyTitle.text = NSLocalizedString("_request_in_progress_", comment: "") + view.emptyDescription.text = "" + } else { + if serverUrl.isEmpty { + view.emptyImage.image = emptyImage + view.emptyTitle.text = NSLocalizedString(emptyTitle, comment: "") + view.emptyDescription.text = NSLocalizedString(emptyDescription, comment: "") + } else { + view.emptyImage.image = UIImage(named: "folder_nmcloud") + view.emptyTitle.text = NSLocalizedString("_files_no_files_", comment: "") + view.emptyDescription.text = NSLocalizedString("_no_file_pull_down_", comment: "") + } + } + } // MARK: - SEARCH @@ -630,6 +1193,10 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS // MARK: - TAP EVENT + func tapMoreListItem(with ocId: String, ocIdTransfer: String, namedButtonMore: String, image: UIImage?, sender: Any) { + tapMoreGridItem(with: ocId, ocIdTransfer: ocIdTransfer, namedButtonMore: namedButtonMore, image: image, sender: sender) + } + func tapMoreListItem(with ocId: String, ocIdTransfer: String, image: UIImage?, sender: Any) { tapMoreGridItem(with: ocId, ocIdTransfer: ocIdTransfer, image: image, sender: sender) } @@ -639,15 +1206,38 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS } func tapShareListItem(with ocId: String, ocIdTransfer: String, sender: Any) { + if isEditMode { return } guard let metadata = self.database.getMetadataFromOcId(ocId) else { return } NCCreate().createShare(viewController: self, metadata: metadata, page: .sharing) +// NCDownloadAction.shared.openShare(viewController: self, metadata: metadata, page: .sharing) + TealiumHelper.shared.trackEvent(title: "magentacloud-app.filebrowser.sharing", data: ["": ""]) + appDelegate.adjust.trackEvent(TriggerEvent(Sharing.rawValue)) + + } + + func tapMoreGridItem(with ocId: String, ocIdTransfer: String, namedButtonMore: String, image: UIImage?, sender: Any) { + if isEditMode { return } + guard let metadata = self.database.getMetadataFromOcId(ocId) else { return } +// toggleMenu(metadata: metadata, image: image) + if namedButtonMore == NCGlobal.shared.buttonMoreMore || namedButtonMore == NCGlobal.shared.buttonMoreLock { + toggleMenu(metadata: metadata, image: image) + } else if namedButtonMore == NCGlobal.shared.buttonMoreStop { + Task { + await cancelSession(metadata: metadata) + } + } } func tapMoreGridItem(with ocId: String, ocIdTransfer: String, image: UIImage?, sender: Any) { guard let metadata = self.database.getMetadataFromOcId(ocId) else { return } - toggleMenu(metadata: metadata, image: image, sender: sender) +// toggleMenu(metadata: metadata, image: image, sender: sender) + Task { + await cancelSession(metadata: metadata) + } } + + func longPressMoreListItem(with ocId: String, ocIdTransfer: String, gestureRecognizer: UILongPressGestureRecognizer) { } func tapRichWorkspace(_ sender: Any) { if let navigationController = UIStoryboard(name: "NCViewerRichWorkspace", bundle: nil).instantiateInitialViewController() as? UINavigationController { @@ -673,6 +1263,34 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS func tapRecommendations(with metadata: tableMetadata) { didSelectMetadata(metadata, withOcIds: false) } + + func tapButtonSwitch(_ sender: Any) { + guard !isTransitioning else { return } + isTransitioning = true + + guard let layoutForView = NCManageDatabase.shared.getLayoutForView(account: session.account, key: layoutKey, serverUrl: serverUrl) else { return } + + if layoutForView.layout == NCGlobal.shared.layoutGrid { + layoutForView.layout = NCGlobal.shared.layoutList + } else { + layoutForView.layout = NCGlobal.shared.layoutGrid + } + self.layoutForView = NCManageDatabase.shared.setLayoutForView(layoutForView: layoutForView) + self.collectionView.reloadData() + self.collectionView.collectionViewLayout.invalidateLayout() + self.collectionView.setCollectionViewLayout(layoutForView.layout == NCGlobal.shared.layoutList ? self.listLayout : self.gridLayout, animated: true) {_ in self.isTransitioning = false } + } + + func tapButtonOrder(_ sender: Any) { + let sortMenu = NCSortMenu() + sortMenu.toggleMenu(viewController: self, account: session.account, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl) + } + + func tapButtonTransfer(_ sender: Any) { } + + func longPressListItem(with objectId: String, indexPath: IndexPath, gestureRecognizer: UILongPressGestureRecognizer) { + } + func longPressListItem(with ocId: String, ocIdTransfer: String, namedButtonMore: String, gestureRecognizer: UILongPressGestureRecognizer) { } func longPressListItem(with ocId: String, ocIdTransfer: String, gestureRecognizer: UILongPressGestureRecognizer) { } @@ -714,6 +1332,12 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS } } + // MARK: - Transfer Delegate + + func transferProgressDidUpdate(progress: Float, totalBytes: Int64, totalBytesExpected: Int64, fileName: String, serverUrl: String) { } + + func tranferChange(status: String, metadata: tableMetadata, error: NKError) { } + // MARK: - Menu Item override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { @@ -828,6 +1452,40 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS func getServerData(forced: Bool = false) async { } + @objc func reloadDataSource() { + + // get auto upload folder + autoUploadFileName = NCManageDatabase.shared.getAccountAutoUploadFileName() + autoUploadDirectory = NCManageDatabase.shared.getAccountAutoUploadDirectory(urlBase: session.urlBase, userId: session.userId, account: session.account) + + // get layout for view + layoutForView = NCManageDatabase.shared.getLayoutForView(account: session.account, key: layoutKey, serverUrl: serverUrl) + // set GroupField for Grid + if !isSearchingMode && layoutForView?.layout == NCGlobal.shared.layoutGrid { + groupByField = "classFile" + } else { + groupByField = "name" + } + if isSearchingMode { + isDirectoryEncrypted = false + } else { + isDirectoryEncrypted = NCUtilityFileSystem().isDirectoryE2EE(session: session, serverUrl: serverUrl) + } + + DispatchQueue.main.async { +// UIView.transition(with: self.collectionView, +// duration: 0.20, +// options: .transitionCrossDissolve, +// animations: { self.collectionView.reloadData() }, +// completion: nil) +// +// (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() + self.refreshControl.endRefreshing() + self.collectionView.reloadData() + self.setNavigationRightItems() + } + } + @objc func networkSearch() { guard !networkSearchInProgress else { return @@ -996,18 +1654,28 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS } } + func isHeaderMenuTransferViewEnabled() -> [tableMetadata]? { + if headerMenuTransferView, + NCNetworking.shared.isOnline, + let results = database.getResultsMetadatas(predicate: NSPredicate(format: "status IN %@", [global.metadataStatusWaitUpload, global.metadataStatusUploading])), + !results.isEmpty { + return Array(results) + } + return nil + } + func sizeForHeaderInSection(section: Int) -> CGSize { var height: CGFloat = 0 let isLandscape = view.bounds.width > view.bounds.height let isIphone = UIDevice.current.userInterfaceIdiom == .phone if self.dataSource.isEmpty() { - height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: emptyDataPortaitOffset, landscapeOffset: emptyDataLandscapeOffset) + height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: emptyDataPortaitOffset, landscapeOffset: emptyDataLandscapeOffset, isHeaderMenuTransferViewEnabled: isHeaderMenuTransferViewEnabled() != nil) } else if isEditMode || (isLandscape && isIphone) { return CGSize.zero } else { - let (heightHeaderRichWorkspace, heightHeaderRecommendations, heightHeaderSection) = getHeaderHeight(section: section) - height = heightHeaderRichWorkspace + heightHeaderRecommendations + heightHeaderSection + let (heightHeaderCommands, heightHeaderRichWorkspace, heightHeaderSection) = getHeaderHeight(section: section) + height = heightHeaderCommands + heightHeaderRichWorkspace + heightHeaderSection } return CGSize(width: collectionView.frame.width, height: height) @@ -1016,25 +1684,21 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS // MARK: - Footer size func sizeForFooterInSection(section: Int) -> CGSize { - guard let controller else { - return CGSize.zero - } let sections = dataSource.numberOfSections() - let bottomAreaInsets: CGFloat = controller.tabBar.safeAreaInsets.bottom == 0 ? 34 : 0 - let height = controller.tabBar.frame.height + bottomAreaInsets - - if isEditMode { - return CGSize(width: collectionView.frame.width, height: 90 + height) - } - - if isSearchingMode { - return CGSize(width: collectionView.frame.width, height: 50) - } + let metadataForSection = self.dataSource.getMetadataForSection(section) + let isPaginated = metadataForSection?.lastSearchResult?.isPaginated ?? false + let metadatasCount: Int = metadataForSection?.lastSearchResult?.entries.count ?? 0 + var size = CGSize(width: collectionView.frame.width, height: 0) if section == sections - 1 { - return CGSize(width: collectionView.frame.width, height: height) + size.height += 85 } else { - return CGSize(width: collectionView.frame.width, height: 0) + size.height += 1 + } + + if isSearchingMode && isPaginated && metadatasCount > 0 { + size.height += 30 } + return size } } diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift index 36b5b715c1..688b09e70c 100644 --- a/iOSClient/NCGlobal.swift +++ b/iOSClient/NCGlobal.swift @@ -4,18 +4,34 @@ import UIKit -final class NCGlobal: Sendable { - static let shared = NCGlobal() - - init() { } - +/// Used for read/write in Realm +var isAppSuspending: Bool = false +/// Used for know if the app in in Background mode +var isAppInBackground: Bool = false + +class NCGlobal: NSObject, @unchecked Sendable { + @objc static let shared = NCGlobal() + + override init() { + super.init() + NotificationCenter.default.addObserver(forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: .main) { _ in + isAppSuspending = true + isAppInBackground = true + } + + NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: .main) { _ in + isAppSuspending = false + isAppInBackground = false + } + } + // ENUM // public enum TypeFilterScanDocument: String { case document = "document" case original = "original" } - + // Directory on Group // let directoryProviderStorage = "File Provider Storage" @@ -24,13 +40,13 @@ final class NCGlobal: Sendable { let appDatabaseNextcloud = "Library/Application Support/Nextcloud" let appScan = "Library/Application Support/Scan" let appUserData = "Library/Application Support/UserData" - + // Service // let metadataKeyedUnarchiver = "it.twsweb.nextcloud.metadata" let refreshTask = "com.nextcloud.refreshTask" let processingTask = "com.nextcloud.processingTask" - + // App // let appName = "files" @@ -39,9 +55,10 @@ final class NCGlobal: Sendable { let spreedName = "spreed" let twoFactorNotificatioName = "twofactor_nextcloud_notification" let termsOfServiceName = "terms_of_service" - + // Nextcloud version // + let nextcloudVersion12: Int = 12 let nextcloudVersion18: Int = 18 let nextcloudVersion20: Int = 20 let nextcloudVersion23: Int = 23 @@ -52,21 +69,28 @@ final class NCGlobal: Sendable { let nextcloudVersion28: Int = 28 let nextcloudVersion30: Int = 30 let nextcloudVersion31: Int = 31 - + // Nextcloud unsupported // let nextcloud_unsupported_version: Int = 20 +// let nextcloud_unsupported_version: Int = 17 + // Intro selector // - let introLogin: Int = 0 - let introSignUpWithProvider: Int = 1 - + @objc let introLogin: Int = 0 + let introSignup: Int = 1 + // let introSignUpWithProvider: Int = 1 + + // Varie size GUI + // + @objc let heightCellSettings: CGFloat = 50 + // Avatar // let avatarSize: Int = 128 * Int(UIScreen.main.scale) let avatarSizeRounded: Int = 128 - + // Preview size // let size1024: CGSize = CGSize(width: 1024, height: 1024) @@ -76,50 +100,50 @@ final class NCGlobal: Sendable { let previewExt1024 = ".1024.preview.jpg" let previewExt512 = ".512.preview.jpg" let previewExt256 = ".256.preview.jpg" - + func getSizeExtension(column: Int) -> String { if column == 0 { return previewExt256 } let width = UIScreen.main.bounds.width / CGFloat(column) - - switch (width * 4) { - case 0...384: - return previewExt256 - case 385...768: - return previewExt512 - default: - return previewExt1024 - } + + switch (width * 4) { + case 0...384: + return previewExt256 + case 385...768: + return previewExt512 + default: + return previewExt1024 + } } - + // E2EE // let e2eePassphraseTest = "more over television factory tendency independence international intellectual impress interest sentence pony" - let e2eeVersions = ["1.1", "1.2", "2.0"] + @objc let e2eeVersions = ["1.1", "1.2", "2.0"] let e2eeVersionV11 = "1.1" let e2eeVersionV12 = "1.2" let e2eeVersionV20 = "2.0" - + // CHUNK let chunkSizeMBCellular = 10000000 let chunkSizeMBEthernetOrWiFi = 100000000 - + // Video // let maxHTTPCache: Int64 = 10000000000 // 10 GB let fileNameVideoEncoded: String = "video_encoded.mp4" - + // NCViewerProviderContextMenu // let maxAutoDownload: UInt64 = 50000000 // 50MB let maxAutoDownloadCellular: UInt64 = 10000000 // 10MB - + // Layout // let layoutList = "typeLayoutList" let layoutGrid = "typeLayoutGrid" let layoutPhotoRatio = "typeLayoutPhotoRatio" let layoutPhotoSquare = "typeLayoutPhotoSquare" - + let layoutViewTrash = "LayoutTrash" let layoutViewOffline = "LayoutOffline" let layoutViewFavorite = "LayoutFavorite" @@ -129,16 +153,47 @@ final class NCGlobal: Sendable { let layoutViewShareExtension = "LayoutShareExtension" let layoutViewGroupfolders = "LayoutGroupfolders" let layoutViewMedia = "LayoutMedia" + let layoutViewMove = "LayoutMove" + // Button Type in Cell list/grid // let buttonMoreMore = "more" let buttonMoreLock = "moreLock" - + let buttonMoreStop = "stop" + + + // Standard height sections header/footer + // + let heightButtonsView: CGFloat = 50 + let heightHeaderTransfer: CGFloat = 50 + let heightSection: CGFloat = 30 + let heightFooter: CGFloat = 1 + let heightFooterButton: CGFloat = 30 + let endHeightFooter: CGFloat = 85 + + + // Text - OnlyOffice - Collabora - QuickLook + // + let editorText = "text" + let editorOnlyoffice = "onlyoffice" + let editorCollabora = "collabora" + let editorQuickLook = "quicklook" + + let onlyofficeDocx = "onlyoffice_docx" + let onlyofficeXlsx = "onlyoffice_xlsx" + let onlyofficePptx = "onlyoffice_pptx" + + // Template + // + let templateDocument = "document" + let templateSpreadsheet = "spreadsheet" + let templatePresentation = "presentation" + // Rich Workspace // let fileNameRichWorkspace = "Readme.md" - + // ContentPresenter // let dismissAfterSecond: TimeInterval = 5 @@ -156,6 +211,7 @@ final class NCGlobal: Sendable { let errorConflict: Int = 409 let errorPreconditionFailed: Int = 412 let errorUnsupportedMediaType: Int = 415 + let errorWebDAVLocked: Int = 423 let errorInternalServerError: Int = 500 let errorMaintenance: Int = 503 let errorQuota: Int = 507 @@ -183,6 +239,7 @@ final class NCGlobal: Sendable { let errorE2EEKeyChecksums: Int = -98002 let errorE2EEKeyEncodeMetadata: Int = -98003 let errorE2EEKeyDecodeMetadataV12: Int = -98004 + let errorE2EEKeyDecodeMetadata: Int = -98004 let errorE2EEKeyVerifySignature: Int = -98005 let errorE2EEKeyCiphertext: Int = -98006 let errorE2EEKeyFiledropCiphertext: Int = -98007 @@ -209,6 +266,7 @@ final class NCGlobal: Sendable { let selectorDownloadFile = "downloadFile" let selectorUploadAutoUpload = "uploadAutoUpload" + let selectorUploadAutoUploadAll = "uploadAutoUploadAll" let selectorUploadFile = "uploadFile" let selectorUploadFileNODelete = "UploadFileNODelete" let selectorUploadFileShareExtension = "uploadFileShareExtension" @@ -217,7 +275,9 @@ final class NCGlobal: Sendable { let selectorSaveAsScan = "saveAsScan" let selectorOpenDetail = "openDetail" let selectorSynchronizationOffline = "synchronizationOffline" - + let selectorPrint = "print" + let selectorDeleteFile = "deleteFile" + // Metadata : Status // // 0 normal @@ -226,69 +286,91 @@ final class NCGlobal: Sendable { // ± 3 error // let metadataStatusNormal: Int = 0 - + let metadataStatusWaitDownload: Int = -1 let metadataStatusDownloading: Int = -2 let metadataStatusDownloadError: Int = -3 - + let metadataStatusWaitUpload: Int = 1 let metadataStatusUploading: Int = 2 let metadataStatusUploadError: Int = 3 - + let metadataStatusWaitCreateFolder: Int = 10 let metadataStatusWaitDelete: Int = 11 let metadataStatusWaitRename: Int = 12 let metadataStatusWaitFavorite: Int = 13 let metadataStatusWaitCopy: Int = 14 let metadataStatusWaitMove: Int = 15 - + let metadataStatusUploadingAllMode = [1,2,3] let metadataStatusDownloadingAllMode = [-1, -2, -3] let metadataStatusForScreenAwake = [-1, -2, 1, 2] + let metadataStatusInTransfer = [-1, -2, 1, 2] + let metadataStatusFileDown = [-1, -2, -3] let metadataStatusHideInView = [1, 2, 3, 11] + let metadataStatusHideInFileExtension = [1, 2, 3, 10, 11] let metadataStatusWaitWebDav = [10, 11, 12, 13, 14, 15] let metadataStatusTransfers = [-2, -3, 2, 3, 10, 11, 12, 13, 14, 15] + let metadataStatusObserveNetworkingProcess = [-1, 1, 10, 11, 12, 13, 14, 15] + let metadataStatusObserveTrasfers = [-2, 2, 10, 11, 12, 13, 14, 15] let metadatasStatusInWaiting = [-1, 1, 10, 11, 12, 13, 14, 15] let metadatasStatusInProgress = [-2, 2] + // Hidden files included in the read + // + let includeHiddenFiles: [String] = [".LivePhoto"] + // Auto upload subfolder granularity // - let subfolderGranularityDaily = 2 - let subfolderGranularityMonthly = 1 - let subfolderGranularityYearly = 0 - + @objc let subfolderGranularityDaily = 2 + @objc let subfolderGranularityMonthly = 1 + @objc let subfolderGranularityYearly = 0 + // Notification Center // - let notificationCenterChangeUser = "changeUser" // userInfo: account, controller - let notificationCenterChangeTheming = "changeTheming" // userInfo: account + @objc let notificationCenterChangeUser = "changeUser" + let notificationCenterChangeTheming = "changeTheming" + @objc let notificationCenterApplicationDidEnterBackground = "applicationDidEnterBackground" + @objc let notificationCenterApplicationDidBecomeActive = "applicationDidBecomeActive" + @objc let notificationCenterApplicationWillResignActive = "applicationWillResignActive" + @objc let notificationCenterApplicationWillEnterForeground = "applicationWillEnterForeground" + + + @objc let notificationCenterInitialize = "initialize" let notificationCenterRichdocumentGrabFocus = "richdocumentGrabFocus" let notificationCenterReloadDataNCShare = "reloadDataNCShare" + let notificationCenterDidCreateShareLink = "didCreateShareLink" + let notificationCenterCloseRichWorkspaceWebView = "closeRichWorkspaceWebView" let notificationCenterReloadAvatar = "reloadAvatar" + let notificationCenterReloadHeader = "reloadHeader" let notificationCenterClearCache = "clearCache" + let notificationCenterChangeLayout = "changeLayout" // userInfo: account, serverUrl, layoutForView let notificationCenterCheckUserDelaultErrorDone = "checkUserDelaultErrorDone" // userInfo: account, controller let notificationCenterServerDidUpdate = "serverDidUpdate" // userInfo: account let notificationCenterNetworkReachability = "networkReachability" + let notificationCenterCreateMediaCacheEnded = "createMediaCacheEnded" let notificationCenterUpdateNotification = "updateNotification" + let notificationCenterReloadDataSource = "reloadDataSource" // userInfo: serverUrl?, clearDataSource let notificationCenterGetServerData = "getServerData" // userInfo: serverUrl? - + let notificationCenterChangeStatusFolderE2EE = "changeStatusFolderE2EE" // userInfo: serverUrl - + let notificationCenterDownloadStartFile = "downloadStartFile" // userInfo: ocId, ocIdTransfer, session, serverUrl, account let notificationCenterDownloadedFile = "downloadedFile" // userInfo: ocId, ocIdTransfer, session, session, serverUrl, account, selector, error let notificationCenterDownloadCancelFile = "downloadCancelFile" // userInfo: ocId, ocIdTransfer, session, serverUrl, account - + let notificationCenterUploadStartFile = "uploadStartFile" // userInfo: ocId, ocIdTransfer, session, serverUrl, account, fileName, sessionSelector let notificationCenterUploadedFile = "uploadedFile" // userInfo: ocId, ocIdTransfer, session, serverUrl, account, fileName, ocIdTransfer, error let notificationCenterUploadedLivePhoto = "uploadedLivePhoto" // userInfo: ocId, ocIdTransfer, session, serverUrl, account, fileName, ocIdTransfer, error let notificationCenterUploadCancelFile = "uploadCancelFile" // userInfo: ocId, ocIdTransfer, session, serverUrl, account - + let notificationCenterProgressTask = "progressTask" // userInfo: account, ocId, ocIdTransfer, session, serverUrl, status, chunk, e2eEncrypted, progress, totalBytes, totalBytesExpected - + let notificationCenterUpdateBadgeNumber = "updateBadgeNumber" // userInfo: counterDownload, counterUpload - + let notificationCenterCreateFolder = "createFolder" // userInfo: ocId, serverUrl, account, withPush, sceneIdentifier let notificationCenterDeleteFile = "deleteFile" // userInfo: [ocId], error let notificationCenterCopyMoveFile = "copyMoveFile" // userInfo: [ocId] serverUrl, account, dragdrop, type (copy, move) @@ -297,20 +379,32 @@ final class NCGlobal: Sendable { let notificationCenterRenameFile = "renameFile" // userInfo: serverUrl, account, error let notificationCenterFavoriteFile = "favoriteFile" // userInfo: ocId, serverUrl let notificationCenterFileExists = "fileExists" // userInfo: ocId, fileExists - + let notificationCenterMenuSearchTextPDF = "menuSearchTextPDF" let notificationCenterMenuGotToPageInPDF = "menuGotToPageInPDF" - + let notificationCenterOpenMediaDetail = "openMediaDetail" // userInfo: ocId - + let notificationCenterDismissScanDocument = "dismissScanDocument" let notificationCenterDismissUploadAssets = "dismissUploadAssets" - + let notificationCenterEnableSwipeGesture = "enableSwipeGesture" let notificationCenterDisableSwipeGesture = "disableSwipeGesture" - + + let notificationCenterShareViewIn = "ShareViewIn" + let notificationCenterShareAdvancePermission = "ShareAdvancePermission" + let notificationCenterShareSendEmail = "ShareSendEmail" + let notificationCenterShareUnshare = "ShareUnshare" + let notificationCenterStatusReadOnly = "statusReadOnly" + let notificationCenterStatusEditing = "statusEditing" + let notificationCenterStatusFileDrop = "statusFileDrop" + let notificationCenterPlayerIsPlaying = "playerIsPlaying" let notificationCenterPlayerStoppedPlaying = "playerStoppedPlaying" + + let notificationCenterUpdateShare = "updateShare" + let notificationCenterShareCountsUpdated = "shareCountsUpdated" + let notificationCenterUpdateIcons = "updateIcons" // Networking Status let networkingStatusCreateFolder = "statusCreateFolder" @@ -336,6 +430,7 @@ final class NCGlobal: Sendable { let tipScanAddImage = "tipScanAddImage" let tipMediaDetailView = "tipMediaDetailView" let tipAutoUploadButton = "tipAutoUploadButton" + let tipAutoUpload = "tipAutoUpload" // ACTION // @@ -366,10 +461,31 @@ final class NCGlobal: Sendable { let configuration_disable_multiaccount = "disable_multiaccount" let configuration_disable_crash_service = "disable_crash_service" let configuration_disable_log = "disable_log" + let configuration_disable_manage_account = "disable_manage_account" let configuration_disable_more_external_site = "disable_more_external_site" let configuration_disable_openin_file = "disable_openin_file" let configuration_enforce_passcode_lock = "enforce_passcode_lock" - + + // CAPABILITIES + // + var capabilityServerVersionMajor: Int = 0 + @objc var capabilityServerVersion: String = "" + @objc var capabilityThemingName: String = "" + @objc var capabilityThemingSlogan: String = "" + + @objc var capabilityE2EEEnabled: Bool = false + @objc var capabilityE2EEApiVersion: String = "" + + var capabilityRichdocumentsEnabled: Bool = false + var capabilityRichdocumentsMimetypes: [String] = [] + var capabilityActivity: [String] = [] + var capabilityNotification: [String] = [] + + @objc var capabilityUserStatusEnabled: Bool = false + var isLivePhotoServerAvailable: Bool { // NC28 + return capabilityServerVersionMajor >= nextcloudVersion28 + } + // MORE NEXTCLOUD APPS // let talkSchemeUrl = "nextcloudtalk://" @@ -377,40 +493,59 @@ final class NCGlobal: Sendable { let talkAppStoreUrl = "https://apps.apple.com/in/app/nextcloud-talk/id1296825574" let notesAppStoreUrl = "https://apps.apple.com/in/app/nextcloud-notes/id813973264" let moreAppsUrl = "itms-apps://search.itunes.apple.com/WebObjects/MZSearch.woa/wa/search?media=software&term=nextcloud" - + // SNAPSHOT PREVIEW // let defaultSnapshotConfiguration = "DefaultPreviewConfiguration" - + +// // FORBIDDEN CHARACTERS +// // +// // TODO: Remove this +// let forbiddenCharacters = ["/", "\\", ":", "\"", "|", "?", "*", "<", ">"] + // DIAGNOSTICS CLIENTS // let diagnosticIssueSyncConflicts = "sync_conflicts" let diagnosticIssueProblems = "problems" let diagnosticIssueVirusDetected = "virus_detected" let diagnosticIssueE2eeErrors = "e2ee_errors" - + let diagnosticProblemsForbidden = "CHARACTERS_FORBIDDEN" let diagnosticProblemsBadResponse = "BAD_SERVER_RESPONSE" let diagnosticProblemsUploadServerError = "UploadError.SERVER_ERROR" - + // MEDIA LAYOUT // let mediaLayoutRatio = "mediaLayoutRatio" let mediaLayoutSquare = "mediaLayoutSquare" - + // DRAG & DROP // let metadataOcIdDataRepresentation = "text/com.nextcloud.ocId" - + // GROUP AMIN // let groupAdmin = "admin" - // TASK DESCRIPTION + // DATA TASK DESCRIPTION // let taskDescriptionRetrievesProperties = "retrievesProperties" let taskDescriptionSynchronization = "synchronization" - + let taskDescriptionDeleteFileOrFolder = "deleteFileOrFolder" + + // MoEngage App Version + // + let moEngageAppVersion = 854 + + // Filename Mask and Type + // + let keyFileNameMask = "fileNameMask" + let keyFileNameType = "fileNameType" + let keyFileNameAutoUploadMask = "fileNameAutoUploadMask" + let keyFileNameAutoUploadType = "fileNameAutoUploadType" + let keyFileNameOriginal = "fileNameOriginal" + let keyFileNameOriginalAutoUpload = "fileNameOriginalAutoUpload" + // LOG TAG // let logTagTask = "BGT" From 1341f0a80709248bcc851b073e62a848d60e22e8 Mon Sep 17 00:00:00 2001 From: harshada-15-tsys Date: Mon, 15 Dec 2025 12:37:14 +0530 Subject: [PATCH 6/6] NMC 2267 - Rename file/folder customisation changes --- .../NCCollectionViewCommon.swift | 753 ++---------------- iOSClient/NCGlobal.swift | 225 ++---- iOSClient/Rename file/NCRenameFile.swift | 16 +- 3 files changed, 124 insertions(+), 870 deletions(-) diff --git a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift index 60e6c75e9c..521976e570 100644 --- a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift +++ b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift @@ -33,7 +33,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS var serverUrl: String = "" var isEditMode = false var isDirectoryE2EE = false - var isDirectoryEncrypted = false var fileSelect: [String] = [] var metadataFolder: tableMetadata? var richWorkspaceText: String? @@ -43,7 +42,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS var networkSearchInProgress: Bool = false var layoutForView: NCDBLayoutForView? var searchDataSourceTask: URLSessionTask? - var dataSourceTask: URLSessionTask? var providers: [NKSearchProvider]? var searchResults: [NKSearchResult]? var listLayout = NCListLayout() @@ -54,9 +52,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS var tabBarSelect: NCCollectionViewCommonSelectTabBar? var attributesZoomIn: UIMenuElement.Attributes = [] var attributesZoomOut: UIMenuElement.Attributes = [] - let maxImageGrid: CGFloat = 7 - // var headerMenu: NCSectionFirstHeader? - var tipViewAccounts: EasyTipView? var syncMetadatasTask: Task? var tipViewAutoUpload: EasyTipView? @@ -65,6 +60,8 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS var headerMenuButtonsView: Bool = true var headerRichWorkspaceDisable: Bool = false + var selectableDataSource: [RealmSwiftObject] { dataSource.getMetadataSourceForAllSections() } + // DECLARE var layoutKey = "" var titleCurrentFolder = "" @@ -72,11 +69,8 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS var enableSearchBar: Bool = false var headerRichWorkspaceDisable: Bool = false - var groupByField = "name" - var emptyImageName: String? var emptyImageColors: [UIColor]? - var emptyImage: UIImage? var emptyTitle: String = "" var emptyDescription: String = "" @@ -95,11 +89,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS var numberOfColumns: Int = 0 var lastNumberOfColumns: Int = 0 - var isTransitioning: Bool = false - var selectableDataSource: [RealmSwiftObject] { dataSource.getMetadataSourceForAllSections() } - var pushed: Bool = false - var emptyDataSet: NCEmptyDataSet? - let heightHeaderRecommendations: CGFloat = 160 let heightHeaderSection: CGFloat = 30 @@ -146,16 +135,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS (self.tabBarController as? NCMainTabBarController)?.sceneIdentifier ?? "" } - var defaultPredicate: NSPredicate { - let predicate = NSPredicate(format: "account == %@ AND serverUrl == %@ AND NOT (status IN %@) AND NOT (livePhotoFile != '' AND classFile == %@)", session.account, self.serverUrl, NCGlobal.shared.metadataStatusHideInView, NKCommon.TypeClassFile.video.rawValue) - return predicate - } - - var personalFilesOnlyPredicate: NSPredicate { - let predicate = NSPredicate(format: "account == %@ AND serverUrl == %@ AND (ownerId == %@ || ownerId == '') AND mountType == '' AND NOT (status IN %@) AND NOT (livePhotoFile != '' AND classFile == %@)", session.account, self.serverUrl, session.userId, global.metadataStatusHideInView, NKCommon.TypeClassFile.video.rawValue) - return predicate - } - var isNumberOfItemsInAllSectionsNull: Bool { var totalItems = 0 for section in 0.. Bool { - let appVersion = Bundle.main.infoDictionary?["CFBundleInfoDictionaryVersion"] as? String ?? "" - let currentVersion = UserDefaults.standard.string(forKey: "CurrentAppVersion") - return currentVersion != appVersion - } - func redirectToPrivacyViewController() { - let storyBoard: UIStoryboard = UIStoryboard(name: "NCSettings", bundle: nil) - let newViewController = storyBoard.instantiateViewController(withIdentifier: "privacySettingsNavigation") as! UINavigationController - newViewController.modalPresentationStyle = .fullScreen - self.present(newViewController, animated: true, completion: nil) + removeImageCache(metadatas: self.dataSource.getMetadatas()) } func presentationControllerDidDismiss( _ presentationController: UIPresentationController) { @@ -481,6 +359,23 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS override var canBecomeFirstResponder: Bool { return true } + + @objc func updateIcons() { + collectionView.reloadData() + } + + func isApplicationUpdated() -> Bool { + let appVersion = Bundle.main.infoDictionary?["CFBundleInfoDictionaryVersion"] as? String ?? "" + let currentVersion = UserDefaults.standard.string(forKey: "CurrentAppVersion") + return currentVersion != appVersion + } + + func redirectToPrivacyViewController() { + let storyBoard: UIStoryboard = UIStoryboard(name: "NCSettings", bundle: nil) + let newViewController = storyBoard.instantiateViewController(withIdentifier: "privacySettingsNavigation") as? UINavigationController + newViewController?.modalPresentationStyle = .fullScreen + self.present(newViewController!, animated: true, completion: nil) + } // MARK: - Transfer Delegate @@ -652,413 +547,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS self.present(alertController, animated: true) } } - - override func viewWillLayoutSubviews() { - super.viewWillLayoutSubviews() - - if let frame = tabBarController?.tabBar.frame { - tabBarSelect?.hostingController?.view.frame = frame - } - } - - // MARK: - NotificationCenter - -// @objc func applicationWillResignActive(_ notification: NSNotification) { -// self.resetPlusButtonAlpha() -// self.refreshControl.endRefreshing() -// } - - @objc func reloadAvatar(_ notification: NSNotification) { - DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { - self.showTipAccounts() - } - guard let userInfo = notification.userInfo as NSDictionary?, - let error = userInfo["error"] as? NKError, - error.errorCode != global.errorNotModified else { return } - /// Magentacloud branding changes hide user account button on left navigation bar - setNavigationLeftItems() - } - - @objc func changeTheming(_ notification: NSNotification) { - self.reloadDataSource() - } - - @objc func changeLayout(_ notification: NSNotification) { - guard let userInfo = notification.userInfo as NSDictionary?, - let account = userInfo["account"] as? String, - let serverUrl = userInfo["serverUrl"] as? String, - let layoutForView = userInfo["layoutForView"] as? NCDBLayoutForView, - account == session.account, - serverUrl == self.serverUrl - else { return } - - if self.layoutForView?.layout == layoutForView.layout { - self.layoutForView = self.database.setLayoutForView(layoutForView: layoutForView) - self.reloadDataSource() - return - } - - self.layoutForView = self.database.setLayoutForView(layoutForView: layoutForView) - layoutForView.layout = layoutForView.layout - self.layoutType = layoutForView.layout - - collectionView.reloadData() - - switch layoutForView.layout { - case global.layoutList: - self.collectionView.setCollectionViewLayout(self.listLayout, animated: true) - case global.layoutGrid: - self.collectionView.setCollectionViewLayout(self.gridLayout, animated: true) - case global.layoutPhotoSquare, global.layoutPhotoRatio: - self.collectionView.setCollectionViewLayout(self.mediaLayout, animated: true) - default: - break - } - - self.collectionView.collectionViewLayout.invalidateLayout() - -// (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() - } - - @objc func reloadDataSource(_ notification: NSNotification) { - if let userInfo = notification.userInfo as? NSDictionary { - if let serverUrl = userInfo["serverUrl"] as? String { - if serverUrl != self.serverUrl { - return - } - } - - if let clearDataSource = userInfo["clearDataSource"] as? Bool, clearDataSource { - self.dataSource.removeAll() - } - } - - reloadDataSource() - } - - @objc func getServerData(_ notification: NSNotification) { - if let userInfo = notification.userInfo as NSDictionary?, - let serverUrl = userInfo["serverUrl"] as? String { - if serverUrl != self.serverUrl { - return - } - } - - getServerData() - } - - @objc func reloadHeader(_ notification: NSNotification) { - guard let userInfo = notification.userInfo as NSDictionary?, - let account = userInfo["account"] as? String, - account == session.account - else { return } - - self.collectionView.reloadData() - } - - @objc func changeStatusFolderE2EE(_ notification: NSNotification) { - reloadDataSource() - } - - @objc func closeRichWorkspaceWebView() { - reloadDataSource() - } - - @objc func deleteFile(_ notification: NSNotification) { - guard let userInfo = notification.userInfo as NSDictionary?, - let error = userInfo["error"] as? NKError else { return } - - if error == .success { - if isSearchingMode { - return networkSearch() - } - - if isRecommendationActived { - Task.detached { - await NCNetworking.shared.createRecommendations(session: self.session) - } - } - } else { - NCContentPresenter().showError(error: error) - } - - reloadDataSource() - } - - @objc func copyMoveFile(_ notification: NSNotification) { - guard let userInfo = notification.userInfo as NSDictionary?, - let serverUrl = userInfo["serverUrl"] as? String, - let account = userInfo["account"] as? String, - account == session.account else { return } - - if isSearchingMode { - return networkSearch() - } - - if isRecommendationActived { - Task.detached { - await NCNetworking.shared.createRecommendations(session: self.session) - } - } - - if serverUrl == self.serverUrl { - reloadDataSource() - } - } - - @objc func renameFile(_ notification: NSNotification) { - guard let userInfo = notification.userInfo as NSDictionary?, - let account = userInfo["account"] as? String, - let serverUrl = userInfo["serverUrl"] as? String, - let error = userInfo["error"] as? NKError, - account == session.account - else { return } - - if error == .success { - if isSearchingMode { - return networkSearch() - } - - if isRecommendationActived { - Task.detached { - await NCNetworking.shared.createRecommendations(session: self.session) - } - } - } - - if serverUrl == self.serverUrl { - if error != .success { - NCContentPresenter().showError(error: error) - } - reloadDataSource() - } else { - collectionView.reloadData() - } - } - - @objc func createFolder(_ notification: NSNotification) { - guard let userInfo = notification.userInfo as NSDictionary?, - let ocId = userInfo["ocId"] as? String, - let account = userInfo["account"] as? String, - account == session.account, - let withPush = userInfo["withPush"] as? Bool, - let metadata = database.getMetadataFromOcId(ocId) - else { return } - - if isSearchingMode { - return networkSearch() - } - - if metadata.serverUrl + "/" + metadata.fileName == self.serverUrl { - reloadDataSource() - } else if withPush, metadata.serverUrl == self.serverUrl { - reloadDataSource() - if let sceneIdentifier = userInfo["sceneIdentifier"] as? String { - if sceneIdentifier == controller?.sceneIdentifier { - pushMetadata(metadata) - } - } else { - pushMetadata(metadata) - } - } - } - - @objc func favoriteFile(_ notification: NSNotification) { - if isSearchingMode { - return networkSearch() - } - - if self is NCFavorite { - return reloadDataSource() - } - - guard let userInfo = notification.userInfo as NSDictionary?, - let serverUrl = userInfo["serverUrl"] as? String, - serverUrl == self.serverUrl - else { return } - - reloadDataSource() - } - - @objc func downloadStartFile(_ notification: NSNotification) { - guard let userInfo = notification.userInfo as NSDictionary?, - let serverUrl = userInfo["serverUrl"] as? String, - let account = userInfo["account"] as? String - else { return } - - if account == self.session.account, serverUrl == self.serverUrl { - reloadDataSource() - } else { - collectionView?.reloadData() - } - } - - @objc func downloadedFile(_ notification: NSNotification) { - guard let userInfo = notification.userInfo as NSDictionary?, - let serverUrl = userInfo["serverUrl"] as? String, - let account = userInfo["account"] as? String - else { return } - - if account == self.session.account, serverUrl == self.serverUrl { - reloadDataSource() - } else { - collectionView?.reloadData() - } - } - - @objc func downloadCancelFile(_ notification: NSNotification) { - guard let userInfo = notification.userInfo as NSDictionary?, - let serverUrl = userInfo["serverUrl"] as? String, - let account = userInfo["account"] as? String - else { return } - - if account == self.session.account, serverUrl == self.serverUrl { - reloadDataSource() - } else { - collectionView?.reloadData() - } - } - - @objc func uploadStartFile(_ notification: NSNotification) { - guard let userInfo = notification.userInfo as NSDictionary?, - let ocId = userInfo["ocId"] as? String, - let serverUrl = userInfo["serverUrl"] as? String, - let account = userInfo["account"] as? String, - !isSearchingMode, - let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) - else { return } - - // Header view trasfer - if metadata.isTransferInForeground { - NCNetworking.shared.transferInForegorund = NCNetworking.TransferInForegorund(ocId: ocId, progress: 0) - DispatchQueue.main.async { self.collectionView?.reloadData() } - } - - if account == self.session.account, serverUrl == self.serverUrl { - reloadDataSource() - } else { - collectionView?.reloadData() - } - } - - @objc func uploadedFile(_ notification: NSNotification) { - guard let userInfo = notification.userInfo as NSDictionary?, - let serverUrl = userInfo["serverUrl"] as? String, - let account = userInfo["account"] as? String - else { return } - - if account == self.session.account, serverUrl == self.serverUrl { - reloadDataSource() - } else { - collectionView?.reloadData() - } - } - - @objc func uploadedLivePhoto(_ notification: NSNotification) { - guard let userInfo = notification.userInfo as NSDictionary?, - let serverUrl = userInfo["serverUrl"] as? String, - let account = userInfo["account"] as? String - else { return } - - if account == self.session.account, serverUrl == self.serverUrl { - reloadDataSource() - } else { - collectionView?.reloadData() - } - } - - @objc func uploadCancelFile(_ notification: NSNotification) { - guard let userInfo = notification.userInfo as NSDictionary?, - let serverUrl = userInfo["serverUrl"] as? String, - let account = userInfo["account"] as? String - else { return } - - if account == self.session.account, serverUrl == self.serverUrl { - reloadDataSource() - } else { - collectionView?.reloadData() - } - } - - @objc func triggerProgressTask(_ notification: NSNotification) { - guard let userInfo = notification.userInfo as NSDictionary?, - let progressNumber = userInfo["progress"] as? NSNumber, - let totalBytes = userInfo["totalBytes"] as? Int64, - let totalBytesExpected = userInfo["totalBytesExpected"] as? Int64, - let ocId = userInfo["ocId"] as? String, - let ocIdTransfer = userInfo["ocIdTransfer"] as? String, - let session = userInfo["session"] as? String - else { return } - - let chunk: Int = userInfo["chunk"] as? Int ?? 0 - let e2eEncrypted: Bool = userInfo["e2eEncrypted"] as? Bool ?? false - - let transfer = NCTransferProgress.shared.append(NCTransferProgress.Transfer(ocId: ocId, ocIdTransfer: ocIdTransfer, session: session, chunk: chunk, e2eEncrypted: e2eEncrypted, progressNumber: progressNumber, totalBytes: totalBytes, totalBytesExpected: totalBytesExpected)) - -// DispatchQueue.main.async { - if self.headerMenuTransferView && (chunk > 0 || e2eEncrypted) { - if NCNetworking.shared.transferInForegorund?.ocId == ocId { - NCNetworking.shared.transferInForegorund?.progress = progressNumber.floatValue - } else { - NCNetworking.shared.transferInForegorund = NCNetworking.TransferInForegorund(ocId: ocId, progress: progressNumber.floatValue) - self.collectionView.reloadData() - } - self.headerMenu?.progressTransfer.progress = transfer.progressNumber.floatValue - } else { - guard let indexPath = self.dataSource.getIndexPathMetadata(ocId: ocId), - let cell = self.collectionView?.cellForItem(at: indexPath), - let cell = cell as? NCCellProtocol else { return } - if progressNumber.floatValue == 1 && !(cell is NCTransferCell) { - cell.fileProgressView?.isHidden = true - cell.fileProgressView?.progress = .zero - cell.setButtonMore(named: NCGlobal.shared.buttonMoreMore, image: NCImageCache.images.buttonMore) - if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) { - cell.writeInfoDateSize(date: metadata.date, size: metadata.size) - } else { - cell.fileInfoLabel?.text = "" - cell.fileSubinfoLabel?.text = "" - } - } else { - cell.fileProgressView?.isHidden = false - cell.fileProgressView?.progress = progressNumber.floatValue - cell.setButtonMore(named: NCGlobal.shared.buttonMoreStop, image: NCImageCache.images.buttonStop) - let status = userInfo["status"] as? Int ?? NCGlobal.shared.metadataStatusNormal - if status == NCGlobal.shared.metadataStatusDownloading { - cell.fileInfoLabel?.text = self.utilityFileSystem.transformedSize(totalBytesExpected) - cell.fileSubinfoLabel?.text = self.infoLabelsSeparator + "↓ " + self.utilityFileSystem.transformedSize(totalBytes) - } else if status == NCGlobal.shared.metadataStatusUploading { - if totalBytes > 0 { - cell.fileInfoLabel?.text = self.utilityFileSystem.transformedSize(totalBytesExpected) - cell.fileSubinfoLabel?.text = self.infoLabelsSeparator + "↑ " + self.utilityFileSystem.transformedSize(totalBytes) - } else { - cell.fileInfoLabel?.text = self.utilityFileSystem.transformedSize(totalBytesExpected) - cell.fileSubinfoLabel?.text = self.infoLabelsSeparator + "↑ …" - } - } - } - } -// } - } - - @objc func updateShare(_ notification: NSNotification) { - if isSearchingMode { - networkSearch() - } else { -// self.dataSource.removeAll() - getServerData() - } - } - - @objc func updateIcons() { - collectionView.reloadData() -// reloadDataSource() - } - - // MARK: - Layout - - func setNavigationLeftItems() { - navigationItem.title = titleCurrentFolder - } func getNavigationTitle() -> String { let tblAccount = self.database.getTableAccount(predicate: NSPredicate(format: "account == %@", session.account)) @@ -1104,42 +592,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS self.navigationItem.titleView = nil self.navigationItem.title = self.titleCurrentFolder } - - func accountSettingsDidDismiss(tableAccount: tableAccount?, controller: NCMainTabBarController?) { } - - func resetPlusButtonAlpha(animated: Bool = true) { } - - func isHiddenPlusButton(_ isHidden: Bool) { } - - // MARK: - Empty - - func emptyDataSetView(_ view: NCEmptyView) { - - self.emptyDataSet?.setOffset(getHeaderHeight()) - if isSearchingMode { - view.emptyImage.image = UIImage(named: "search")?.image(color: .gray, size: UIScreen.main.bounds.width) - if self.dataSourceTask?.state == .running { - view.emptyTitle.text = NSLocalizedString("_search_in_progress_", comment: "") - } else { - view.emptyTitle.text = NSLocalizedString("_search_no_record_found_", comment: "") - } - view.emptyDescription.text = NSLocalizedString("_search_instruction_", comment: "") - } else if self.dataSourceTask?.state == .running { - view.emptyImage.image = UIImage(named: "networkInProgress")?.image(color: .gray, size: UIScreen.main.bounds.width) - view.emptyTitle.text = NSLocalizedString("_request_in_progress_", comment: "") - view.emptyDescription.text = "" - } else { - if serverUrl.isEmpty { - view.emptyImage.image = emptyImage - view.emptyTitle.text = NSLocalizedString(emptyTitle, comment: "") - view.emptyDescription.text = NSLocalizedString(emptyDescription, comment: "") - } else { - view.emptyImage.image = UIImage(named: "folder_nmcloud") - view.emptyTitle.text = NSLocalizedString("_files_no_files_", comment: "") - view.emptyDescription.text = NSLocalizedString("_no_file_pull_down_", comment: "") - } - } - } // MARK: - SEARCH @@ -1193,10 +645,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS // MARK: - TAP EVENT - func tapMoreListItem(with ocId: String, ocIdTransfer: String, namedButtonMore: String, image: UIImage?, sender: Any) { - tapMoreGridItem(with: ocId, ocIdTransfer: ocIdTransfer, namedButtonMore: namedButtonMore, image: image, sender: sender) - } - func tapMoreListItem(with ocId: String, ocIdTransfer: String, image: UIImage?, sender: Any) { tapMoreGridItem(with: ocId, ocIdTransfer: ocIdTransfer, image: image, sender: sender) } @@ -1206,7 +654,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS } func tapShareListItem(with ocId: String, ocIdTransfer: String, sender: Any) { - if isEditMode { return } guard let metadata = self.database.getMetadataFromOcId(ocId) else { return } NCCreate().createShare(viewController: self, metadata: metadata, page: .sharing) @@ -1215,29 +662,11 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS appDelegate.adjust.trackEvent(TriggerEvent(Sharing.rawValue)) } - - func tapMoreGridItem(with ocId: String, ocIdTransfer: String, namedButtonMore: String, image: UIImage?, sender: Any) { - if isEditMode { return } - guard let metadata = self.database.getMetadataFromOcId(ocId) else { return } -// toggleMenu(metadata: metadata, image: image) - if namedButtonMore == NCGlobal.shared.buttonMoreMore || namedButtonMore == NCGlobal.shared.buttonMoreLock { - toggleMenu(metadata: metadata, image: image) - } else if namedButtonMore == NCGlobal.shared.buttonMoreStop { - Task { - await cancelSession(metadata: metadata) - } - } - } func tapMoreGridItem(with ocId: String, ocIdTransfer: String, image: UIImage?, sender: Any) { guard let metadata = self.database.getMetadataFromOcId(ocId) else { return } -// toggleMenu(metadata: metadata, image: image, sender: sender) - Task { - await cancelSession(metadata: metadata) - } + toggleMenu(metadata: metadata, image: image, sender: sender) } - - func longPressMoreListItem(with ocId: String, ocIdTransfer: String, gestureRecognizer: UILongPressGestureRecognizer) { } func tapRichWorkspace(_ sender: Any) { if let navigationController = UIStoryboard(name: "NCViewerRichWorkspace", bundle: nil).instantiateInitialViewController() as? UINavigationController { @@ -1263,34 +692,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS func tapRecommendations(with metadata: tableMetadata) { didSelectMetadata(metadata, withOcIds: false) } - - func tapButtonSwitch(_ sender: Any) { - guard !isTransitioning else { return } - isTransitioning = true - - guard let layoutForView = NCManageDatabase.shared.getLayoutForView(account: session.account, key: layoutKey, serverUrl: serverUrl) else { return } - - if layoutForView.layout == NCGlobal.shared.layoutGrid { - layoutForView.layout = NCGlobal.shared.layoutList - } else { - layoutForView.layout = NCGlobal.shared.layoutGrid - } - self.layoutForView = NCManageDatabase.shared.setLayoutForView(layoutForView: layoutForView) - self.collectionView.reloadData() - self.collectionView.collectionViewLayout.invalidateLayout() - self.collectionView.setCollectionViewLayout(layoutForView.layout == NCGlobal.shared.layoutList ? self.listLayout : self.gridLayout, animated: true) {_ in self.isTransitioning = false } - } - - func tapButtonOrder(_ sender: Any) { - let sortMenu = NCSortMenu() - sortMenu.toggleMenu(viewController: self, account: session.account, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl) - } - - func tapButtonTransfer(_ sender: Any) { } - - func longPressListItem(with objectId: String, indexPath: IndexPath, gestureRecognizer: UILongPressGestureRecognizer) { - } - func longPressListItem(with ocId: String, ocIdTransfer: String, namedButtonMore: String, gestureRecognizer: UILongPressGestureRecognizer) { } func longPressListItem(with ocId: String, ocIdTransfer: String, gestureRecognizer: UILongPressGestureRecognizer) { } @@ -1332,12 +733,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS } } - // MARK: - Transfer Delegate - - func transferProgressDidUpdate(progress: Float, totalBytes: Int64, totalBytesExpected: Int64, fileName: String, serverUrl: String) { } - - func tranferChange(status: String, metadata: tableMetadata, error: NKError) { } - // MARK: - Menu Item override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { @@ -1452,40 +847,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS func getServerData(forced: Bool = false) async { } - @objc func reloadDataSource() { - - // get auto upload folder - autoUploadFileName = NCManageDatabase.shared.getAccountAutoUploadFileName() - autoUploadDirectory = NCManageDatabase.shared.getAccountAutoUploadDirectory(urlBase: session.urlBase, userId: session.userId, account: session.account) - - // get layout for view - layoutForView = NCManageDatabase.shared.getLayoutForView(account: session.account, key: layoutKey, serverUrl: serverUrl) - // set GroupField for Grid - if !isSearchingMode && layoutForView?.layout == NCGlobal.shared.layoutGrid { - groupByField = "classFile" - } else { - groupByField = "name" - } - if isSearchingMode { - isDirectoryEncrypted = false - } else { - isDirectoryEncrypted = NCUtilityFileSystem().isDirectoryE2EE(session: session, serverUrl: serverUrl) - } - - DispatchQueue.main.async { -// UIView.transition(with: self.collectionView, -// duration: 0.20, -// options: .transitionCrossDissolve, -// animations: { self.collectionView.reloadData() }, -// completion: nil) -// -// (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() - self.refreshControl.endRefreshing() - self.collectionView.reloadData() - self.setNavigationRightItems() - } - } - @objc func networkSearch() { guard !networkSearchInProgress else { return @@ -1654,28 +1015,18 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS } } - func isHeaderMenuTransferViewEnabled() -> [tableMetadata]? { - if headerMenuTransferView, - NCNetworking.shared.isOnline, - let results = database.getResultsMetadatas(predicate: NSPredicate(format: "status IN %@", [global.metadataStatusWaitUpload, global.metadataStatusUploading])), - !results.isEmpty { - return Array(results) - } - return nil - } - func sizeForHeaderInSection(section: Int) -> CGSize { var height: CGFloat = 0 let isLandscape = view.bounds.width > view.bounds.height let isIphone = UIDevice.current.userInterfaceIdiom == .phone if self.dataSource.isEmpty() { - height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: emptyDataPortaitOffset, landscapeOffset: emptyDataLandscapeOffset, isHeaderMenuTransferViewEnabled: isHeaderMenuTransferViewEnabled() != nil) + height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: emptyDataPortaitOffset, landscapeOffset: emptyDataLandscapeOffset) } else if isEditMode || (isLandscape && isIphone) { return CGSize.zero } else { - let (heightHeaderCommands, heightHeaderRichWorkspace, heightHeaderSection) = getHeaderHeight(section: section) - height = heightHeaderCommands + heightHeaderRichWorkspace + heightHeaderSection + let (heightHeaderRichWorkspace, heightHeaderRecommendations, heightHeaderSection) = getHeaderHeight(section: section) + height = heightHeaderRichWorkspace + heightHeaderRecommendations + heightHeaderSection } return CGSize(width: collectionView.frame.width, height: height) @@ -1684,21 +1035,25 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS // MARK: - Footer size func sizeForFooterInSection(section: Int) -> CGSize { + guard let controller else { + return CGSize.zero + } let sections = dataSource.numberOfSections() - let metadataForSection = self.dataSource.getMetadataForSection(section) - let isPaginated = metadataForSection?.lastSearchResult?.isPaginated ?? false - let metadatasCount: Int = metadataForSection?.lastSearchResult?.entries.count ?? 0 - var size = CGSize(width: collectionView.frame.width, height: 0) + let bottomAreaInsets: CGFloat = controller.tabBar.safeAreaInsets.bottom == 0 ? 34 : 0 + let height = controller.tabBar.frame.height + bottomAreaInsets - if section == sections - 1 { - size.height += 85 - } else { - size.height += 1 + if isEditMode { + return CGSize(width: collectionView.frame.width, height: 90 + height) } - if isSearchingMode && isPaginated && metadatasCount > 0 { - size.height += 30 + if isSearchingMode { + return CGSize(width: collectionView.frame.width, height: 50) + } + + if section == sections - 1 { + return CGSize(width: collectionView.frame.width, height: height) + } else { + return CGSize(width: collectionView.frame.width, height: 0) } - return size } } diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift index 688b09e70c..0d5f0fc74c 100644 --- a/iOSClient/NCGlobal.swift +++ b/iOSClient/NCGlobal.swift @@ -4,34 +4,18 @@ import UIKit -/// Used for read/write in Realm -var isAppSuspending: Bool = false -/// Used for know if the app in in Background mode -var isAppInBackground: Bool = false +final class NCGlobal: Sendable { + static let shared = NCGlobal() + + init() { } -class NCGlobal: NSObject, @unchecked Sendable { - @objc static let shared = NCGlobal() - - override init() { - super.init() - NotificationCenter.default.addObserver(forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: .main) { _ in - isAppSuspending = true - isAppInBackground = true - } - - NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: .main) { _ in - isAppSuspending = false - isAppInBackground = false - } - } - // ENUM // public enum TypeFilterScanDocument: String { case document = "document" case original = "original" } - + // Directory on Group // let directoryProviderStorage = "File Provider Storage" @@ -40,13 +24,13 @@ class NCGlobal: NSObject, @unchecked Sendable { let appDatabaseNextcloud = "Library/Application Support/Nextcloud" let appScan = "Library/Application Support/Scan" let appUserData = "Library/Application Support/UserData" - + // Service // let metadataKeyedUnarchiver = "it.twsweb.nextcloud.metadata" let refreshTask = "com.nextcloud.refreshTask" let processingTask = "com.nextcloud.processingTask" - + // App // let appName = "files" @@ -55,10 +39,9 @@ class NCGlobal: NSObject, @unchecked Sendable { let spreedName = "spreed" let twoFactorNotificatioName = "twofactor_nextcloud_notification" let termsOfServiceName = "terms_of_service" - + // Nextcloud version // - let nextcloudVersion12: Int = 12 let nextcloudVersion18: Int = 18 let nextcloudVersion20: Int = 20 let nextcloudVersion23: Int = 23 @@ -69,7 +52,7 @@ class NCGlobal: NSObject, @unchecked Sendable { let nextcloudVersion28: Int = 28 let nextcloudVersion30: Int = 30 let nextcloudVersion31: Int = 31 - + // Nextcloud unsupported // let nextcloud_unsupported_version: Int = 20 @@ -78,14 +61,10 @@ class NCGlobal: NSObject, @unchecked Sendable { // Intro selector // - @objc let introLogin: Int = 0 + let introLogin: Int = 0 let introSignup: Int = 1 - // let introSignUpWithProvider: Int = 1 - - // Varie size GUI - // - @objc let heightCellSettings: CGFloat = 50 - + let introSignUpWithProvider: Int = 1 + // Avatar // let avatarSize: Int = 128 * Int(UIScreen.main.scale) @@ -100,50 +79,50 @@ class NCGlobal: NSObject, @unchecked Sendable { let previewExt1024 = ".1024.preview.jpg" let previewExt512 = ".512.preview.jpg" let previewExt256 = ".256.preview.jpg" - + func getSizeExtension(column: Int) -> String { if column == 0 { return previewExt256 } let width = UIScreen.main.bounds.width / CGFloat(column) - - switch (width * 4) { - case 0...384: - return previewExt256 - case 385...768: - return previewExt512 - default: - return previewExt1024 - } + + switch (width * 4) { + case 0...384: + return previewExt256 + case 385...768: + return previewExt512 + default: + return previewExt1024 + } } - + // E2EE // let e2eePassphraseTest = "more over television factory tendency independence international intellectual impress interest sentence pony" - @objc let e2eeVersions = ["1.1", "1.2", "2.0"] + let e2eeVersions = ["1.1", "1.2", "2.0"] let e2eeVersionV11 = "1.1" let e2eeVersionV12 = "1.2" let e2eeVersionV20 = "2.0" - + // CHUNK let chunkSizeMBCellular = 10000000 let chunkSizeMBEthernetOrWiFi = 100000000 - + // Video // let maxHTTPCache: Int64 = 10000000000 // 10 GB let fileNameVideoEncoded: String = "video_encoded.mp4" - + // NCViewerProviderContextMenu // let maxAutoDownload: UInt64 = 50000000 // 50MB let maxAutoDownloadCellular: UInt64 = 10000000 // 10MB - + // Layout // let layoutList = "typeLayoutList" let layoutGrid = "typeLayoutGrid" let layoutPhotoRatio = "typeLayoutPhotoRatio" let layoutPhotoSquare = "typeLayoutPhotoSquare" - + let layoutViewTrash = "LayoutTrash" let layoutViewOffline = "LayoutOffline" let layoutViewFavorite = "LayoutFavorite" @@ -153,16 +132,13 @@ class NCGlobal: NSObject, @unchecked Sendable { let layoutViewShareExtension = "LayoutShareExtension" let layoutViewGroupfolders = "LayoutGroupfolders" let layoutViewMedia = "LayoutMedia" - let layoutViewMove = "LayoutMove" - // Button Type in Cell list/grid // let buttonMoreMore = "more" let buttonMoreLock = "moreLock" let buttonMoreStop = "stop" - // Standard height sections header/footer // let heightButtonsView: CGFloat = 50 @@ -193,7 +169,7 @@ class NCGlobal: NSObject, @unchecked Sendable { // Rich Workspace // let fileNameRichWorkspace = "Readme.md" - + // ContentPresenter // let dismissAfterSecond: TimeInterval = 5 @@ -211,7 +187,6 @@ class NCGlobal: NSObject, @unchecked Sendable { let errorConflict: Int = 409 let errorPreconditionFailed: Int = 412 let errorUnsupportedMediaType: Int = 415 - let errorWebDAVLocked: Int = 423 let errorInternalServerError: Int = 500 let errorMaintenance: Int = 503 let errorQuota: Int = 507 @@ -239,7 +214,6 @@ class NCGlobal: NSObject, @unchecked Sendable { let errorE2EEKeyChecksums: Int = -98002 let errorE2EEKeyEncodeMetadata: Int = -98003 let errorE2EEKeyDecodeMetadataV12: Int = -98004 - let errorE2EEKeyDecodeMetadata: Int = -98004 let errorE2EEKeyVerifySignature: Int = -98005 let errorE2EEKeyCiphertext: Int = -98006 let errorE2EEKeyFiledropCiphertext: Int = -98007 @@ -266,7 +240,6 @@ class NCGlobal: NSObject, @unchecked Sendable { let selectorDownloadFile = "downloadFile" let selectorUploadAutoUpload = "uploadAutoUpload" - let selectorUploadAutoUploadAll = "uploadAutoUploadAll" let selectorUploadFile = "uploadFile" let selectorUploadFileNODelete = "UploadFileNODelete" let selectorUploadFileShareExtension = "uploadFileShareExtension" @@ -277,7 +250,7 @@ class NCGlobal: NSObject, @unchecked Sendable { let selectorSynchronizationOffline = "synchronizationOffline" let selectorPrint = "print" let selectorDeleteFile = "deleteFile" - + // Metadata : Status // // 0 normal @@ -286,33 +259,27 @@ class NCGlobal: NSObject, @unchecked Sendable { // ± 3 error // let metadataStatusNormal: Int = 0 - + let metadataStatusWaitDownload: Int = -1 let metadataStatusDownloading: Int = -2 let metadataStatusDownloadError: Int = -3 - + let metadataStatusWaitUpload: Int = 1 let metadataStatusUploading: Int = 2 let metadataStatusUploadError: Int = 3 - + let metadataStatusWaitCreateFolder: Int = 10 let metadataStatusWaitDelete: Int = 11 let metadataStatusWaitRename: Int = 12 let metadataStatusWaitFavorite: Int = 13 let metadataStatusWaitCopy: Int = 14 let metadataStatusWaitMove: Int = 15 - + let metadataStatusUploadingAllMode = [1,2,3] let metadataStatusDownloadingAllMode = [-1, -2, -3] let metadataStatusForScreenAwake = [-1, -2, 1, 2] - let metadataStatusInTransfer = [-1, -2, 1, 2] - let metadataStatusFileDown = [-1, -2, -3] let metadataStatusHideInView = [1, 2, 3, 11] - let metadataStatusHideInFileExtension = [1, 2, 3, 10, 11] let metadataStatusWaitWebDav = [10, 11, 12, 13, 14, 15] - let metadataStatusTransfers = [-2, -3, 2, 3, 10, 11, 12, 13, 14, 15] - let metadataStatusObserveNetworkingProcess = [-1, 1, 10, 11, 12, 13, 14, 15] - let metadataStatusObserveTrasfers = [-2, 2, 10, 11, 12, 13, 14, 15] let metadatasStatusInWaiting = [-1, 1, 10, 11, 12, 13, 14, 15] let metadatasStatusInProgress = [-2, 2] @@ -323,88 +290,42 @@ class NCGlobal: NSObject, @unchecked Sendable { // Auto upload subfolder granularity // - @objc let subfolderGranularityDaily = 2 - @objc let subfolderGranularityMonthly = 1 - @objc let subfolderGranularityYearly = 0 - + let subfolderGranularityDaily = 2 + let subfolderGranularityMonthly = 1 + let subfolderGranularityYearly = 0 + // Notification Center // - @objc let notificationCenterChangeUser = "changeUser" - let notificationCenterChangeTheming = "changeTheming" - @objc let notificationCenterApplicationDidEnterBackground = "applicationDidEnterBackground" - @objc let notificationCenterApplicationDidBecomeActive = "applicationDidBecomeActive" - @objc let notificationCenterApplicationWillResignActive = "applicationWillResignActive" - @objc let notificationCenterApplicationWillEnterForeground = "applicationWillEnterForeground" - - - @objc let notificationCenterInitialize = "initialize" + let notificationCenterChangeUser = "changeUser" // userInfo: account, controller + let notificationCenterChangeTheming = "changeTheming" // userInfo: account let notificationCenterRichdocumentGrabFocus = "richdocumentGrabFocus" let notificationCenterReloadDataNCShare = "reloadDataNCShare" let notificationCenterDidCreateShareLink = "didCreateShareLink" - + let notificationCenterCloseRichWorkspaceWebView = "closeRichWorkspaceWebView" let notificationCenterReloadAvatar = "reloadAvatar" - let notificationCenterReloadHeader = "reloadHeader" let notificationCenterClearCache = "clearCache" - let notificationCenterChangeLayout = "changeLayout" // userInfo: account, serverUrl, layoutForView let notificationCenterCheckUserDelaultErrorDone = "checkUserDelaultErrorDone" // userInfo: account, controller let notificationCenterServerDidUpdate = "serverDidUpdate" // userInfo: account let notificationCenterNetworkReachability = "networkReachability" - let notificationCenterCreateMediaCacheEnded = "createMediaCacheEnded" - let notificationCenterUpdateNotification = "updateNotification" - let notificationCenterReloadDataSource = "reloadDataSource" // userInfo: serverUrl?, clearDataSource - let notificationCenterGetServerData = "getServerData" // userInfo: serverUrl? - - let notificationCenterChangeStatusFolderE2EE = "changeStatusFolderE2EE" // userInfo: serverUrl - - let notificationCenterDownloadStartFile = "downloadStartFile" // userInfo: ocId, ocIdTransfer, session, serverUrl, account - let notificationCenterDownloadedFile = "downloadedFile" // userInfo: ocId, ocIdTransfer, session, session, serverUrl, account, selector, error - let notificationCenterDownloadCancelFile = "downloadCancelFile" // userInfo: ocId, ocIdTransfer, session, serverUrl, account - - let notificationCenterUploadStartFile = "uploadStartFile" // userInfo: ocId, ocIdTransfer, session, serverUrl, account, fileName, sessionSelector - let notificationCenterUploadedFile = "uploadedFile" // userInfo: ocId, ocIdTransfer, session, serverUrl, account, fileName, ocIdTransfer, error - let notificationCenterUploadedLivePhoto = "uploadedLivePhoto" // userInfo: ocId, ocIdTransfer, session, serverUrl, account, fileName, ocIdTransfer, error - let notificationCenterUploadCancelFile = "uploadCancelFile" // userInfo: ocId, ocIdTransfer, session, serverUrl, account - - let notificationCenterProgressTask = "progressTask" // userInfo: account, ocId, ocIdTransfer, session, serverUrl, status, chunk, e2eEncrypted, progress, totalBytes, totalBytesExpected - - let notificationCenterUpdateBadgeNumber = "updateBadgeNumber" // userInfo: counterDownload, counterUpload - - let notificationCenterCreateFolder = "createFolder" // userInfo: ocId, serverUrl, account, withPush, sceneIdentifier - let notificationCenterDeleteFile = "deleteFile" // userInfo: [ocId], error - let notificationCenterCopyMoveFile = "copyMoveFile" // userInfo: [ocId] serverUrl, account, dragdrop, type (copy, move) - let notificationCenterMoveFile = "moveFile" // userInfo: [ocId], [indexPath], error - let notificationCenterCopyFile = "copyFile" // userInfo: [ocId], [indexPath], error let notificationCenterRenameFile = "renameFile" // userInfo: serverUrl, account, error - let notificationCenterFavoriteFile = "favoriteFile" // userInfo: ocId, serverUrl - let notificationCenterFileExists = "fileExists" // userInfo: ocId, fileExists - + let notificationCenterMenuSearchTextPDF = "menuSearchTextPDF" let notificationCenterMenuGotToPageInPDF = "menuGotToPageInPDF" - + let notificationCenterOpenMediaDetail = "openMediaDetail" // userInfo: ocId - + let notificationCenterDismissScanDocument = "dismissScanDocument" let notificationCenterDismissUploadAssets = "dismissUploadAssets" - + let notificationCenterEnableSwipeGesture = "enableSwipeGesture" let notificationCenterDisableSwipeGesture = "disableSwipeGesture" - - let notificationCenterShareViewIn = "ShareViewIn" - let notificationCenterShareAdvancePermission = "ShareAdvancePermission" - let notificationCenterShareSendEmail = "ShareSendEmail" - let notificationCenterShareUnshare = "ShareUnshare" - let notificationCenterStatusReadOnly = "statusReadOnly" - let notificationCenterStatusEditing = "statusEditing" - let notificationCenterStatusFileDrop = "statusFileDrop" - + let notificationCenterPlayerIsPlaying = "playerIsPlaying" let notificationCenterPlayerStoppedPlaying = "playerStoppedPlaying" - - let notificationCenterUpdateShare = "updateShare" - let notificationCenterShareCountsUpdated = "shareCountsUpdated" - let notificationCenterUpdateIcons = "updateIcons" + + let notificationCenterFavoriteStatusChanged = "favoriteStatusChanged" // Networking Status let networkingStatusCreateFolder = "statusCreateFolder" @@ -420,8 +341,9 @@ class NCGlobal: NSObject, @unchecked Sendable { let networkingStatusUploading = "statusUploading" let networkingStatusUploaded = "statusUploaded" - let networkingStatusReloadAvatar = "statusReloadAvatar" + let networkingStatusReloadAvatar = "statusReloadAvatar" + let notificationCenterUpdateIcons = "updateIcons" // TIP // @@ -430,7 +352,6 @@ class NCGlobal: NSObject, @unchecked Sendable { let tipScanAddImage = "tipScanAddImage" let tipMediaDetailView = "tipMediaDetailView" let tipAutoUploadButton = "tipAutoUploadButton" - let tipAutoUpload = "tipAutoUpload" // ACTION // @@ -461,31 +382,10 @@ class NCGlobal: NSObject, @unchecked Sendable { let configuration_disable_multiaccount = "disable_multiaccount" let configuration_disable_crash_service = "disable_crash_service" let configuration_disable_log = "disable_log" - let configuration_disable_manage_account = "disable_manage_account" let configuration_disable_more_external_site = "disable_more_external_site" let configuration_disable_openin_file = "disable_openin_file" let configuration_enforce_passcode_lock = "enforce_passcode_lock" - - // CAPABILITIES - // - var capabilityServerVersionMajor: Int = 0 - @objc var capabilityServerVersion: String = "" - @objc var capabilityThemingName: String = "" - @objc var capabilityThemingSlogan: String = "" - - @objc var capabilityE2EEEnabled: Bool = false - @objc var capabilityE2EEApiVersion: String = "" - - var capabilityRichdocumentsEnabled: Bool = false - var capabilityRichdocumentsMimetypes: [String] = [] - var capabilityActivity: [String] = [] - var capabilityNotification: [String] = [] - - @objc var capabilityUserStatusEnabled: Bool = false - var isLivePhotoServerAvailable: Bool { // NC28 - return capabilityServerVersionMajor >= nextcloudVersion28 - } - + // MORE NEXTCLOUD APPS // let talkSchemeUrl = "nextcloudtalk://" @@ -493,41 +393,36 @@ class NCGlobal: NSObject, @unchecked Sendable { let talkAppStoreUrl = "https://apps.apple.com/in/app/nextcloud-talk/id1296825574" let notesAppStoreUrl = "https://apps.apple.com/in/app/nextcloud-notes/id813973264" let moreAppsUrl = "itms-apps://search.itunes.apple.com/WebObjects/MZSearch.woa/wa/search?media=software&term=nextcloud" - + // SNAPSHOT PREVIEW // let defaultSnapshotConfiguration = "DefaultPreviewConfiguration" - -// // FORBIDDEN CHARACTERS -// // -// // TODO: Remove this -// let forbiddenCharacters = ["/", "\\", ":", "\"", "|", "?", "*", "<", ">"] - + // DIAGNOSTICS CLIENTS // let diagnosticIssueSyncConflicts = "sync_conflicts" let diagnosticIssueProblems = "problems" let diagnosticIssueVirusDetected = "virus_detected" let diagnosticIssueE2eeErrors = "e2ee_errors" - + let diagnosticProblemsForbidden = "CHARACTERS_FORBIDDEN" let diagnosticProblemsBadResponse = "BAD_SERVER_RESPONSE" let diagnosticProblemsUploadServerError = "UploadError.SERVER_ERROR" - + // MEDIA LAYOUT // let mediaLayoutRatio = "mediaLayoutRatio" let mediaLayoutSquare = "mediaLayoutSquare" - + // DRAG & DROP // let metadataOcIdDataRepresentation = "text/com.nextcloud.ocId" - + // GROUP AMIN // let groupAdmin = "admin" - // DATA TASK DESCRIPTION + // TASK DESCRIPTION // let taskDescriptionRetrievesProperties = "retrievesProperties" let taskDescriptionSynchronization = "synchronization" @@ -545,7 +440,7 @@ class NCGlobal: NSObject, @unchecked Sendable { let keyFileNameAutoUploadType = "fileNameAutoUploadType" let keyFileNameOriginal = "fileNameOriginal" let keyFileNameOriginalAutoUpload = "fileNameOriginalAutoUpload" - + // LOG TAG // let logTagTask = "BGT" diff --git a/iOSClient/Rename file/NCRenameFile.swift b/iOSClient/Rename file/NCRenameFile.swift index 723e02ed3f..d27b86dc9a 100644 --- a/iOSClient/Rename file/NCRenameFile.swift +++ b/iOSClient/Rename file/NCRenameFile.swift @@ -45,6 +45,7 @@ class NCRenameFile: UIViewController, UITextFieldDelegate { @IBOutlet weak var cancelButton: UIButton! @IBOutlet weak var renameButton: UIButton! @IBOutlet weak var seperator: UIView! + let imageCache = NCImageCache.shared let width: CGFloat = 300 let height: CGFloat = 350 @@ -89,7 +90,7 @@ class NCRenameFile: UIViewController, UITextFieldDelegate { if metadata.directory { if imagePreview == nil { - previewFile.image = NCImageCache.images.folder + previewFile.image = imageCache.getFolder(account: metadata.account) } ext.isHidden = true @@ -99,7 +100,7 @@ class NCRenameFile: UIViewController, UITextFieldDelegate { } else { if imagePreview == nil { - previewFile.image = NCImageCache.images.file + previewFile.image = imageCache.getImageFile() } fileNameNoExtensionTrailingContraint.constant = 90 @@ -118,7 +119,7 @@ class NCRenameFile: UIViewController, UITextFieldDelegate { ext.delegate = self if imagePreview == nil { - previewFile.image = NCImageCache.images.file + previewFile.image = imageCache.getImageFile() } else { previewFile.image = imagePreview } @@ -127,11 +128,11 @@ class NCRenameFile: UIViewController, UITextFieldDelegate { } cancelButton.setTitle(NSLocalizedString("_cancel_", comment: ""), for: .normal) - cancelButton.setTitleColor(NCBrandColor.shared.iconColor, for: .normal) + cancelButton.setTitleColor(NCBrandColor.shared.iconImageColor, for: .normal) cancelButton.layer.cornerRadius = 5 cancelButton.layer.masksToBounds = true cancelButton.layer.borderWidth = 0.3 - cancelButton.layer.borderColor = NCBrandColor.shared.iconColor.cgColor + cancelButton.layer.borderColor = NCBrandColor.shared.iconImageColor.cgColor renameButton.setTitle(NSLocalizedString("_rename_", comment: ""), for: .normal) renameButton.setTitleColor(NCBrandColor.shared.brandText, for: .normal) @@ -246,13 +247,16 @@ class NCRenameFile: UIViewController, UITextFieldDelegate { NCActivityIndicator.shared.start() +// NCNetworking.shared.renameMetadata(metadata, fileNameNew: fileNameNew) NCNetworking.shared.renameMetadata(metadata, fileNameNew: fileNameNew, indexPath: indexPath, viewController: self) { error in NCActivityIndicator.shared.stop() if error == .success { - self.dismiss(animated: true) + DispatchQueue.main.async { + self.dismiss(animated: true) + } } else {