From 199384af34e3bb2cbad2711a409ee9a97b8f867f Mon Sep 17 00:00:00 2001 From: TSI-amrutwaghmare <96108296+TSI-amrutwaghmare@users.noreply.github.com> Date: Mon, 27 Nov 2023 17:19:30 +0530 Subject: [PATCH 1/4] NMC 1997 - Sharing customisation NMC 1997 - Merging conflict resolve after nextcloud version 4.9.2 release NMC 1992 - Remove configuration changes NMC 1992 - Removed unused files NMC 1992 - Sharing changes update after NC 5.2 NMC 1992 - Removed project configuration file changes --- Tests/NextcloudUnitTests/SharingTest.swift | 232 +++++ .../Extensions/DateFormatter+Extension.swift | 9 + iOSClient/Extensions/UIButton+Extension.swift | 23 +- .../Extensions/UIToolbar+Extension.swift | 14 + iOSClient/Extensions/UIView+Extension.swift | 22 + iOSClient/Main/NCActionCenter.swift | 27 +- iOSClient/Menu/NCShare+Menu.swift | 66 +- iOSClient/NCGlobal.swift | 9 + iOSClient/Networking/NCService.swift | 21 + .../Scan document/PasswordInputField.swift | 75 ++ .../Scan document/PasswordInputField.xib | 70 ++ .../Share/Advanced/NCFilePermissionCell.swift | 91 ++ .../Share/Advanced/NCFilePermissionCell.xib | 95 ++ .../Advanced/NCFilePermissionEditCell.swift | 176 ++++ .../Advanced/NCFilePermissionEditCell.xib | 108 +++ .../Advanced/NCShareAdvancePermission.swift | 871 ++++++++++++++---- .../NCShareAdvancePermissionFooter.swift | 27 +- .../NCShareAdvancePermissionFooter.xib | 79 +- .../NCShareAdvancePermissionHeader.xib | 84 ++ .../Advanced/NCShareHeaderCustomCell.swift | 30 + .../Advanced/NCShareHeaderCustomCell.xib | 42 + .../Advanced/NCShareNewUserAddComment.swift | 115 ++- .../Share/Advanced/NCShareTextInputCell.swift | 151 +++ .../Share/Advanced/NCShareTextInputCell.xib | 80 ++ iOSClient/Share/NCSearchUserDropDownCell.xib | 10 +- iOSClient/Share/NCShare+Helper.swift | 113 +++ iOSClient/Share/NCShare+NCCellDelegate.swift | 7 +- iOSClient/Share/NCShare.storyboard | 472 ++++------ iOSClient/Share/NCShare.swift | 419 +++++---- iOSClient/Share/NCShareCommon.swift | 71 +- iOSClient/Share/NCShareEmailFieldCell.swift | 89 ++ iOSClient/Share/NCShareEmailFieldCell.xib | 128 +++ iOSClient/Share/NCShareHeader.swift | 71 +- iOSClient/Share/NCShareHeaderView.xib | 247 ++--- iOSClient/Share/NCShareLinkCell.swift | 78 +- iOSClient/Share/NCShareLinkCell.xib | 195 ++-- iOSClient/Share/NCShareNetworking.swift | 15 + iOSClient/Share/NCSharePaging.swift | 149 ++- iOSClient/Share/NCShareUserCell.swift | 78 +- iOSClient/Share/NCShareUserCell.xib | 203 ++-- .../Share/ShareDownloadLimitNetwork.swift | 146 +++ iOSClient/Utility/NCUtility.swift | 7 + 42 files changed, 3710 insertions(+), 1305 deletions(-) create mode 100644 Tests/NextcloudUnitTests/SharingTest.swift create mode 100644 iOSClient/Scan document/PasswordInputField.swift create mode 100644 iOSClient/Scan document/PasswordInputField.xib create mode 100644 iOSClient/Share/Advanced/NCFilePermissionCell.swift create mode 100644 iOSClient/Share/Advanced/NCFilePermissionCell.xib create mode 100644 iOSClient/Share/Advanced/NCFilePermissionEditCell.swift create mode 100644 iOSClient/Share/Advanced/NCFilePermissionEditCell.xib create mode 100644 iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.xib create mode 100644 iOSClient/Share/Advanced/NCShareHeaderCustomCell.swift create mode 100644 iOSClient/Share/Advanced/NCShareHeaderCustomCell.xib create mode 100644 iOSClient/Share/Advanced/NCShareTextInputCell.swift create mode 100644 iOSClient/Share/Advanced/NCShareTextInputCell.xib create mode 100644 iOSClient/Share/NCShare+Helper.swift create mode 100644 iOSClient/Share/NCShareEmailFieldCell.swift create mode 100644 iOSClient/Share/NCShareEmailFieldCell.xib create mode 100644 iOSClient/Share/ShareDownloadLimitNetwork.swift diff --git a/Tests/NextcloudUnitTests/SharingTest.swift b/Tests/NextcloudUnitTests/SharingTest.swift new file mode 100644 index 0000000000..66d94dbfbb --- /dev/null +++ b/Tests/NextcloudUnitTests/SharingTest.swift @@ -0,0 +1,232 @@ +// +// SharingTest.swift +// NextcloudTests +// +// Created by A200020526 on 07/06/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +import XCTest +@testable import Nextcloud +final class SharingTest: XCTestCase { + + var button: UIButton? + var ncShare: NCShare? + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + super.setUp() + button = UIButton() + ncShare = NCShare() + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + button = nil + ncShare = nil + super.tearDown() + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + + + //Date exntesion test case + func testTomorrow() { + let tomorrow = Date.tomorrow + let expectedTomorrow = Calendar.current.date(byAdding: .day, value: 1, to: Date())! + XCTAssertEqual(tomorrow.extendedIso8601String, expectedTomorrow.extendedIso8601String, "Tomorrow date should be correct.") + } + func testToday() { + let today = Date.today + let currentDate = Date() + XCTAssertEqual(today.extendedIso8601String, currentDate.extendedIso8601String, "Today date should be correct.") + } + + func testDayAfter() { + let date = Date() + let dayAfter = date.dayAfter + let expectedDayAfter = Calendar.current.date(byAdding: .day, value: 1, to: date)! + XCTAssertEqual(dayAfter.extendedIso8601String, expectedDayAfter.extendedIso8601String, "Day after date should be correct.") + } + + //Date Formatter extension Test Case + func testShareExpDate() { + let dateFormatter = DateFormatter.shareExpDate + + XCTAssertEqual(dateFormatter.formatterBehavior, .behavior10_4, "Formatter behavior should be correct.") + XCTAssertEqual(dateFormatter.dateStyle, .medium, "Date style should be correct.") + XCTAssertEqual(dateFormatter.dateFormat, NCShareAdvancePermission.displayDateFormat, "Date format should be correct.") + } + + //Button Extension test case + func testSetBackgroundColor() { + // Arrange + let color = UIColor.red + let state: UIControl.State = .normal + + // Act + button?.setBackgroundColor(color, for: state) + + // Assert + XCTAssertNotNil(button?.currentBackgroundImage, "Button background image not nil") + } + + func testSetBackgroundColorForDifferentStates() { + // Arrange + + let selectedColor = UIColor.green + + // Act + button?.isSelected = true + button?.setBackgroundColor(selectedColor, for: .selected) + + // Assert + XCTAssertNotNil(button?.currentBackgroundImage, "Button background image not nil") + button?.isSelected = false + XCTAssertNil(button?.currentBackgroundImage,"Button background image will be nil") + button?.isHighlighted = true + XCTAssertNil(button?.currentBackgroundImage, "Button background image will be nil") + } + + //UIView extension shadow test case + func testAddShadowWithLocation() { + // Create a UIView instance + let view = UIView() + + // Set the shadow with bottom location + view.addShadow(location: .bottom, height: 2, color: .red, opacity: 0.4, radius: 2) + + // Verify that the shadow offset is set correctly for the bottom location + let bottomShadowOffset = view.layer.shadowOffset + XCTAssertEqual(bottomShadowOffset, CGSize(width: 0, height: 2), "Shadow offset not set correctly for bottom location") + + // Verify that the shadow color is set correctly + let shadowColor = view.layer.shadowColor + XCTAssertEqual(shadowColor, UIColor.red.cgColor, "Shadow color not set correctly") + + // Verify that the shadow opacity is set correctly + let shadowOpacity = view.layer.shadowOpacity + XCTAssertEqual(shadowOpacity, 0.4, "Shadow opacity not set correctly") + + // Verify that the shadow radius is set correctly + let shadowRadius = view.layer.shadowRadius + XCTAssertEqual(shadowRadius, 2.0, "Shadow radius not set correctly") + } + + func testAddShadowWithOffset() { + // Create a UIView instance + let view = UIView() + + // Set the shadow with a custom offset + view.addShadow(offset: CGSize(width: 0, height: -4), color: .blue, opacity: 0.6, radius: 3) + + // Verify that the shadow offset is set correctly + let shadowOffset = view.layer.shadowOffset + XCTAssertEqual(shadowOffset, CGSize(width: 0, height: -4), "Shadow offset not set correctly") + + // Verify that the shadow color is set correctly + let shadowColor = view.layer.shadowColor + XCTAssertEqual(shadowColor, UIColor.blue.cgColor, "Shadow color not set correctly") + + // Verify that the shadow opacity is set correctly + let shadowOpacity = view.layer.shadowOpacity + XCTAssertEqual(shadowOpacity, 0.6, "Shadow opacity not set correctly") + + // Verify that the shadow radius is set correctly + let shadowRadius = view.layer.shadowRadius + XCTAssertEqual(shadowRadius, 3.0, "Shadow radius not set correctly") + } + + func testAddShadowForLocation() { + // Create a UIView instance + let view = UIView() + + // Add shadow to the bottom + view.addShadow(location: .bottom, color: UIColor.black) + + // Verify that the shadow properties are set correctly for the bottom location + XCTAssertEqual(view.layer.shadowOffset, CGSize(width: 0, height: 2), "Shadow offset not set correctly for bottom location") + XCTAssertEqual(view.layer.shadowColor, UIColor.black.cgColor, "Shadow color not set correctly for bottom location") + XCTAssertEqual(view.layer.shadowOpacity, 0.4, "Shadow opacity not set correctly for bottom location") + XCTAssertEqual(view.layer.shadowRadius, 2.0, "Shadow radius not set correctly for bottom location") + + // Add shadow to the top + view.addShadow(location: .top) + + // Verify that the shadow properties are set correctly for the top location + XCTAssertEqual(view.layer.shadowOffset, CGSize(width: 0, height: -2), "Shadow offset not set correctly for top location") + XCTAssertEqual(view.layer.shadowColor, NCBrandColor.shared.customerDarkGrey.cgColor, "Shadow color not set correctly for top location") + XCTAssertEqual(view.layer.shadowOpacity, 0.4, "Shadow opacity not set correctly for top location") + XCTAssertEqual(view.layer.shadowRadius, 2.0, "Shadow radius not set correctly for top location") + } + + func testAddShadowForOffset() { + // Create a UIView instance + let view = UIView() + + // Add shadow with custom offset + view.addShadow(offset: CGSize(width: 2, height: 2)) + + // Verify that the shadow properties are set correctly for the custom offset + XCTAssertEqual(view.layer.shadowOffset, CGSize(width: 2, height: 2), "Shadow offset not set correctly for custom offset") + XCTAssertEqual(view.layer.shadowColor, UIColor.black.cgColor, "Shadow color not set correctly for custom offset") + XCTAssertEqual(view.layer.shadowOpacity, 0.5, "Shadow opacity not set correctly for custom offset") + XCTAssertEqual(view.layer.shadowRadius, 5.0, "Shadow radius not set correctly for custom offset") + } + + + func testHasUploadPermission() { + // Create an instance of NCShare + let share = NCShare() + + // Define the input parameters + let tableShareWithUploadPermission = tableShare() + tableShareWithUploadPermission.permissions = NCGlobal.shared.permissionMaxFileShare + + let tableShareWithoutUploadPermission = tableShare() + tableShareWithoutUploadPermission.permissions = NCGlobal.shared.permissionReadShare + + // Call the hasUploadPermission function + let hasUploadPermission1 = share.hasUploadPermission(tableShare: tableShareWithUploadPermission) + let hasUploadPermission2 = share.hasUploadPermission(tableShare: tableShareWithoutUploadPermission) + + // Verify the results + XCTAssertTrue(hasUploadPermission1, "hasUploadPermission returned false for a tableShare with upload permission") + XCTAssertFalse(hasUploadPermission2, "hasUploadPermission returned true for a tableShare without upload permission") + } + + func testGetImageShareType() { + let sut = NCShareCommon() // Replace with the actual class containing the getImageShareType function + + // Test case 1: SHARE_TYPE_USER + let shareType1 = sut.SHARE_TYPE_USER + let result1 = sut.getImageShareType(shareType: shareType1) + XCTAssertEqual(result1, UIImage(named: "shareTypeEmail")?.imageColor(NCBrandColor.shared.label)) + + // Test case 2: SHARE_TYPE_GROUP + let shareType2 = sut.SHARE_TYPE_GROUP + let result2 = sut.getImageShareType(shareType: shareType2) + XCTAssertEqual(result2, UIImage(named: "shareTypeGroup")?.imageColor(NCBrandColor.shared.label)) + + // Test case 3: SHARE_TYPE_LINK + let shareType3 = sut.SHARE_TYPE_LINK + let result3 = sut.getImageShareType(shareType: shareType3) + XCTAssertEqual(result3, UIImage(named: "shareTypeLink")?.imageColor(NCBrandColor.shared.label)) + + // Test case 4: SHARE_TYPE_EMAIL (with isDropDown=false) + let shareType4 = sut.SHARE_TYPE_EMAIL + let result4 = sut.getImageShareType(shareType: shareType4) + XCTAssertEqual(result4, UIImage(named: "shareTypeUser")?.imageColor(NCBrandColor.shared.label)) + + // Test case 5: SHARE_TYPE_EMAIL (with isDropDown=true) + let shareType5 = sut.SHARE_TYPE_EMAIL + let isDropDown5 = true + let result5 = sut.getImageShareType(shareType: shareType5, isDropDown: isDropDown5) + XCTAssertEqual(result5, UIImage(named: "email")?.imageColor(NCBrandColor.shared.label)) + } +} diff --git a/iOSClient/Extensions/DateFormatter+Extension.swift b/iOSClient/Extensions/DateFormatter+Extension.swift index dceb24e7e7..5d6a004843 100644 --- a/iOSClient/Extensions/DateFormatter+Extension.swift +++ b/iOSClient/Extensions/DateFormatter+Extension.swift @@ -29,6 +29,15 @@ extension DateFormatter { let dateFormatter = DateFormatter() dateFormatter.formatterBehavior = .behavior10_4 dateFormatter.dateStyle = .medium + dateFormatter.dateFormat = NCShareAdvancePermission.displayDateFormat return dateFormatter }() } + +extension Date { + static var tomorrow: Date { return Date().dayAfter } + static var today: Date {return Date()} + var dayAfter: Date { + return Calendar.current.date(byAdding: .day, value: 1, to: Date())! + } +} diff --git a/iOSClient/Extensions/UIButton+Extension.swift b/iOSClient/Extensions/UIButton+Extension.swift index 70a85857a5..2879bc1ed0 100644 --- a/iOSClient/Extensions/UIButton+Extension.swift +++ b/iOSClient/Extensions/UIButton+Extension.swift @@ -29,12 +29,21 @@ extension UIButton { } func hideSpinnerAndShowButton() { - let spinnerTag = Int(bitPattern: Unmanaged.passUnretained(self).toOpaque()) - let spinner = self.superview?.subviews.first(where: { view -> Bool in - return view.isKind(of: UIActivityIndicatorView.self) && view.tag == spinnerTag - }) + let spinnerTag = Int(bitPattern: Unmanaged.passUnretained(self).toOpaque()) + let spinner = self.superview?.subviews.first(where: { view -> Bool in + return view.isKind(of: UIActivityIndicatorView.self) && view.tag == spinnerTag + }) - spinner?.removeFromSuperview() - self.isHidden = false - } + spinner?.removeFromSuperview() + self.isHidden = false + } + + func setBackgroundColor(_ color: UIColor, for forState: UIControl.State) { + UIGraphicsBeginImageContext(CGSize(width: 1, height: 1)) + UIGraphicsGetCurrentContext()!.setFillColor(color.cgColor) + UIGraphicsGetCurrentContext()!.fill(CGRect(x: 0, y: 0, width: 1, height: 1)) + let colorImage = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + self.setBackgroundImage(colorImage, for: forState) + } } diff --git a/iOSClient/Extensions/UIToolbar+Extension.swift b/iOSClient/Extensions/UIToolbar+Extension.swift index 3f1f36fcaf..ac403c9791 100644 --- a/iOSClient/Extensions/UIToolbar+Extension.swift +++ b/iOSClient/Extensions/UIToolbar+Extension.swift @@ -58,6 +58,20 @@ extension UIToolbar { ]) return view } + + static func doneToolbar(completion: @escaping () -> Void) -> UIToolbar { + let doneToolbar: UIToolbar = UIToolbar(frame: CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50)) + doneToolbar.barStyle = .default + + let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) + let done: UIBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_done_", comment: ""), style: .done) { + completion() + } + let items = [flexSpace, done] + doneToolbar.items = items + doneToolbar.sizeToFit() + return doneToolbar + } } // https://stackoverflow.com/a/67985180/9506784 diff --git a/iOSClient/Extensions/UIView+Extension.swift b/iOSClient/Extensions/UIView+Extension.swift index a49d1300f0..4673ca902c 100644 --- a/iOSClient/Extensions/UIView+Extension.swift +++ b/iOSClient/Extensions/UIView+Extension.swift @@ -24,6 +24,11 @@ import Foundation import UIKit +enum VerticalLocation: String { + case bottom + case top +} + extension UIView { // Source @@ -69,4 +74,21 @@ extension UIView { self.layer.cornerRadius = self.frame.size.width / 2 self.layer.masksToBounds = true } + + func addShadow(location: VerticalLocation, height: CGFloat = 2, color: UIColor = NCBrandColor.shared.customerDarkGrey, opacity: Float = 0.4, radius: CGFloat = 2) { + switch location { + case .bottom: + addShadow(offset: CGSize(width: 0, height: height), color: color, opacity: opacity, radius: radius) + case .top: + addShadow(offset: CGSize(width: 0, height: -height), color: color, opacity: opacity, radius: radius) + } + } + + func addShadow(offset: CGSize, color: UIColor = .black, opacity: Float = 0.5, radius: CGFloat = 5.0) { + self.layer.masksToBounds = false + self.layer.shadowColor = color.cgColor + self.layer.shadowOffset = offset + self.layer.shadowOpacity = opacity + self.layer.shadowRadius = radius + } } diff --git a/iOSClient/Main/NCActionCenter.swift b/iOSClient/Main/NCActionCenter.swift index f777147968..7908f0ea3f 100644 --- a/iOSClient/Main/NCActionCenter.swift +++ b/iOSClient/Main/NCActionCenter.swift @@ -305,34 +305,9 @@ class NCActionCenter: NSObject, UIDocumentInteractionControllerDelegate, NCSelec NCActivityIndicator.shared.stop() if let metadata = metadata, error == .success { - var pages: [NCBrandOptions.NCInfoPagingTab] = [] let shareNavigationController = UIStoryboard(name: "NCShare", bundle: nil).instantiateInitialViewController() as? UINavigationController - let shareViewController = shareNavigationController?.topViewController as? NCSharePaging - - for value in NCBrandOptions.NCInfoPagingTab.allCases { - pages.append(value) - } - - if NCCapabilities.shared.getCapabilities(account: account).capabilityActivity.isEmpty, let idx = pages.firstIndex(of: .activity) { - pages.remove(at: idx) - } - if !metadata.isSharable(), let idx = pages.firstIndex(of: .sharing) { - pages.remove(at: idx) - } - - (pages, page) = NCApplicationHandle().filterPages(pages: pages, page: page, metadata: metadata) - - shareViewController?.pages = pages + let shareViewController = shareNavigationController?.topViewController as? NCShare shareViewController?.metadata = metadata - - if pages.contains(page) { - shareViewController?.page = page - } else if let page = pages.first { - shareViewController?.page = page - } else { - return - } - shareNavigationController?.modalPresentationStyle = .formSheet if let shareNavigationController = shareNavigationController { viewController.present(shareNavigationController, animated: true, completion: nil) diff --git a/iOSClient/Menu/NCShare+Menu.swift b/iOSClient/Menu/NCShare+Menu.swift index b9f1abcc58..6de4cc8444 100644 --- a/iOSClient/Menu/NCShare+Menu.swift +++ b/iOSClient/Menu/NCShare+Menu.swift @@ -26,17 +26,17 @@ import UIKit import NextcloudKit extension NCShare { - func toggleShareMenu(for share: tableShare) { - let capabilities = NCCapabilities.shared.getCapabilities(account: self.metadata.account) + func toggleShareMenu(for share: tableShare, sendMail: Bool, folder: Bool, sender: Any) { + var actions = [NCMenuAction]() - if share.shareType == 3, canReshare { + if !folder { actions.append( NCMenuAction( - title: NSLocalizedString("_share_add_sharelink_", comment: ""), - icon: utility.loadImage(named: "plus", colors: [NCBrandColor.shared.iconImageColor]), + title: NSLocalizedString("_open_in_", comment: ""), + icon: utility.loadImage(named: "viewInFolder").imageColor(NCBrandColor.shared.brandElement), action: { _ in - self.makeNewLinkShare() + NCShareCommon().copyLink(link: share.url, viewController: self, sender: sender) } ) ) @@ -44,15 +44,17 @@ extension NCShare { actions.append( NCMenuAction( - title: NSLocalizedString("_details_", comment: ""), - icon: utility.loadImage(named: "pencil", colors: [NCBrandColor.shared.iconImageColor]), - accessibilityIdentifier: "shareMenu/details", +// title: NSLocalizedString("_details_", comment: ""), +// icon: utility.loadImage(named: "pencil", colors: [NCBrandColor.shared.iconImageColor]), +// accessibilityIdentifier: "shareMenu/details", + title: NSLocalizedString("_advance_permissions_", comment: ""), + icon: utility.loadImage(named: "rename").imageColor(NCBrandColor.shared.brandElement), action: { _ in guard let advancePermission = UIStoryboard(name: "NCShare", bundle: nil).instantiateViewController(withIdentifier: "NCShareAdvancePermission") as? NCShareAdvancePermission, let navigationController = self.navigationController, !share.isInvalidated else { return } advancePermission.networking = self.networking - advancePermission.share = tableShare(value: share) + advancePermission.share = share advancePermission.oldTableShare = tableShare(value: share) advancePermission.metadata = self.metadata @@ -64,12 +66,28 @@ extension NCShare { } ) ) - + + if sendMail { + actions.append( + NCMenuAction( + title: NSLocalizedString("_send_new_email_", comment: ""), + icon: NCUtility().loadImage(named: "email").imageColor(NCBrandColor.shared.brandElement), + action: { menuAction in + let storyboard = UIStoryboard(name: "NCShare", bundle: nil) + guard let viewNewUserComment = storyboard.instantiateViewController(withIdentifier: "NCShareNewUserAddComment") as? NCShareNewUserAddComment else { return } + viewNewUserComment.metadata = self.metadata + viewNewUserComment.share = tableShare(value: share) + viewNewUserComment.networking = self.networking + self.navigationController?.pushViewController(viewNewUserComment, animated: true) + } + ) + ) + } + actions.append( NCMenuAction( title: NSLocalizedString("_share_unshare_", comment: ""), - destructive: true, - icon: utility.loadImage(named: "person.2.slash"), + icon: utility.loadImage(named: "trash").imageColor(NCBrandColor.shared.brandElement), action: { _ in Task { if share.shareType != NCShareCommon().SHARE_TYPE_LINK, let metadata = self.metadata, metadata.e2eEncrypted && capabilities.capabilityE2EEApiVersion == NCGlobal.shared.e2eeVersionV20 { @@ -99,8 +117,8 @@ extension NCShare { actions.append( NCMenuAction( title: NSLocalizedString("_share_read_only_", comment: ""), - icon: utility.loadImage(named: "eye", colors: [NCBrandColor.shared.iconImageColor]), - selected: tableShare.permissions == (permissions.permissionReadShare + permissions.permissionShareShare) || tableShare.permissions == permissions.permissionReadShare, + icon: UIImage(), + selected: tableShare.permissions == (NCGlobal.shared.permissionReadShare + NCGlobal.shared.permissionShareShare) || tableShare.permissions == NCGlobal.shared.permissionReadShare, on: false, action: { _ in let canShare = permissions.isPermissionToCanShare(tableShare.permissions) @@ -113,7 +131,7 @@ extension NCShare { actions.append( NCMenuAction( title: isDirectory ? NSLocalizedString("_share_allow_upload_", comment: "") : NSLocalizedString("_share_editing_", comment: ""), - icon: utility.loadImage(named: "pencil", colors: [NCBrandColor.shared.iconImageColor]), + icon: UIImage(), selected: hasUploadPermission(tableShare: tableShare), on: false, action: { _ in @@ -124,6 +142,22 @@ extension NCShare { ) ) + if isDirectory, + NCShareCommon().isFileDropOptionVisible(isDirectory: isDirectory, shareType: tableShare.shareType) { + actions.append( + NCMenuAction( + title: NSLocalizedString("_share_file_drop_", comment: ""), + icon: tableShare.permissions == NCGlobal.shared.permissionCreateShare ? UIImage(named: "success")?.image(color: NCBrandColor.shared.customer, size: 25.0) ?? UIImage() : UIImage(), + selected: false, + on: false, + action: { menuAction in + let permissions = NCGlobal.shared.permissionCreateShare + self.updateSharePermissions(share: tableShare, permissions: permissions) + } + ) + ) + } + self.presentMenu(with: actions) } diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift index cbbd8c1e3f..c787c4948f 100644 --- a/iOSClient/NCGlobal.swift +++ b/iOSClient/NCGlobal.swift @@ -328,6 +328,15 @@ final class NCGlobal: Sendable { 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" diff --git a/iOSClient/Networking/NCService.swift b/iOSClient/Networking/NCService.swift index 345d7d05ea..90d82f906c 100644 --- a/iOSClient/Networking/NCService.swift +++ b/iOSClient/Networking/NCService.swift @@ -184,6 +184,27 @@ class NCService: NSObject { NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterChangeTheming, userInfo: ["account": account]) } + // Sharing & Comments + if !NCGlobal.shared.capabilityFileSharingApiEnabled && !NCGlobal.shared.capabilityFilesComments && NCGlobal.shared.capabilityActivity.isEmpty { + self.appDelegate.disableSharesView = true + } else { + self.appDelegate.disableSharesView = false + } + + // File Sharing + if NCGlobal.shared.capabilityFileSharingApiEnabled { + let home = self.utilityFileSystem.getHomeServer(urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId) + NextcloudKit.shared.readShares(parameters: NKShareParameter()) { account, shares, data, error in + if error == .success { + NCManageDatabase.shared.deleteTableShare(account: account) + if let shares = shares, !shares.isEmpty { + NCManageDatabase.shared.addShare(account: account, home: home, shares: shares) + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource) + } + } + } + } + // Text direct editor detail if capability.capabilityServerVersionMajor >= NCGlobal.shared.nextcloudVersion18 { let options = NKRequestOptions(queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue) diff --git a/iOSClient/Scan document/PasswordInputField.swift b/iOSClient/Scan document/PasswordInputField.swift new file mode 100644 index 0000000000..c2b893324b --- /dev/null +++ b/iOSClient/Scan document/PasswordInputField.swift @@ -0,0 +1,75 @@ +// +// PasswordInputField.swift +// Nextcloud +// +// Created by Sumit on 10/06/21. +// Copyright © 2021 Marino Faggiana. All rights reserved. +// + +import Foundation + +class PasswordInputField: XLFormBaseCell,UITextFieldDelegate { + + @IBOutlet weak var fileNameInputTextField: UITextField! + @IBOutlet weak var separatorBottom: UIView! + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + fileNameInputTextField.isSecureTextEntry = true + fileNameInputTextField.delegate = self + separatorBottom.backgroundColor = NCBrandColor.shared.systemGray4 + self.selectionStyle = .none + fileNameInputTextField.inputAccessoryView = UIToolbar.doneToolbar { + self.fileNameInputTextField.resignFirstResponder() + } + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + + override func configure() { + super.configure() + // fileNameInputTextField.isEnabled = false + + } + + override func update() { + super.update() + } + + func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + + if fileNameInputTextField == textField { + if let rowDescriptor = rowDescriptor, let text = self.fileNameInputTextField.text { + + if (text + " ").isEmpty == false { + rowDescriptor.value = self.fileNameInputTextField.text! + string + } else { + rowDescriptor.value = nil + } + } + } + + self.formViewController().textField(textField, shouldChangeCharactersIn: range, replacementString: string) + + return true + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + self.formViewController()?.textFieldShouldReturn(fileNameInputTextField) + return true + } + + func textFieldShouldClear(_ textField: UITextField) -> Bool { + self.formViewController()?.textFieldShouldClear(fileNameInputTextField) + return true + } + + override class func formDescriptorCellHeight(for rowDescriptor: XLFormRowDescriptor!) -> CGFloat { + return 45 + } +} diff --git a/iOSClient/Scan document/PasswordInputField.xib b/iOSClient/Scan document/PasswordInputField.xib new file mode 100644 index 0000000000..26914e0760 --- /dev/null +++ b/iOSClient/Scan document/PasswordInputField.xib @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOSClient/Share/Advanced/NCFilePermissionCell.swift b/iOSClient/Share/Advanced/NCFilePermissionCell.swift new file mode 100644 index 0000000000..4e5ec77f72 --- /dev/null +++ b/iOSClient/Share/Advanced/NCFilePermissionCell.swift @@ -0,0 +1,91 @@ +// +// NCFilePermissionCell.swift +// Nextcloud +// +// Created by T-systems on 17/08/21. +// Copyright © 2021 Marino Faggiana. All rights reserved. +// + +import UIKit + +class NCFilePermissionCell: XLFormButtonCell { + + @IBOutlet weak var seperator: UIView! + @IBOutlet weak var titleLabel: UILabel! + @IBOutlet weak var imageCheck: UIImageView! + @IBOutlet weak var seperatorBelow: UIView! + @IBOutlet weak var seperatorBelowFull: UIView! + @IBOutlet weak var titleLabelBottom: UILabel! + + override func awakeFromNib() { + super.awakeFromNib() + self.selectionStyle = .none + self.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + self.titleLabel.textColor = NCBrandColor.shared.label + NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil) + } + + @objc func changeTheming() { + self.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + self.titleLabel.textColor = NCBrandColor.shared.label + self.titleLabelBottom.textColor = NCBrandColor.shared.iconColor + } + + override func configure() { + super.configure() + } + + + override func update() { + super.update() + self.selectionStyle = .none + if rowDescriptor.tag == "NCFilePermissionCellSharing" || rowDescriptor.tag == "NCFilePermissionCellAdvanceTxt" { + self.seperator.isHidden = true + self.seperatorBelowFull.isHidden = true + self.seperatorBelow.isHidden = true + self.titleLabel.font = UIFont.boldSystemFont(ofSize: 17) + self.titleLabelBottom.font = UIFont.boldSystemFont(ofSize: 17) + } + if rowDescriptor.tag == "kNMCFilePermissionCellEditing" { + self.seperator.isHidden = true +// self.seperatorBelowFull.isHidden = true + } + + if rowDescriptor.tag == "NCFilePermissionCellFileDrop" { + self.seperator.isHidden = true + self.seperatorBelow.isHidden = false + self.seperatorBelowFull.isHidden = true + } + + if rowDescriptor.tag == "kNMCFilePermissionEditCellEditingCanShare" { + self.seperator.isHidden = true + self.seperatorBelowFull.isHidden = false + } + + if rowDescriptor.tag == "kNMCFilePermissionCellEditingMsg" { + self.seperator.isHidden = true + self.seperatorBelow.isHidden = true + self.seperatorBelowFull.isHidden = false + } + + if rowDescriptor.tag == "kNMCFilePermissionCellFiledropMessage" { + self.seperator.isHidden = true + self.seperatorBelow.isHidden = true + self.seperatorBelowFull.isHidden = false + self.imageCheck.isHidden = true + } + } + + @objc func switchChanged(mySwitch: UISwitch) { + self.rowDescriptor.value = mySwitch.isOn + } + + override func formDescriptorCellDidSelected(withForm controller: XLFormViewController!) { + self.selectionStyle = .none + } + + override class func formDescriptorCellHeight(for rowDescriptor: XLFormRowDescriptor!) -> CGFloat { + return 44.0 + } + +} diff --git a/iOSClient/Share/Advanced/NCFilePermissionCell.xib b/iOSClient/Share/Advanced/NCFilePermissionCell.xib new file mode 100644 index 0000000000..e40c22e14d --- /dev/null +++ b/iOSClient/Share/Advanced/NCFilePermissionCell.xib @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOSClient/Share/Advanced/NCFilePermissionEditCell.swift b/iOSClient/Share/Advanced/NCFilePermissionEditCell.swift new file mode 100644 index 0000000000..b32d66a74f --- /dev/null +++ b/iOSClient/Share/Advanced/NCFilePermissionEditCell.swift @@ -0,0 +1,176 @@ +// +// NCFilePermissionEditCell.swift +// Nextcloud +// +// Created by T-systems on 10/08/21. +// Copyright © 2021 Marino Faggiana. All rights reserved. +// + +import UIKit + +class NCFilePermissionEditCell: XLFormBaseCell, UITextFieldDelegate { + + @IBOutlet weak var seperator: UIView! + @IBOutlet weak var seperatorMiddle: UIView! + @IBOutlet weak var seperatorBottom: UIView! + @IBOutlet weak var titleLabel: UILabel! + @IBOutlet weak var switchControl: UISwitch! + @IBOutlet weak var cellTextField: UITextField! + @IBOutlet weak var buttonLinkLabel: UIButton! + let datePicker = UIDatePicker() + var expirationDateText: String! + var expirationDate: NSDate! + + override func awakeFromNib() { + super.awakeFromNib() + self.cellTextField.delegate = self + self.cellTextField.isEnabled = false + self.selectionStyle = .none + switchControl.addTarget(self, action: #selector(switchChanged), for: UIControl.Event.valueChanged) + self.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + self.titleLabel.textColor = NCBrandColor.shared.label + self.cellTextField.attributedPlaceholder = NSAttributedString(string: "", + attributes: [NSAttributedString.Key.foregroundColor: NCBrandColor.shared.fileFolderName]) + self.cellTextField.textColor = NCBrandColor.shared.singleTitleColorButton + NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil) + } + + @objc func changeTheming() { + self.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + self.titleLabel.textColor = NCBrandColor.shared.iconColor + } + + override func configure() { + super.configure() + } + + override func update() { + super.update() + + if rowDescriptor.tag == "kNMCFilePermissionCellEditingCanShare" { + self.seperatorMiddle.isHidden = true + self.seperatorBottom.isHidden = true + self.cellTextField.isHidden = true + } + if rowDescriptor.tag == "kNMCFilePermissionEditCellLinkLabel" { + self.switchControl.isHidden = true + self.cellTextField.isEnabled = true + self.seperatorBottom.isHidden = true + } + if rowDescriptor.tag == "kNMCFilePermissionEditCellLinkLabel" { + self.switchControl.isHidden = true + } + + if rowDescriptor.tag == "kNMCFilePermissionEditCellExpiration" { + self.seperator.isHidden = true + setDatePicker(sender: self.cellTextField) + } + + if rowDescriptor.tag == "kNMCFilePermissionEditPasswordCellWithText" { + self.seperatorMiddle.isHidden = true + self.seperator.isHidden = true + } + + if rowDescriptor.tag == "kNMCFilePermissionEditCellHideDownload" { + self.seperator.isHidden = true + self.seperatorMiddle.isHidden = true + } + + if rowDescriptor.tag == "kNMCFilePermissionEditCellEditingCanShare" { + self.seperator.isHidden = true + self.seperatorBottom.isHidden = true + } + } + + @objc func switchChanged(mySwitch: UISwitch) { + let isOn = mySwitch.isOn + if isOn { + //on + self.rowDescriptor.value = isOn + self.cellTextField.isEnabled = true + cellTextField.delegate = self + } else { + self.rowDescriptor.value = isOn + self.cellTextField.isEnabled = false + if rowDescriptor.tag == "kNMCFilePermissionEditCellExpiration" || rowDescriptor.tag == "kNMCFilePermissionEditCellPassword" { + self.cellTextField.text = "" + } + } + if rowDescriptor.tag == "kNMCFilePermissionEditPasswordCellWithText" { + seperatorBottom.isHidden = isOn + seperatorMiddle.isHidden = !isOn + } + if rowDescriptor.tag == "kNMCFilePermissionEditCellExpiration" { + seperatorBottom.isHidden = isOn + seperatorMiddle.isHidden = !isOn + } + } + + func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + if self.cellTextField == textField { + if let rowDescriptor = rowDescriptor, let text = self.cellTextField.text { + + if (text + " ").isEmpty == false { + rowDescriptor.value = self.cellTextField.text! + string + } else { + rowDescriptor.value = nil + } + } + } + + self.formViewController().textField(textField, shouldChangeCharactersIn: range, replacementString: string) + return true + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + self.formViewController()?.textFieldShouldReturn(textField) + return true + } + + func textFieldShouldClear(_ textField: UITextField) -> Bool { + self.formViewController()?.textFieldShouldClear(textField) + return true + } + + override class func formDescriptorCellHeight(for rowDescriptor: XLFormRowDescriptor!) -> CGFloat { + return 30 + } + + override func formDescriptorCellDidSelected(withForm controller: XLFormViewController!) { + self.selectionStyle = .none + } + + func setDatePicker(sender: UITextField) { + //Format Date + datePicker.datePickerMode = .date + datePicker.minimumDate = Date() + //ToolBar + let toolbar = UIToolbar(); + toolbar.sizeToFit() + let doneButton = UIBarButtonItem(title: NSLocalizedString("_done_", comment: ""), style: .plain, target: self, action: #selector(doneDatePicker)); + let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil) + let cancelButton = UIBarButtonItem(title: NSLocalizedString("_cancel_", comment: ""), style: .plain, target: self, action: #selector(cancelDatePicker)); + + toolbar.setItems([doneButton,spaceButton,cancelButton], animated: false) + + sender.inputAccessoryView = toolbar + sender.inputView = datePicker + } + + @objc func doneDatePicker() { + let dateFormatter = DateFormatter() + dateFormatter.formatterBehavior = .behavior10_4 + dateFormatter.dateStyle = .medium + self.expirationDateText = dateFormatter.string(from: datePicker.date as Date) + + dateFormatter.dateFormat = "YYYY-MM-dd HH:mm:ss" + self.expirationDate = datePicker.date as NSDate + self.cellTextField.text = self.expirationDateText + self.rowDescriptor.value = self.expirationDate + self.cellTextField.endEditing(true) + } + + @objc func cancelDatePicker() { + self.cellTextField.endEditing(true) + } +} diff --git a/iOSClient/Share/Advanced/NCFilePermissionEditCell.xib b/iOSClient/Share/Advanced/NCFilePermissionEditCell.xib new file mode 100644 index 0000000000..2a7aa3ac63 --- /dev/null +++ b/iOSClient/Share/Advanced/NCFilePermissionEditCell.xib @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOSClient/Share/Advanced/NCShareAdvancePermission.swift b/iOSClient/Share/Advanced/NCShareAdvancePermission.swift index a57e926429..a94116be1d 100644 --- a/iOSClient/Share/Advanced/NCShareAdvancePermission.swift +++ b/iOSClient/Share/Advanced/NCShareAdvancePermission.swift @@ -26,58 +26,44 @@ import NextcloudKit import SVGKit import CloudKit -class NCShareAdvancePermission: UITableViewController, NCShareAdvanceFotterDelegate, NCShareNavigationTitleSetting { +class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelegate, NCShareDetail { func dismissShareAdvanceView(shouldSave: Bool) { - guard shouldSave else { - guard oldTableShare?.hasChanges(comparedTo: share) != false else { - navigationController?.popViewController(animated: true) - return - } - - let alert = UIAlertController( - title: NSLocalizedString("_cancel_request_", comment: ""), - message: NSLocalizedString("_discard_changes_info_", comment: ""), - preferredStyle: .alert) - - alert.addAction(UIAlertAction( - title: NSLocalizedString("_discard_changes_", comment: ""), - style: .destructive, - handler: { _ in self.navigationController?.popViewController(animated: true) })) - - alert.addAction(UIAlertAction(title: NSLocalizedString("_continue_editing_", comment: ""), style: .default)) - self.present(alert, animated: true) - - return - } - - Task { - // TODO: Apply share token to download limit object - + if shouldSave { + self.oldTableShare?.permissions = self.permission ?? (self.oldTableShare?.permissions ?? 0) + self.share.permissions = self.permission ?? (self.oldTableShare?.permissions ?? 0) if isNewShare { - let serverUrl = metadata.serverUrl + "/" + metadata.fileName - - if share.shareType != NCShareCommon().SHARE_TYPE_LINK, metadata.e2eEncrypted, - NCCapabilities.shared.getCapabilities(account: metadata.account).capabilityE2EEApiVersion == NCGlobal.shared.e2eeVersionV20 { - - if NCNetworkingE2EE().isInUpload(account: metadata.account, serverUrl: serverUrl) { - let error = NKError(errorCode: NCGlobal.shared.errorE2EEUploadInProgress, errorDescription: NSLocalizedString("_e2e_in_upload_", comment: "")) - return NCContentPresenter().showInfo(error: error) - } - - let error = await NCNetworkingE2EE().uploadMetadata(serverUrl: serverUrl, addUserId: share.shareWith, removeUserId: nil, account: metadata.account) - - if error != .success { - return NCContentPresenter().showError(error: error) + let storyboard = UIStoryboard(name: "NCShare", bundle: nil) + guard let viewNewUserComment = storyboard.instantiateViewController(withIdentifier: "NCShareNewUserAddComment") as? NCShareNewUserAddComment else { return } + viewNewUserComment.metadata = self.metadata + viewNewUserComment.share = self.share + viewNewUserComment.networking = self.networking + self.navigationController?.pushViewController(viewNewUserComment, animated: true) + } else { + if let downloadSwitchCell = getDownloadLimitSwitchCell() { + let isDownloadLimitOn = downloadSwitchCell.switchControl.isOn + if !isDownloadLimitOn { + setDownloadLimit(deleteLimit: true, limit: "") + } else { + let downloadLimitInputCell = getDownloadLimitInputCell() + let enteredDownloadLimit = downloadLimitInputCell?.cellTextField.text ?? "" + if enteredDownloadLimit.isEmpty { + showDownloadLimitError(message: NSLocalizedString("_share_download_limit_alert_empty_", comment: "")) + return + } + if let num = Int(enteredDownloadLimit), num < 1 { + showDownloadLimitError(message: NSLocalizedString("_share_download_limit_alert_zero_", comment: "")) + return + } + setDownloadLimit(deleteLimit: false, limit: enteredDownloadLimit) } } - - networking?.createShare(share, downloadLimit: self.downloadLimit) - } else { - networking?.updateShare(share, downloadLimit: self.downloadLimit) + + networking?.updateShare(option: share) + navigationController?.popViewController(animated: true) } + } else { + navigationController?.popViewController(animated: true) } - - navigationController?.popViewController(animated: true) } let database = NCManageDatabase.shared @@ -108,32 +94,29 @@ class NCShareAdvancePermission: UITableViewController, NCShareAdvanceFotterDeleg var shareConfig: NCShareConfig! var networking: NCShareNetworking? - + let tableViewBottomInset: CGFloat = 80.0 + lazy var shareType: Int = { + isNewShare ? share.shareType : oldTableShare?.shareType ?? NCShareCommon().SHARE_TYPE_USER + }() + static let displayDateFormat = "dd. MMM. yyyy" + var downloadLimit: DownloadLimit? + var permission: Int? + override func viewDidLoad() { super.viewDidLoad() self.shareConfig = NCShareConfig(parentMetadata: metadata, share: share) - - // Only persisted shares have tokens which are provided by the server. - // A download limit requires a token to exist. - // Hence it can only be looked up if the share is already persisted at this point. - if isNewShare == false { - if let persistedShare = share as? tableShare { - do { - if let limit = try database.getDownloadLimit(byAccount: metadata.account, shareToken: persistedShare.token) { - self.downloadLimit = .limited(limit: limit.limit, count: limit.count) - } - } catch { - NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] There was an error while fetching the download limit for share with token \(persistedShare.token)!") - } - } - } - - tableView.estimatedRowHeight = tableView.rowHeight - tableView.rowHeight = UITableView.automaticDimension self.setNavigationTitle() - self.navigationItem.hidesBackButton = true - // disable pull to dimiss + // disbale pull to dimiss isModalInPresentation = true + self.tableView.separatorStyle = UITableViewCell.SeparatorStyle.none + self.permission = oldTableShare?.permissions + initializeForm() + changeTheming() + getDownloadLimit() + NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil) + + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil) } override func viewWillLayoutSubviews() { @@ -142,125 +125,699 @@ class NCShareAdvancePermission: UITableViewController, NCShareAdvanceFotterDeleg setupHeaderView() setupFooterView() } + + override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { + if (UIDevice.current.userInterfaceIdiom == .phone), UIDevice().hasNotch { + let isLandscape = UIDevice.current.orientation.isLandscape + let tableViewWidth = isLandscape ? view.bounds.width - 80 : view.bounds.width + tableView.frame = CGRect(x: isLandscape ? 40 : 0, y: tableView.frame.minY, width: tableViewWidth, height: tableView.bounds.height) + tableView.layoutIfNeeded() + } + } + + @objc func keyboardWillShow(_ notification:Notification) { + if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue { + tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height + 60, right: 0) + } + } + + @objc func keyboardWillHide(_ notification:Notification) { + if ((notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil { + tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: tableViewBottomInset, right: 0) + } + } + @objc func changeTheming() { + tableView.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + self.view.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + self.navigationController?.navigationBar.tintColor = NCBrandColor.shared.customer + tableView.reloadData() + } + func setupFooterView() { guard let footerView = (Bundle.main.loadNibNamed("NCShareAdvancePermissionFooter", owner: self, options: nil)?.first as? NCShareAdvancePermissionFooter) else { return } footerView.setupUI(delegate: self, account: metadata.account) // tableFooterView can't use auto layout directly - let container = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 120)) - container.addSubview(footerView) - tableView.tableFooterView = container + footerView.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 100) + self.view.addSubview(footerView) footerView.translatesAutoresizingMaskIntoConstraints = false - footerView.bottomAnchor.constraint(equalTo: container.bottomAnchor).isActive = true - footerView.heightAnchor.constraint(equalTo: container.heightAnchor).isActive = true - footerView.widthAnchor.constraint(equalTo: container.widthAnchor).isActive = true + footerView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true + footerView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true + footerView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true + footerView.heightAnchor.constraint(equalToConstant: 100).isActive = true + tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: tableViewBottomInset, right: 0) + } func setupHeaderView() { guard let headerView = (Bundle.main.loadNibNamed("NCShareHeader", owner: self, options: nil)?.first as? NCShareHeader) else { return } headerView.setupUI(with: metadata) - - let container = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 220)) - container.addSubview(headerView) - tableView.tableHeaderView = container + headerView.ocId = metadata.ocId + headerView.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 190) + self.tableView.tableHeaderView = headerView headerView.translatesAutoresizingMaskIntoConstraints = false - headerView.topAnchor.constraint(equalTo: container.topAnchor).isActive = true - headerView.heightAnchor.constraint(equalTo: container.heightAnchor).isActive = true - headerView.widthAnchor.constraint(equalTo: container.widthAnchor).isActive = true + headerView.heightAnchor.constraint(equalToConstant: 190).isActive = true + headerView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true } - override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { - if section == 0 { - return NSLocalizedString("_permissions_", comment: "") - } else if section == 1 { - return NSLocalizedString("_advanced_", comment: "") - } else { return nil } + func initializeForm() { + let form : XLFormDescriptor + var section : XLFormSectionDescriptor + var row : XLFormRowDescriptor + + form = XLFormDescriptor(title: "Other Cells") + + //Sharing + section = XLFormSectionDescriptor.formSection(withTitle: "") + XLFormViewController.cellClassesForRowDescriptorTypes()["kNMCFilePermissionCell"] = NCFilePermissionCell.self + row = XLFormRowDescriptor(tag: "NCFilePermissionCellSharing", rowType: "kNMCFilePermissionCell", title: "") + row.cellConfig["titleLabel.text"] = NSLocalizedString("_sharing_", comment: "") + row.height = 44 + section.addFormRow(row) + + //PERMISSION + XLFormViewController.cellClassesForRowDescriptorTypes()["kNMCShareHeaderCustomCell"] = NCShareHeaderCustomCell.self + row = XLFormRowDescriptor(tag: "kNMCShareHeaderCustomCell", rowType: "kNMCShareHeaderCustomCell", title: NSLocalizedString("_PERMISSIONS_", comment: "")) + row.height = 26 + row.cellConfig["titleLabel.text"] = NSLocalizedString("_PERMISSIONS_", comment: "") + section.addFormRow(row) + + //read only + XLFormViewController.cellClassesForRowDescriptorTypes()["kNMCFilePermissionCell"] = NCFilePermissionCell.self + row = XLFormRowDescriptor(tag: "NCFilePermissionCellRead", rowType: "kNMCFilePermissionCell", title: NSLocalizedString("_PERMISSIONS_", comment: "")) + row.cellConfig["titleLabel.text"] = NSLocalizedString("_share_read_only_", comment: "") + row.height = 44 + + if let permission = self.permission, !CCUtility.isAnyPermission(toEdit: permission), permission != NCGlobal.shared.permissionCreateShare { + row.cellConfig["imageCheck.image"] = UIImage(named: "success")!.image(color: NCBrandColor.shared.customer, size: 25.0) + } + if isNewShare { + row.cellConfig["imageCheck.image"] = UIImage(named: "success")!.image(color: NCBrandColor.shared.customer, size: 25.0) + self.permission = NCGlobal.shared.permissionReadShare + } + section.addFormRow(row) + + //editing + XLFormViewController.cellClassesForRowDescriptorTypes()["kNMCFilePermissionCell"] = NCFilePermissionCell.self + + row = XLFormRowDescriptor(tag: "kNMCFilePermissionCellEditing", rowType: "kNMCFilePermissionCell", title: NSLocalizedString("_PERMISSIONS_", comment: "")) + row.cellConfig["titleLabel.text"] = NSLocalizedString("_share_allow_editing_", comment: "") + row.height = 44 + if let permission = self.permission { + if CCUtility.isAnyPermission(toEdit: permission), permission != NCGlobal.shared.permissionCreateShare { + row.cellConfig["imageCheck.image"] = UIImage(named: "success")!.image(color: NCBrandColor.shared.customer, size: 25.0) + } + } + let enabled = NCShareCommon().isEditingEnabled(isDirectory: metadata.directory, fileExtension: metadata.fileExtension, shareType: shareType) || checkIsCollaboraFile() + row.cellConfig["titleLabel.textColor"] = enabled ? NCBrandColor.shared.label : NCBrandColor.shared.systemGray + row.disabled = !enabled + section.addFormRow(row) + + if !enabled { + row = XLFormRowDescriptor(tag: "kNMCFilePermissionCellEditingMsg", rowType: "kNMCFilePermissionCell", title: NSLocalizedString("_PERMISSIONS_", comment: "")) + row.cellConfig["titleLabel.text"] = NSLocalizedString("share_editing_message", comment: "") + row.cellConfig["titleLabel.textColor"] = NCBrandColor.shared.gray60 + row.height = 80 + section.addFormRow(row) + } + + //file drop + if isFileDropOptionVisible() { + XLFormViewController.cellClassesForRowDescriptorTypes()["kNMCFilePermissionCell"] = NCFilePermissionCell.self + row = XLFormRowDescriptor(tag: "NCFilePermissionCellFileDrop", rowType: "kNMCFilePermissionCell", title: NSLocalizedString("_PERMISSIONS_", comment: "")) + row.cellConfig["titleLabel.text"] = NSLocalizedString("_share_file_drop_", comment: "") + if self.permission == NCGlobal.shared.permissionCreateShare { + row.cellConfig["imageCheck.image"] = UIImage(named: "success")!.image(color: NCBrandColor.shared.customer, size: 25.0) + } + row.height = 44 + section.addFormRow(row) + + //sammelbox message + XLFormViewController.cellClassesForRowDescriptorTypes()["kNMCFilePermissionCell"] = NCFilePermissionCell.self + + row = XLFormRowDescriptor(tag: "kNMCFilePermissionCellFiledropMessage", rowType: "kNMCFilePermissionCell", title: NSLocalizedString("_PERMISSIONS_", comment: "")) + row.cellConfig["titleLabel.text"] = NSLocalizedString("_file_drop_message_", comment: "") + row.cellConfig["titleLabel.textColor"] = NCBrandColor.shared.gray60 + row.cellConfig["imageCheck.image"] = UIImage() + row.height = 84 + section.addFormRow(row) + } + + //empty cell + XLFormViewController.cellClassesForRowDescriptorTypes()["kNMCXLFormBaseCell"] = NCSeparatorCell.self + row = XLFormRowDescriptor(tag: "kNMCXLFormBaseCell", rowType: "kNMCXLFormBaseCell", title: NSLocalizedString("", comment: "")) + row.height = 16 + section.addFormRow(row) + + //ADVANCE PERMISSION + XLFormViewController.cellClassesForRowDescriptorTypes()["kNMCFilePermissionCell"] = NCFilePermissionCell.self + + row = XLFormRowDescriptor(tag: "NCFilePermissionCellAdvanceTxt", rowType: "kNMCFilePermissionCell", title: NSLocalizedString("_PERMISSIONS_", comment: "")) + row.cellConfig["titleLabel.text"] = NSLocalizedString("_advance_permissions_", comment: "") + row.height = 52 + section.addFormRow(row) + + if isLinkShare() { + //link label section header + + // Custom Link label + XLFormViewController.cellClassesForRowDescriptorTypes()["kNCShareTextInputCell"] = NCShareTextInputCell.self + row = XLFormRowDescriptor(tag: "kNCShareTextInputCellCustomLinkField", rowType: "kNCShareTextInputCell", title: "") + row.cellConfig["cellTextField.placeholder"] = NSLocalizedString("_custom_link_label", comment: "") + row.cellConfig["cellTextField.text"] = oldTableShare?.label + row.cellConfig["cellTextField.textAlignment"] = NSTextAlignment.left.rawValue + row.cellConfig["cellTextField.font"] = UIFont.systemFont(ofSize: 15.0) + row.cellConfig["cellTextField.textColor"] = NCBrandColor.shared.label + row.height = 44 + section.addFormRow(row) + } + + //can reshare + if isCanReshareOptionVisible() { + XLFormViewController.cellClassesForRowDescriptorTypes()["kNMCFilePermissionEditCell"] = NCFilePermissionEditCell.self + + row = XLFormRowDescriptor(tag: "kNMCFilePermissionEditCellEditingCanShare", rowType: "kNMCFilePermissionEditCell", title: "") + row.cellConfig["switchControl.onTintColor"] = NCBrandColor.shared.customer + row.cellClass = NCFilePermissionEditCell.self + row.cellConfig["titleLabel.text"] = NSLocalizedString("_share_can_reshare_", comment: "") + row.height = 44 + section.addFormRow(row) + } + + //hide download + if isHideDownloadOptionVisible() { + + XLFormViewController.cellClassesForRowDescriptorTypes()["kNMCFilePermissionEditCell"] = NCFilePermissionEditCell.self + row = XLFormRowDescriptor(tag: "kNMCFilePermissionEditCellHideDownload", rowType: "kNMCFilePermissionEditCell", title: NSLocalizedString("_PERMISSIONS_", comment: "")) + row.cellConfig["titleLabel.text"] = NSLocalizedString("_share_hide_download_", comment: "") + row.cellConfig["switchControl.onTintColor"] = NCBrandColor.shared.customer + row.cellClass = NCFilePermissionEditCell.self + row.height = 44 + section.addFormRow(row) + } + + //password + if isPasswordOptionsVisible() { + + // Set password + XLFormViewController.cellClassesForRowDescriptorTypes()["kNMCFilePermissionEditCell"] = NCFilePermissionEditCell.self + row = XLFormRowDescriptor(tag: "kNMCFilePermissionEditPasswordCellWithText", rowType: "kNMCFilePermissionEditCell", title: NSLocalizedString("_PERMISSIONS_", comment: "")) + row.cellConfig["titleLabel.text"] = NSLocalizedString("_set_password_", comment: "") + row.cellConfig["switchControl.onTintColor"] = NCBrandColor.shared.customer + row.cellClass = NCFilePermissionEditCell.self + row.height = 44 + section.addFormRow(row) + + // enter password input field + XLFormViewController.cellClassesForRowDescriptorTypes()["NMCSetPasswordCustomInputField"] = PasswordInputField.self + row = XLFormRowDescriptor(tag: "SetPasswordInputField", rowType: "NMCSetPasswordCustomInputField", title: NSLocalizedString("_filename_", comment: "")) + row.cellClass = PasswordInputField.self + row.cellConfig["fileNameInputTextField.placeholder"] = NSLocalizedString("_password_", comment: "") + row.cellConfig["fileNameInputTextField.textAlignment"] = NSTextAlignment.left.rawValue + row.cellConfig["fileNameInputTextField.font"] = UIFont.systemFont(ofSize: 15.0) + row.cellConfig["fileNameInputTextField.textColor"] = NCBrandColor.shared.label + row.cellConfig["backgroundColor"] = NCBrandColor.shared.secondarySystemGroupedBackground + row.height = 44 + let hasPassword = oldTableShare?.password != nil && !oldTableShare!.password.isEmpty + row.hidden = NSNumber.init(booleanLiteral: !hasPassword) + section.addFormRow(row) + } + + //expiration + + // expiry date switch + XLFormViewController.cellClassesForRowDescriptorTypes()["kNMCFilePermissionEditCell"] = NCFilePermissionEditCell.self + row = XLFormRowDescriptor(tag: "kNMCFilePermissionEditCellExpiration", rowType: "kNMCFilePermissionEditCell", title: NSLocalizedString("_share_expiration_date_", comment: "")) + row.cellConfig["titleLabel.text"] = NSLocalizedString("_share_expiration_date_", comment: "") + row.cellConfig["switchControl.onTintColor"] = NCBrandColor.shared.customer + row.cellClass = NCFilePermissionEditCell.self + row.height = 44 + section.addFormRow(row) + + // set expiry date field + XLFormViewController.cellClassesForRowDescriptorTypes()["kNCShareTextInputCell"] = NCShareTextInputCell.self + row = XLFormRowDescriptor(tag: "NCShareTextInputCellExpiry", rowType: "kNCShareTextInputCell", title: "") + row.cellClass = NCShareTextInputCell.self + row.cellConfig["cellTextField.placeholder"] = NSLocalizedString("_share_expiration_date_placeholder_", comment: "") + if !isNewShare { + if let date = oldTableShare?.expirationDate { + row.cellConfig["cellTextField.text"] = DateFormatter.shareExpDate.string(from: date as Date) + } + } + row.cellConfig["cellTextField.textAlignment"] = NSTextAlignment.left.rawValue + row.cellConfig["cellTextField.font"] = UIFont.systemFont(ofSize: 15.0) + row.cellConfig["cellTextField.textColor"] = NCBrandColor.shared.label + if let date = oldTableShare?.expirationDate { + row.cellConfig["cellTextField.text"] = DateFormatter.shareExpDate.string(from: date as Date) + } + row.height = 44 + let hasExpiry = oldTableShare?.expirationDate != nil + row.hidden = NSNumber.init(booleanLiteral: !hasExpiry) + section.addFormRow(row) + + if isDownloadLimitVisible() { + // DownloadLimit switch + XLFormViewController.cellClassesForRowDescriptorTypes()["kNMCFilePermissionEditCell"] = NCFilePermissionEditCell.self + row = XLFormRowDescriptor(tag: "kNMCFilePermissionEditCellDownloadLimit", rowType: "kNMCFilePermissionEditCell", title: NSLocalizedString("_share_download_limit_", comment: "")) + row.cellConfig["titleLabel.text"] = NSLocalizedString("_share_download_limit_", comment: "") + row.cellConfig["switchControl.onTintColor"] = NCBrandColor.shared.customer + row.cellClass = NCFilePermissionEditCell.self + row.height = 44 + section.addFormRow(row) + + // set Download Limit field + XLFormViewController.cellClassesForRowDescriptorTypes()["kNCShareTextInputCell"] = NCShareTextInputCell.self + row = XLFormRowDescriptor(tag: "NCShareTextInputCellDownloadLimit", rowType: "kNCShareTextInputCell", title: "") + row.cellClass = NCShareTextInputCell.self + row.cellConfig["cellTextField.placeholder"] = NSLocalizedString("_share_download_limit_placeholder_", comment: "") + row.cellConfig["cellTextField.textAlignment"] = NSTextAlignment.left.rawValue + row.cellConfig["cellTextField.font"] = UIFont.systemFont(ofSize: 15.0) + row.cellConfig["cellTextField.textColor"] = NCBrandColor.shared.label + row.height = 44 + let downloadLimitSet = downloadLimit?.limit != nil + row.hidden = NSNumber.init(booleanLiteral: !downloadLimitSet) + if let value = downloadLimit?.limit { + row.cellConfig["cellTextField.text"] = "\(value)" + } + section.addFormRow(row) + + XLFormViewController.cellClassesForRowDescriptorTypes()["kNMCFilePermissionCell"] = NCFilePermissionCell.self + row = XLFormRowDescriptor(tag: "kNMCDownloadLimitCell", rowType: "kNMCFilePermissionCell", title: "") + row.cellClass = NCFilePermissionCell.self + row.height = 44 + if downloadLimit?.limit != nil { + row.cellConfig["titleLabel.text"] = NSLocalizedString("_share_remaining_download_", comment: "") + " \(downloadLimit?.count ?? 0)" + } + row.cellConfig["titleLabel.textColor"] = NCBrandColor.shared.systemGray + row.disabled = true + row.hidden = NSNumber.init(booleanLiteral: !downloadLimitSet) + section.addFormRow(row) + } + + form.addFormSection(section) + self.form = form } + + func reloadForm() { + self.form.delegate = nil + self.tableView.reloadData() + self.form.delegate = self + } + + func updateDownloadLimitUI() { + if let value = downloadLimit?.limit { + if let downloadLimitSwitchField: XLFormRowDescriptor = self.form.formRow(withTag: "kNMCFilePermissionEditCellDownloadLimit") { + if let indexPath = self.form.indexPath(ofFormRow: downloadLimitSwitchField) { + let cell = tableView.cellForRow(at: indexPath) as? NCFilePermissionEditCell + cell?.switchControl.isOn = true + } + + if let downloadLimitInputField: XLFormRowDescriptor = self.form.formRow(withTag: "NCShareTextInputCellDownloadLimit") { + downloadLimitInputField.hidden = false + if let indexPath = self.form.indexPath(ofFormRow: downloadLimitInputField) { + let cell = tableView.cellForRow(at: indexPath) as? NCShareTextInputCell + cell?.cellTextField.text = "\(value)" + } + } + + if let downloadLimitInputField: XLFormRowDescriptor = self.form.formRow(withTag: "kNMCDownloadLimitCell") { + downloadLimitInputField.hidden = false + if let indexPath = self.form.indexPath(ofFormRow: downloadLimitInputField) { + let cell = tableView.cellForRow(at: indexPath) as? NCFilePermissionCell + cell?.titleLabel.text = NSLocalizedString("_share_remaining_download_", comment: "") + " \(downloadLimit?.count ?? 0)" + } + } + } + } + } + + func getDownloadLimitSwitchCell() -> NCFilePermissionEditCell? { + if let downloadLimitSwitchField: XLFormRowDescriptor = self.form.formRow(withTag: "kNMCFilePermissionEditCellDownloadLimit") { + if let indexPath = self.form.indexPath(ofFormRow: downloadLimitSwitchField) { + let cell = tableView.cellForRow(at: indexPath) as? NCFilePermissionEditCell + return cell + } + } + return nil + } + + func getDownloadLimitInputCell() -> NCShareTextInputCell? { + if let downloadLimitInputField: XLFormRowDescriptor = self.form.formRow(withTag: "NCShareTextInputCellDownloadLimit") { + if let indexPath = self.form.indexPath(ofFormRow: downloadLimitInputField) { + let cell = tableView.cellForRow(at: indexPath) as? NCShareTextInputCell + return cell + } + } + return nil + } + + // MARK: - Row Descriptor Value Changed + + override func didSelectFormRow(_ formRow: XLFormRowDescriptor!) { + guard let metadata = self.metadata else { return } + + switch formRow.tag { + case "NCFilePermissionCellRead": + + let value = CCUtility.getPermissionsValue(byCanEdit: false, andCanCreate: false, andCanChange: false, andCanDelete: false, andCanShare: canReshareTheShare(), andIsFolder: metadata.directory) + self.permission = value +// self.permissions = "RDNVCK" + metadata.permissions = "RDNVCK" + if let row : XLFormRowDescriptor = self.form.formRow(withTag: "NCFilePermissionCellRead") { + row.cellConfig["imageCheck.image"] = UIImage(named: "success")!.image(color: NCBrandColor.shared.customer, size: 25.0) + if let row1 : XLFormRowDescriptor = self.form.formRow(withTag: "kNMCFilePermissionCellEditing") { + row1.cellConfig["imageCheck.image"] = UIImage(named: "success")!.image(color: .clear, size: 25.0) + } + if let row2 : XLFormRowDescriptor = self.form.formRow(withTag: "NCFilePermissionCellFileDrop") { + row2.cellConfig["imageCheck.image"] = UIImage(named: "success")!.image(color: .clear, size: 25.0) + } + } - override func numberOfSections(in tableView: UITableView) -> Int { - return 2 + self.reloadForm() + break + case "kNMCFilePermissionCellEditing": + let value = CCUtility.getPermissionsValue(byCanEdit: true, andCanCreate: true, andCanChange: true, andCanDelete: true, andCanShare: canReshareTheShare(), andIsFolder: metadata.directory) + self.permission = value +// self.permissions = "RGDNV" + metadata.permissions = "RGDNV" + if let row : XLFormRowDescriptor = self.form.formRow(withTag: "NCFilePermissionCellRead") { + row.cellConfig["imageCheck.image"] = UIImage(named: "success")!.image(color: .clear, size: 25.0) + } + if let row1 : XLFormRowDescriptor = self.form.formRow(withTag: "kNMCFilePermissionCellEditing") { + row1.cellConfig["imageCheck.image"] = UIImage(named: "success")!.image(color: NCBrandColor.shared.customer, size: 25.0) + } + if let row2 : XLFormRowDescriptor = self.form.formRow(withTag: "NCFilePermissionCellFileDrop") { + row2.cellConfig["imageCheck.image"] = UIImage(named: "success")!.image(color: .clear, size: 25.0) + } + self.reloadForm() + break + case "NCFilePermissionCellFileDrop": + self.permission = NCGlobal.shared.permissionCreateShare +// self.permissions = "RGDNVCK" + metadata.permissions = "RGDNVCK" + if let row : XLFormRowDescriptor = self.form.formRow(withTag: "NCFilePermissionCellRead") { + row.cellConfig["imageCheck.image"] = UIImage(named: "success")!.image(color: .clear, size: 25.0) + } + if let row1 : XLFormRowDescriptor = self.form.formRow(withTag: "kNMCFilePermissionCellEditing") { + row1.cellConfig["imageCheck.image"] = UIImage(named: "success")!.image(color: .clear, size: 25.0) + } + if let row2 : XLFormRowDescriptor = self.form.formRow(withTag: "NCFilePermissionCellFileDrop") { + row2.cellConfig["imageCheck.image"] = UIImage(named: "success")!.image(color: NCBrandColor.shared.customer, size: 25.0) + } + self.reloadForm() + break + default: + break + } } - override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if section == 0 { - // check reshare permission, if restricted add note - let maxPermission = metadata.directory ? NCPermissions().permissionMaxFolderShare : NCPermissions().permissionMaxFileShare - return shareConfig.resharePermission != maxPermission ? shareConfig.permissions.count + 1 : shareConfig.permissions.count - } else if section == 1 { - return shareConfig.advanced.count - } else { return 0 } + func canReshareTheShare() -> Bool { + if let permissionValue = self.permission { + let canReshare = CCUtility.isPermission(toCanShare: permissionValue) + return canReshare + } else { + return false + } } - override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - guard let cell = shareConfig.cellFor(indexPath: indexPath) else { - let noteCell = UITableViewCell(style: .subtitle, reuseIdentifier: "noteCell") - noteCell.detailTextLabel?.text = NSLocalizedString("_share_reshare_restricted_", comment: "") - noteCell.detailTextLabel?.isEnabled = false - noteCell.isUserInteractionEnabled = false - noteCell.detailTextLabel?.numberOfLines = 0 - return noteCell + override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { + if let advancePermissionHeaderRow: XLFormRowDescriptor = self.form.formRow(withTag: "NCFilePermissionCellAdvanceTxt") { + if let advancePermissionHeaderRowIndexPath = form.indexPath(ofFormRow: advancePermissionHeaderRow), indexPath == advancePermissionHeaderRowIndexPath { + let cell = cell as? NCFilePermissionCell + cell?.seperatorBelowFull.isHidden = isLinkShare() + } + } + + //can Reshare + if let canReshareRow: XLFormRowDescriptor = self.form.formRow(withTag: "kNMCFilePermissionEditCellEditingCanShare") { + if let canReShareRowIndexPath = form.indexPath(ofFormRow: canReshareRow), indexPath == canReShareRowIndexPath { + let cell = cell as? NCFilePermissionEditCell + // Can reshare (file) + if let permissionValue = self.permission { + let canReshare = CCUtility.isPermission(toCanShare: permissionValue) + cell?.switchControl.isOn = canReshare + } else { + //new share + cell?.switchControl.isOn = false + } + } + } + //hide download + if let hideDownloadRow: XLFormRowDescriptor = self.form.formRow(withTag: "kNMCFilePermissionEditCellHideDownload"){ + if let hideDownloadRowIndexPath = form.indexPath(ofFormRow: hideDownloadRow), indexPath == hideDownloadRowIndexPath { + let cell = cell as? NCFilePermissionEditCell + cell?.switchControl.isOn = oldTableShare?.hideDownload ?? false + cell?.titleLabel.isEnabled = !(self.permission == NCGlobal.shared.permissionCreateShare) + cell?.switchControl.isEnabled = !(self.permission == NCGlobal.shared.permissionCreateShare) + cell?.isUserInteractionEnabled = !(self.permission == NCGlobal.shared.permissionCreateShare) + } + + // set password + if let setPassword : XLFormRowDescriptor = self.form.formRow(withTag: "kNMCFilePermissionEditPasswordCellWithText") { + if let setPasswordIndexPath = self.form.indexPath(ofFormRow: setPassword), indexPath == setPasswordIndexPath { + let passwordCell = cell as? NCFilePermissionEditCell + if let password = oldTableShare?.password { + passwordCell?.switchControl.isOn = !password.isEmpty + } else { + passwordCell?.switchControl.isOn = false + } + } + } + } + + //updateExpiryDateSwitch + if let expiryRow : XLFormRowDescriptor = self.form.formRow(withTag: "kNMCFilePermissionEditCellExpiration") { + if let expiryIndexPath = self.form.indexPath(ofFormRow: expiryRow), indexPath == expiryIndexPath { + let cell = cell as? NCFilePermissionEditCell + if oldTableShare?.expirationDate != nil { + cell?.switchControl.isOn = true + } else { + //new share + cell?.switchControl.isOn = false + } + } + } + + //SetDownloadLimitSwitch + if let limitRow : XLFormRowDescriptor = self.form.formRow(withTag: "kNMCFilePermissionEditCellDownloadLimit") { + if let expiryIndexPath = self.form.indexPath(ofFormRow: limitRow), indexPath == expiryIndexPath { + let cell = cell as? NCFilePermissionEditCell + cell?.switchControl.isOn = downloadLimit?.limit != nil + } + } + + //SetDownloadLimitSwitch + if let downloadlimitFieldRow : XLFormRowDescriptor = self.form.formRow(withTag: "NCShareTextInputCellDownloadLimit") { + if let downloadlimitIndexPath = self.form.indexPath(ofFormRow: downloadlimitFieldRow), indexPath == downloadlimitIndexPath { + let cell = cell as? NCShareTextInputCell + cell?.cellTextField.text = "\(downloadLimit?.limit ?? 0)" + } + } + + //SetDownloadLimitSwitch + if downloadLimit?.count != nil { + if let downloadlimitFieldRow : XLFormRowDescriptor = self.form.formRow(withTag: "kNMCDownloadLimitCell") { + if let downloadlimitIndexPath = self.form.indexPath(ofFormRow: downloadlimitFieldRow), indexPath == downloadlimitIndexPath { + let cell = cell as? NCFilePermissionCell + cell?.titleLabel.text = NSLocalizedString("_share_remaining_download_", comment: "") + " \(downloadLimit?.count ?? 0)" + cell?.seperatorBelowFull.isHidden = true + cell?.seperatorBelow.isHidden = true + } + } } - if let cell = cell as? NCShareDateCell { cell.onReload = tableView.reloadData } - return cell } - override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - tableView.deselectRow(at: indexPath, animated: true) - guard let cellConfig = shareConfig.config(for: indexPath) else { return } - guard let cellConfig = cellConfig as? NCShareDetails else { - cellConfig.didSelect(for: share) - tableView.reloadData() + override func formRowDescriptorValueHasChanged(_ formRow: XLFormRowDescriptor!, oldValue: Any!, newValue: Any!) { + super.formRowDescriptorValueHasChanged(formRow, oldValue: oldValue, newValue: newValue) + + switch formRow.tag { + + case "kNMCFilePermissionEditCellEditingCanShare": + if let value = newValue as? Bool { + canReshareValueChanged(isOn: value) + } + + case "kNMCFilePermissionEditCellHideDownload": + if let value = newValue as? Bool { + share.hideDownload = value + } + + case "kNMCFilePermissionEditPasswordCellWithText": + if let value = newValue as? Bool { + if let setPasswordInputField : XLFormRowDescriptor = self.form.formRow(withTag: "SetPasswordInputField") { + if let indexPath = self.form.indexPath(ofFormRow: setPasswordInputField) { + let cell = tableView.cellForRow(at: indexPath) as? PasswordInputField + cell?.fileNameInputTextField.text = "" + } + share.password = "" + setPasswordInputField.hidden = !value + } + } + + case "kNCShareTextInputCellCustomLinkField": + if let label = formRow.value as? String { + self.form.delegate = nil + share.label = label + self.form.delegate = self + } + + case "SetPasswordInputField": + if let pwd = formRow.value as? String { + self.form.delegate = nil + share.password = pwd + self.form.delegate = self + } + + case "kNMCFilePermissionEditCellLinkLabel": + if let label = formRow.value as? String { + self.form.delegate = nil + share.label = label + self.form.delegate = self + } + + case "kNMCFilePermissionEditCellExpiration": + if let value = newValue as? Bool { + if let inputField : XLFormRowDescriptor = self.form.formRow(withTag: "NCShareTextInputCellExpiry") { + inputField.hidden = !value + } + } + + case "kNMCFilePermissionEditCellDownloadLimit": + if let value = newValue as? Bool { + self.downloadLimit = DownloadLimit() + self.downloadLimit?.limit = value ? 0 : nil + if let inputField : XLFormRowDescriptor = self.form.formRow(withTag: "NCShareTextInputCellDownloadLimit") { + inputField.hidden = !value + if let indexPath = self.form.indexPath(ofFormRow: inputField) { + let cell = tableView.cellForRow(at: indexPath) as? NCShareTextInputCell + cell?.cellTextField.text = "" + } + } + + if let inputField : XLFormRowDescriptor = self.form.formRow(withTag: "kNMCDownloadLimitCell") { + inputField.hidden = !value + if let indexPath = self.form.indexPath(ofFormRow: inputField) { + let cell = tableView.cellForRow(at: indexPath) as? NCFilePermissionCell + cell?.seperatorBelowFull.isHidden = true + cell?.seperatorBelow.isHidden = true + cell?.titleLabel.text = "" + } + } + } + + case "NCShareTextInputCellExpiry": + if let exp = formRow.value as? Date { + self.form.delegate = nil + self.share.expirationDate = exp as NSDate + self.form.delegate = self + } + + default: + break + } + } + //Check file type is collabora + func checkIsCollaboraFile() -> Bool { + guard let metadata = metadata else { + return false + } + + // EDITORS + let editors = NCUtility().isDirectEditing(account: metadata.account, contentType: metadata.contentType) + let availableRichDocument = NCUtility().isRichDocument(metadata) + + // RichDocument: Collabora + return (availableRichDocument && editors.count == 0) + } + + func isFileDropOptionVisible() -> Bool { + return (metadata.directory && (isLinkShare() || isExternalUserShare())) + } + + func isLinkShare() -> Bool { + return NCShareCommon().isLinkShare(shareType: shareType) + } + + func isExternalUserShare() -> Bool { + return NCShareCommon().isExternalUserShare(shareType: shareType) + } + + func isInternalUser() -> Bool { + return NCShareCommon().isInternalUser(shareType: shareType) + } + + func isCanReshareOptionVisible() -> Bool { + return isInternalUser() + } + + func isHideDownloadOptionVisible() -> Bool { + return !isInternalUser() + } + + func isPasswordOptionsVisible() -> Bool { + return !isInternalUser() + } + + func isDownloadLimitVisible() -> Bool { + return isLinkShare() && !(metadata.directory) + } + + func canReshareValueChanged(isOn: Bool) { + + guard let oldTableShare = oldTableShare, let permission = self.permission else { + self.permission = isOn ? (self.permission ?? 0) + NCGlobal.shared.permissionShareShare : ((self.permission ?? 0) - NCGlobal.shared.permissionShareShare) return } - switch cellConfig { - case .limitDownload: - let storyboard = UIStoryboard(name: "NCShare", bundle: nil) - guard let viewController = storyboard.instantiateViewController(withIdentifier: "NCShareDownloadLimit") as? NCShareDownloadLimitViewController else { return } - viewController.downloadLimit = self.downloadLimit - viewController.metadata = self.metadata - viewController.share = self.share - viewController.shareDownloadLimitTableViewControllerDelegate = self - viewController.onDismiss = tableView.reloadData - self.navigationController?.pushViewController(viewController, animated: true) - case .hideDownload: - share.hideDownload.toggle() - tableView.reloadData() - case .expirationDate: - let cell = tableView.cellForRow(at: indexPath) as? NCShareDateCell - cell?.textField.becomeFirstResponder() - cell?.checkMaximumDate(account: metadata.account) - case .password: - guard share.password.isEmpty else { - share.password = "" - tableView.reloadData() - return - } - let alertController = UIAlertController.password(titleKey: "_share_password_") { password in - self.share.password = password ?? "" - tableView.reloadData() - } - self.present(alertController, animated: true) - case .note: - let storyboard = UIStoryboard(name: "NCShare", bundle: nil) - guard let viewNewUserComment = storyboard.instantiateViewController(withIdentifier: "NCShareNewUserAddComment") as? NCShareNewUserAddComment else { return } - viewNewUserComment.metadata = self.metadata - viewNewUserComment.share = self.share - viewNewUserComment.onDismiss = tableView.reloadData - self.navigationController?.pushViewController(viewNewUserComment, animated: true) - case .label: - let alertController = UIAlertController.withTextField(titleKey: "_share_link_name_") { textField in - textField.placeholder = cellConfig.title - textField.text = self.share.label - } completion: { newValue in - self.share.label = newValue ?? "" - self.setNavigationTitle() - tableView.reloadData() - } - self.present(alertController, animated: true) + let canEdit = CCUtility.isAnyPermission(toEdit: permission) + let canCreate = CCUtility.isPermission(toCanCreate: permission) + let canChange = CCUtility.isPermission(toCanChange: permission) + let canDelete = CCUtility.isPermission(toCanDelete: permission) + + if metadata.directory { + self.permission = CCUtility.getPermissionsValue(byCanEdit: canEdit, andCanCreate: canCreate, andCanChange: canChange, andCanDelete: canDelete, andCanShare: isOn, andIsFolder: metadata.directory) + } else { + if isOn { + if canEdit { + self.permission = CCUtility.getPermissionsValue(byCanEdit: true, andCanCreate: true, andCanChange: true, andCanDelete: true, andCanShare: isOn, andIsFolder: metadata.directory) + } else { + self.permission = CCUtility.getPermissionsValue(byCanEdit: false, andCanCreate: false, andCanChange: false, andCanDelete: false, andCanShare: isOn, andIsFolder: metadata.directory) + } + } else { + if canEdit { + self.permission = CCUtility.getPermissionsValue(byCanEdit: true, andCanCreate: true, andCanChange: true, andCanDelete: true, andCanShare: isOn, andIsFolder: metadata.directory) + } else { + self.permission = CCUtility.getPermissionsValue(byCanEdit: false, andCanCreate: false, andCanChange: false, andCanDelete: false, andCanShare: isOn, andIsFolder: metadata.directory) + } + } } } + + func getDownloadLimit() { + NCActivityIndicator.shared.start(backgroundView: view) + NMCCommunication.shared.getDownloadLimit(token: oldTableShare?.token ?? "") { [weak self] (downloadLimit: DownloadLimit?, error: String) in + DispatchQueue.main.async { + NCActivityIndicator.shared.stop() + if let downloadLimit = downloadLimit { + self?.downloadLimit = downloadLimit + } + self?.updateDownloadLimitUI() + } + } + } + + func setDownloadLimit(deleteLimit: Bool, limit: String) { + NMCCommunication.shared.setDownloadLimit(deleteLimit: deleteLimit, limit: limit, token: oldTableShare?.token ?? "") { (success, errorMessage) in + print(success) + } + } + + func showDownloadLimitError(message: String) { + let alertController = UIAlertController(title: "", message: message, preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { action in })) + self.present(alertController, animated: true) + } } // MARK: - NCShareDownloadLimitTableViewControllerDelegate diff --git a/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.swift b/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.swift index 1cd9c88dff..64d8f6d9eb 100644 --- a/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.swift +++ b/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.swift @@ -35,23 +35,24 @@ class NCShareAdvancePermissionFooter: UIView { func setupUI(delegate: NCShareAdvanceFotterDelegate?, account: String) { self.delegate = delegate - backgroundColor = .clear - + buttonCancel.addTarget(self, action: #selector(cancelClicked), for: .touchUpInside) + buttonNext.addTarget(self, action: #selector(nextClicked), for: .touchUpInside) buttonCancel.setTitle(NSLocalizedString("_cancel_", comment: ""), for: .normal) - buttonCancel.layer.cornerRadius = 25 + buttonNext.setTitle(NSLocalizedString(delegate?.isNewShare == true ? "_next_" : "_apply_changes_", comment: ""), for: .normal) + buttonCancel.layer.cornerRadius = 10 buttonCancel.layer.masksToBounds = true buttonCancel.layer.borderWidth = 1 - buttonCancel.layer.borderColor = NCBrandColor.shared.textColor2.cgColor - buttonCancel.backgroundColor = .secondarySystemBackground - buttonCancel.addTarget(self, action: #selector(cancelClicked), for: .touchUpInside) - buttonCancel.setTitleColor(NCBrandColor.shared.textColor2, for: .normal) - - buttonNext.setTitle(NSLocalizedString(delegate?.isNewShare == true ? "_share_" : "_save_", comment: ""), for: .normal) - buttonNext.layer.cornerRadius = 25 - buttonNext.layer.masksToBounds = true - buttonNext.backgroundColor = NCBrandColor.shared.getElement(account: account) - buttonNext.addTarget(self, action: #selector(nextClicked), for: .touchUpInside) + addShadow(location: .top) + layer.cornerRadius = 10 + layer.masksToBounds = true + backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + buttonCancel.setTitleColor(NCBrandColor.shared.label, for: .normal) + buttonCancel.layer.borderColor = NCBrandColor.shared.label.cgColor + buttonCancel.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + buttonNext.setBackgroundColor(NCBrandColor.shared.customer, for: .normal) buttonNext.setTitleColor(.white, for: .normal) + buttonNext.layer.cornerRadius = 10 + buttonNext.layer.masksToBounds = true } @objc func cancelClicked() { diff --git a/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.xib b/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.xib index b4ec72ed06..36b09589ef 100644 --- a/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.xib +++ b/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.xib @@ -1,67 +1,60 @@ - + - + - - - + + - + + - + - - - - - - - + - + - - - - - - - + + + - - + + - + - - - - - - - - diff --git a/iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.xib b/iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.xib new file mode 100644 index 0000000000..161dc96732 --- /dev/null +++ b/iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.xib @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOSClient/Share/Advanced/NCShareHeaderCustomCell.swift b/iOSClient/Share/Advanced/NCShareHeaderCustomCell.swift new file mode 100644 index 0000000000..cb5dae8c1f --- /dev/null +++ b/iOSClient/Share/Advanced/NCShareHeaderCustomCell.swift @@ -0,0 +1,30 @@ +// +// NCShareHeaderCustomCell.swift +// Nextcloud +// +// Created by T-systems on 11/08/21. +// Copyright © 2021 Marino Faggiana. All rights reserved. +// + +import UIKit + +class NCShareHeaderCustomCell: XLFormBaseCell { + + @IBOutlet weak var titleLabel: UILabel! + + override func awakeFromNib() { + super.awakeFromNib() + self.selectionStyle = .none + self.backgroundColor = .clear + } + + override func configure() { + super.configure() + } + + override func update() { + self.backgroundColor = .clear + self.titleLabel.textColor = NCBrandColor.shared.systemGray + super.update() + } +} diff --git a/iOSClient/Share/Advanced/NCShareHeaderCustomCell.xib b/iOSClient/Share/Advanced/NCShareHeaderCustomCell.xib new file mode 100644 index 0000000000..89ba3781e5 --- /dev/null +++ b/iOSClient/Share/Advanced/NCShareHeaderCustomCell.xib @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOSClient/Share/Advanced/NCShareNewUserAddComment.swift b/iOSClient/Share/Advanced/NCShareNewUserAddComment.swift index 0c6bb586ef..a7fe311e0c 100644 --- a/iOSClient/Share/Advanced/NCShareNewUserAddComment.swift +++ b/iOSClient/Share/Advanced/NCShareNewUserAddComment.swift @@ -1,9 +1,12 @@ // +// // NCShareNewUserAddComment.swift // Nextcloud // // Created by TSI-mc on 21/06/21. -// Copyright © 2022 All rights reserved. +// Copyright © 2022 Henrik Storch. All rights reserved. +// +// Author Henrik Storch // // 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 @@ -25,39 +28,60 @@ import NextcloudKit class NCShareNewUserAddComment: UIViewController, NCShareNavigationTitleSetting { @IBOutlet weak var headerContainerView: UIView! - @IBOutlet weak var sharingLabel: UILabel! - @IBOutlet weak var noteTextField: UITextView! - + @IBOutlet weak var labelSharing: UILabel! + @IBOutlet weak var labelNote: UILabel! + @IBOutlet weak var commentTextView: UITextView! + @IBOutlet weak var btnCancel: UIButton! + @IBOutlet weak var btnSendShare: UIButton! + @IBOutlet weak var buttonContainerView: UIView! let contentInsets: CGFloat = 16 - var onDismiss: (() -> Void)? - - public var share: Shareable! + public var share: NCTableShareable! public var metadata: tableMetadata! + var isNewShare: Bool { share is NCTableShareOptions } + var networking: NCShareNetworking? override func viewDidLoad() { super.viewDidLoad() self.setNavigationTitle() - - NotificationCenter.default.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillHideNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillChangeFrameNotification, object: nil) - - sharingLabel.text = NSLocalizedString("_share_note_recipient_", comment: "") - - noteTextField.textContainerInset = UIEdgeInsets(top: contentInsets, left: contentInsets, bottom: contentInsets, right: contentInsets) - noteTextField.text = share.note - let toolbar = UIToolbar.toolbar { - self.noteTextField.resignFirstResponder() - self.noteTextField.text = "" - self.share.note = "" - } onDone: { - self.noteTextField.resignFirstResponder() - self.share.note = self.noteTextField.text - self.navigationController?.popViewController(animated: true) + changeTheming() + setupHeader() + } + + @objc func changeTheming() { + self.view.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + self.commentTextView.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + commentTextView.textColor = NCBrandColor.shared.label + btnCancel.setTitleColor(NCBrandColor.shared.label, for: .normal) + btnCancel.layer.borderColor = NCBrandColor.shared.label.cgColor + btnCancel.backgroundColor = .clear + buttonContainerView.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + btnSendShare.setBackgroundColor(NCBrandColor.shared.customer, for: .normal) + btnSendShare.setTitleColor(.white, for: .normal) + commentTextView.layer.borderColor = NCBrandColor.shared.label.cgColor + commentTextView.layer.borderWidth = 1 + commentTextView.layer.cornerRadius = 4.0 + commentTextView.showsVerticalScrollIndicator = false + commentTextView.textContainerInset = UIEdgeInsets(top: contentInsets, left: contentInsets, bottom: contentInsets, right: contentInsets) + btnCancel.setTitle(NSLocalizedString("_cancel_", comment: ""), for: .normal) + btnCancel.layer.cornerRadius = 10 + btnCancel.layer.masksToBounds = true + btnCancel.layer.borderWidth = 1 + btnSendShare.setTitle(NSLocalizedString("_send_share_", comment: ""), for: .normal) + btnSendShare.layer.cornerRadius = 10 + btnSendShare.layer.masksToBounds = true + labelSharing.text = NSLocalizedString("_sharing_", comment: "") + labelNote.text = NSLocalizedString("_share_note_recipient_", comment: "") + commentTextView.inputAccessoryView = UIToolbar.doneToolbar { [weak self] in + self?.commentTextView.resignFirstResponder() } - - noteTextField.inputAccessoryView = toolbar.wrappedSafeAreaContainer - - guard let headerView = (Bundle.main.loadNibNamed("NCShareHeader", owner: self, options: nil)?.first as? NCShareHeader) else { return } + } + + func setupHeader(){ + guard let headerView = (Bundle.main.loadNibNamed("NCShareAdvancePermissionHeader", owner: self, options: nil)?.first as? NCShareAdvancePermissionHeader) else { return } + headerView.ocId = metadata.ocId headerContainerView.addSubview(headerView) headerView.frame = headerContainerView.frame headerView.translatesAutoresizingMaskIntoConstraints = false @@ -65,29 +89,48 @@ class NCShareNewUserAddComment: UIViewController, NCShareNavigationTitleSetting headerView.bottomAnchor.constraint(equalTo: headerContainerView.bottomAnchor).isActive = true headerView.leftAnchor.constraint(equalTo: headerContainerView.leftAnchor).isActive = true headerView.rightAnchor.constraint(equalTo: headerContainerView.rightAnchor).isActive = true - headerView.setupUI(with: metadata) } - override func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated) - share.note = noteTextField.text - onDismiss?() + @IBAction func cancelClicked(_ sender: Any) { + self.navigationController?.popToRootViewController(animated: true) + } + + @IBAction func sendShareClicked(_ sender: Any) { + share.note = commentTextView.text + if isNewShare { + networking?.createShare(option: share) + } else { + networking?.updateShare(option: share) + } + self.navigationController?.popToRootViewController(animated: true) } @objc func adjustForKeyboard(notification: Notification) { guard let keyboardValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue, - let globalTextViewFrame = noteTextField.superview?.convert(noteTextField.frame, to: nil) else { return } - + let globalTextViewFrame = commentTextView.superview?.convert(commentTextView.frame, to: nil) else { return } let keyboardScreenEndFrame = keyboardValue.cgRectValue let portionCovoredByLeyboard = globalTextViewFrame.maxY - keyboardScreenEndFrame.minY if notification.name == UIResponder.keyboardWillHideNotification || portionCovoredByLeyboard < 0 { - noteTextField.contentInset = .zero + commentTextView.contentInset = .zero } else { - noteTextField.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: portionCovoredByLeyboard, right: 0) + commentTextView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: portionCovoredByLeyboard, right: 0) } + commentTextView.scrollIndicatorInsets = commentTextView.contentInset + } - noteTextField.scrollIndicatorInsets = noteTextField.contentInset + @objc func keyboardWillShow(notification: Notification) { + if UIScreen.main.bounds.width <= 375 { + if view.frame.origin.y == 0 { + self.view.frame.origin.y -= 200 + } + } + } + + @objc func keyboardWillHide(notification: Notification) { + if view.frame.origin.y != 0 { + self.view.frame.origin.y = 0 + } } } diff --git a/iOSClient/Share/Advanced/NCShareTextInputCell.swift b/iOSClient/Share/Advanced/NCShareTextInputCell.swift new file mode 100644 index 0000000000..26da27ef03 --- /dev/null +++ b/iOSClient/Share/Advanced/NCShareTextInputCell.swift @@ -0,0 +1,151 @@ +// +// NCShareTextInputCell.swift +// Nextcloud +// +// Created by T-systems on 20/09/21. +// Copyright © 2021 Kunal. All rights reserved. +// + +import UIKit + +class NCShareTextInputCell: XLFormBaseCell, UITextFieldDelegate { + + @IBOutlet weak var seperator: UIView! + @IBOutlet weak var seperatorBottom: UIView! + @IBOutlet weak var cellTextField: UITextField! + @IBOutlet weak var calendarImageView: UIImageView! + + let datePicker = UIDatePicker() + var expirationDateText: String! + var expirationDate: NSDate! + + override func awakeFromNib() { + super.awakeFromNib() + self.cellTextField.delegate = self + self.cellTextField.isEnabled = true + calendarImageView.image = UIImage(named: "calender")?.imageColor(NCBrandColor.shared.brandElement) + self.selectionStyle = .none + self.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + self.cellTextField.attributedPlaceholder = NSAttributedString(string: "", + attributes: [NSAttributedString.Key.foregroundColor: NCBrandColor.shared.fileFolderName]) + self.cellTextField.textColor = NCBrandColor.shared.singleTitleColorButton + } + + override func configure() { + super.configure() + } + + override func update() { + super.update() + calendarImageView.isHidden = rowDescriptor.tag != "NCShareTextInputCellExpiry" + if rowDescriptor.tag == "NCShareTextInputCellExpiry" { + seperator.isHidden = true + setDatePicker(sender: self.cellTextField) + } else if rowDescriptor.tag == "NCShareTextInputCellDownloadLimit" { + seperator.isHidden = true + cellTextField.keyboardType = .numberPad + setDoneButton(sender: self.cellTextField) + } + } + + func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + if self.cellTextField == textField { + if let rowDescriptor = rowDescriptor, let text = self.cellTextField.text { + + if (text + " ").isEmpty == false { + rowDescriptor.value = self.cellTextField.text! + string + } else { + rowDescriptor.value = nil + } + } + } + + self.formViewController().textField(textField, shouldChangeCharactersIn: range, replacementString: string) + return true + } + + func textFieldDidEndEditing(_ textField: UITextField) { + rowDescriptor.value = cellTextField.text + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + self.formViewController()?.textFieldShouldReturn(textField) + return true + } + + func textFieldShouldClear(_ textField: UITextField) -> Bool { + self.formViewController()?.textFieldShouldClear(textField) + return true + } + + override class func formDescriptorCellHeight(for rowDescriptor: XLFormRowDescriptor!) -> CGFloat { + return 30 + } + + override func formDescriptorCellDidSelected(withForm controller: XLFormViewController!) { + self.selectionStyle = .none + } + + func setDatePicker(sender: UITextField) { + //Format Date + datePicker.datePickerMode = .date + datePicker.minimumDate = Date.tomorrow + if #available(iOS 13.4, *) { + datePicker.preferredDatePickerStyle = .wheels + datePicker.sizeToFit() + } + //ToolBar + let toolbar = UIToolbar(); + toolbar.sizeToFit() + let doneButton = UIBarButtonItem(title: NSLocalizedString("_done_", comment: ""), style: .plain, target: self, action: #selector(doneDatePicker)); + let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil) + let cancelButton = UIBarButtonItem(title: NSLocalizedString("_cancel_", comment: ""), style: .plain, target: self, action: #selector(cancelDatePicker)); + + toolbar.setItems([cancelButton, spaceButton, doneButton], animated: false) + + sender.inputAccessoryView = toolbar + sender.inputView = datePicker + } + + @objc func doneDatePicker() { + let dateFormatter = DateFormatter() + dateFormatter.formatterBehavior = .behavior10_4 + dateFormatter.dateStyle = .medium + dateFormatter.dateFormat = NCShareAdvancePermission.displayDateFormat + + var expiryDate = dateFormatter.string(from: datePicker.date) + expiryDate = expiryDate.replacingOccurrences(of: "..", with: ".") + self.expirationDateText = expiryDate + + self.expirationDate = datePicker.date as NSDate + self.cellTextField.text = self.expirationDateText + self.rowDescriptor.value = self.expirationDate + self.cellTextField.endEditing(true) + } + + @objc func cancelDatePicker() { + self.cellTextField.endEditing(true) + } + + func setDoneButton(sender: UITextField) { + //ToolBar + let toolbar = UIToolbar(); + toolbar.sizeToFit() + let doneButton = UIBarButtonItem(title: NSLocalizedString("_done_", comment: ""), style: .plain, target: self, action: #selector(cancelDatePicker)); + let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil) + toolbar.setItems([spaceButton, doneButton], animated: false) + sender.inputAccessoryView = toolbar + } +} + +class NCSeparatorCell: XLFormBaseCell { + override func awakeFromNib() { + super.awakeFromNib() + selectionStyle = .none + } + + override func update() { + super.update() + self.selectionStyle = .none + } +} diff --git a/iOSClient/Share/Advanced/NCShareTextInputCell.xib b/iOSClient/Share/Advanced/NCShareTextInputCell.xib new file mode 100644 index 0000000000..eaa2f0cd13 --- /dev/null +++ b/iOSClient/Share/Advanced/NCShareTextInputCell.xib @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOSClient/Share/NCSearchUserDropDownCell.xib b/iOSClient/Share/NCSearchUserDropDownCell.xib index 2ba38c8fa6..6c2ffde821 100755 --- a/iOSClient/Share/NCSearchUserDropDownCell.xib +++ b/iOSClient/Share/NCSearchUserDropDownCell.xib @@ -1,9 +1,9 @@ - + - + @@ -29,12 +29,12 @@ - + @@ -58,12 +58,12 @@ + - diff --git a/iOSClient/Share/NCShare+Helper.swift b/iOSClient/Share/NCShare+Helper.swift new file mode 100644 index 0000000000..b08bfa9358 --- /dev/null +++ b/iOSClient/Share/NCShare+Helper.swift @@ -0,0 +1,113 @@ +// +// NCShare+Helper.swift +// Nextcloud +// +// Created by Henrik Storch on 19.03.22. +// Copyright © 2022 Henrik Storch. All rights reserved. +// +// Author Henrik Storch +// +// 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 + +extension tableShare: NCTableShareable { } +extension NKShare: NCTableShareable { } + +protocol NCTableShareable: AnyObject { + var shareType: Int { get set } + var permissions: Int { get set } + var idShare: Int { get set } + var shareWith: String { get set } + var hideDownload: Bool { get set } + var password: String { get set } + var label: String { get set } + var note: String { get set } + var expirationDate: NSDate? { get set } + var shareWithDisplayname: String { get set } + var attributes: String? { get set } +} + +extension NCTableShareable { + var expDateString: String? { + guard let date = expirationDate else { return nil } + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "YYYY-MM-dd HH:mm:ss" + return dateFormatter.string(from: date as Date) + } + + func hasChanges(comparedTo other: NCTableShareable) -> Bool { + return other.shareType != shareType + || other.permissions != permissions + || other.hideDownload != hideDownload + || other.password != password + || other.label != label + || other.note != note + || other.expirationDate != expirationDate + } +} + +class NCTableShareOptions: NCTableShareable { + + var shareType: Int + var permissions: Int + + var idShare: Int = 0 + var shareWith: String = "" + + var hideDownload: Bool = false + var password: String = "" + var label: String = "" + var note: String = "" + var expirationDate: NSDate? + var shareWithDisplayname: String = "" + + var attributes: String? + + private init(shareType: Int, metadata: tableMetadata, password: String?) { + if metadata.e2eEncrypted, NCCapabilities.shared.getCapabilities(account: metadata.account).capabilityE2EEApiVersion == NCGlobal.shared.e2eeVersionV12 { + self.permissions = NCPermissions().permissionCreateShare + } else { + self.permissions = NCCapabilities.shared.getCapabilities(account: metadata.account).capabilityFileSharingDefaultPermission & metadata.sharePermissionsCollaborationServices + } + self.shareType = shareType + if let password = password { + self.password = password + } + } + + convenience init(sharee: NKSharee, metadata: tableMetadata, password: String?) { + self.init(shareType: sharee.shareType, metadata: metadata, password: password) + self.shareWith = sharee.shareWith + } + + static func shareLink(metadata: tableMetadata, password: String?) -> NCTableShareOptions { + return NCTableShareOptions(shareType: NCShareCommon().SHARE_TYPE_LINK, metadata: metadata, password: password) + } +} + +protocol NCShareDetail { + var share: NCTableShareable! { get } +} + +extension NCShareDetail where Self: UIViewController { + func setNavigationTitle() { + title = NSLocalizedString("_sharing_", comment: "") + if share.shareType != NCShareCommon().SHARE_TYPE_LINK { + title! = share.shareWithDisplayname.isEmpty ? share.shareWith : share.shareWithDisplayname + } + } +} diff --git a/iOSClient/Share/NCShare+NCCellDelegate.swift b/iOSClient/Share/NCShare+NCCellDelegate.swift index dd05de5484..412510ed5b 100644 --- a/iOSClient/Share/NCShare+NCCellDelegate.swift +++ b/iOSClient/Share/NCShare+NCCellDelegate.swift @@ -49,7 +49,7 @@ extension NCShare: NCShareLinkCellDelegate, NCShareUserCellDelegate { func tapMenu(with tableShare: tableShare?, sender: Any) { if let tableShare = tableShare { - self.toggleShareMenu(for: tableShare) + self.toggleShareMenu(for: tableShare, sendMail: (tableShare.shareType != NCShareCommon().SHARE_TYPE_LINK), folder: metadata?.directory ?? false, sender: sender) } else { self.makeNewLinkShare() } @@ -61,9 +61,8 @@ extension NCShare: NCShareLinkCellDelegate, NCShareUserCellDelegate { } func quickStatus(with tableShare: tableShare?, sender: Any) { - guard let tableShare, - let metadata, - tableShare.shareType != NCPermissions().permissionDefaultFileRemoteShareNoSupportShareOption else { return } + guard let tableShare = tableShare, + let metadata = metadata else { return } self.toggleUserPermissionMenu(isDirectory: metadata.directory, tableShare: tableShare) } } diff --git a/iOSClient/Share/NCShare.storyboard b/iOSClient/Share/NCShare.storyboard index 07fe9374b4..0c8a27be32 100644 --- a/iOSClient/Share/NCShare.storyboard +++ b/iOSClient/Share/NCShare.storyboard @@ -1,412 +1,262 @@ - + - - + - - - - - - - - - - - - - - - - - + - + - + - + - + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - + - + - + - - + + - - + + - - + + - - - + + + - + - - + + - - - + + + + - + - - - - + - - - - - - - - - - - + + + + + + + + + + + - - - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + - + - - - - - + + + + + + + + - + - - - + + + + + + + - + - - + + - - + + - - + + - - + + - - - - - - - - - - + - + + + + + + + - - + + - - - - + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + - - + + - - - - - - - - - - - - - - - - - - + + + + + + - + - - - - - - - - - - diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift index 0745a56025..d0ac699b42 100644 --- a/iOSClient/Share/NCShare.swift +++ b/iOSClient/Share/NCShare.swift @@ -30,17 +30,11 @@ import NextcloudKit import MarqueeLabel import ContactsUI -class NCShare: UIViewController, NCSharePagingContent { - @IBOutlet weak var viewContainerConstraint: NSLayoutConstraint! - @IBOutlet weak var sharedWithYouByView: UIView! - @IBOutlet weak var sharedWithYouByImage: UIImageView! - @IBOutlet weak var sharedWithYouByLabel: UILabel! - @IBOutlet weak var searchFieldTopConstraint: NSLayoutConstraint! - @IBOutlet weak var searchField: UISearchBar! - var textField: UIView? { searchField } +class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent { + + var textField: UITextField? { self.view.viewWithTag(Tag.searchField) as? UITextField } @IBOutlet weak var tableView: UITableView! - @IBOutlet weak var btnContact: UIButton! weak var appDelegate = UIApplication.shared.delegate as? AppDelegate @@ -53,6 +47,7 @@ class NCShare: UIViewController, NCSharePagingContent { let database = NCManageDatabase.shared var canReshare: Bool { + guard let metadata = metadata else { return true } return ((metadata.sharePermissionsCollaborationServices & NCPermissions().permissionShareShare) != 0) } @@ -70,38 +65,23 @@ class NCShare: UIViewController, NCSharePagingContent { override func viewDidLoad() { super.viewDidLoad() - view.backgroundColor = .systemBackground - - viewContainerConstraint.constant = height - searchFieldTopConstraint.constant = 0 - - searchField.placeholder = NSLocalizedString("_shareLinksearch_placeholder_", comment: "") - searchField.autocorrectionType = .no + view.backgroundColor = .secondarySystemGroupedBackground tableView.dataSource = self tableView.delegate = self tableView.allowsSelection = false - tableView.backgroundColor = .systemBackground - tableView.contentInset = UIEdgeInsets(top: 8, left: 0, bottom: 10, right: 0) + tableView.backgroundColor = .secondarySystemGroupedBackground tableView.register(UINib(nibName: "NCShareLinkCell", bundle: nil), forCellReuseIdentifier: "cellLink") tableView.register(UINib(nibName: "NCShareUserCell", bundle: nil), forCellReuseIdentifier: "cellUser") + tableView.register(UINib(nibName: "NCShareEmailFieldCell", bundle: nil), forCellReuseIdentifier: "NCShareEmailFieldCell") NotificationCenter.default.addObserver(self, selector: #selector(reloadData), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataNCShare), object: nil) - - if metadata.e2eEncrypted { - let direcrory = self.database.getTableDirectory(account: metadata.account, serverUrl: metadata.serverUrl) - let capabilities = NCCapabilities.shared.getCapabilities(account: metadata.account) - if capabilities.capabilityE2EEApiVersion == NCGlobal.shared.e2eeVersionV12 || - (capabilities.capabilityE2EEApiVersion == NCGlobal.shared.e2eeVersionV20 && direcrory?.e2eEncrypted ?? false) { - searchFieldTopConstraint.constant = -50 - searchField.alpha = 0 - btnContact.alpha = 0 - } - } else { - checkSharedWithYou() - } - + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(appWillEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil) + guard let metadata = metadata else { return } + reloadData() networking = NCShareNetworking(metadata: metadata, view: self.view, delegate: self, session: session) @@ -109,11 +89,19 @@ class NCShare: UIViewController, NCSharePagingContent { let isVisible = (self.navigationController?.topViewController as? NCSharePaging)?.page == .sharing networking?.readShare(showLoadingIndicator: isVisible) } - - searchField.searchTextField.font = .systemFont(ofSize: 14) - searchField.delegate = self + self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_cancel_", comment: ""), style: .done, target: self, action: #selector(exitTapped)) + navigationItem.largeTitleDisplayMode = .never + } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + tableView.reloadData() } + @objc func exitTapped() { + self.dismiss(animated: true, completion: nil) + } + func makeNewLinkShare() { guard let advancePermission = UIStoryboard(name: "NCShare", bundle: nil).instantiateViewController(withIdentifier: "NCShareAdvancePermission") as? NCShareAdvancePermission, @@ -126,56 +114,53 @@ class NCShare: UIViewController, NCSharePagingContent { } } - // Shared with you by ... - func checkSharedWithYou() { - guard !metadata.ownerId.isEmpty, metadata.ownerId != session.userId else { return } - - if !canReshare { - searchField.isUserInteractionEnabled = false - searchField.alpha = 0.5 - searchField.placeholder = NSLocalizedString("_share_reshare_disabled_", comment: "") - } + // MARK: - Notification Center - searchFieldTopConstraint.constant = 45 - sharedWithYouByView.isHidden = false - sharedWithYouByLabel.text = NSLocalizedString("_shared_with_you_by_", comment: "") + " " + metadata.ownerDisplayName - sharedWithYouByImage.image = utility.loadUserImage(for: metadata.ownerId, displayName: metadata.ownerDisplayName, urlBase: session.urlBase) - sharedWithYouByLabel.accessibilityHint = NSLocalizedString("_show_profile_", comment: "") - - let shareAction = UITapGestureRecognizer(target: self, action: #selector(openShareProfile)) - sharedWithYouByImage.addGestureRecognizer(shareAction) - let shareLabelAction = UITapGestureRecognizer(target: self, action: #selector(openShareProfile)) - sharedWithYouByLabel.addGestureRecognizer(shareLabelAction) - - let fileName = NCSession.shared.getFileName(urlBase: session.urlBase, user: metadata.ownerId) - let results = NCManageDatabase.shared.getImageAvatarLoaded(fileName: fileName) - - if results.image == nil { - let etag = self.database.getTableAvatar(fileName: fileName)?.etag - - NextcloudKit.shared.downloadAvatar( - user: metadata.ownerId, - fileNameLocalPath: utilityFileSystem.directoryUserData + "/" + fileName, - sizeImage: NCGlobal.shared.avatarSize, - avatarSizeRounded: NCGlobal.shared.avatarSizeRounded, - etag: etag, - account: metadata.account) { _, imageAvatar, _, etag, _, error in - if error == .success, let etag = etag, let imageAvatar = imageAvatar { - self.database.addAvatar(fileName: fileName, etag: etag) - self.sharedWithYouByImage.image = imageAvatar - } else if error.errorCode == NCGlobal.shared.errorNotModified, let imageAvatar = self.database.setAvatarLoaded(fileName: fileName) { - self.sharedWithYouByImage.image = imageAvatar + @objc func openShareProfile() { + self.showProfileMenu(userId: metadata.ownerId, session: session) + } + + @objc func keyboardWillShow(notification: Notification) { + if UIDevice.current.userInterfaceIdiom == .phone { + if (UIScreen.main.bounds.width < 374 || UIDevice.current.orientation.isLandscape) { + if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue { + if view.frame.origin.y == 0 { + self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false) + self.view.frame.origin.y -= keyboardSize.height } } + } else if UIScreen.main.bounds.height < 850 { + if view.frame.origin.y == 0 { + self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false) + self.view.frame.origin.y -= 70 + } + } else { + if view.frame.origin.y == 0 { + self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false) + self.view.frame.origin.y -= 40 + } + } + } + + if UIDevice.current.userInterfaceIdiom == .pad, UIDevice.current.orientation.isLandscape { + if view.frame.origin.y == 0 { + self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false) + self.view.frame.origin.y -= 230 + } } + textField?.layer.borderColor = NCBrandColor.shared.brand.cgColor } - - // MARK: - Notification Center - - @objc func openShareProfile() { - self.showProfileMenu(userId: metadata.ownerId, session: session) + + @objc func keyboardWillHide(notification: Notification) { + if view.frame.origin.y != 0 { + self.view.frame.origin.y = 0 + } + textField?.layer.borderColor = NCBrandColor.shared.label.cgColor } + @objc func appWillEnterForeground(notification: Notification) { + reloadData() + } // MARK: - @objc func reloadData() { @@ -186,18 +171,64 @@ class NCShare: UIViewController, NCSharePagingContent { // MARK: - IBAction @IBAction func searchFieldDidEndOnExit(textField: UITextField) { - // https://stackoverflow.com/questions/25471114/how-to-validate-an-e-mail-address-in-swift - func isValidEmail(_ email: String) -> Bool { - - let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}" - let emailPred = NSPredicate(format: "SELF MATCHES %@", emailRegEx) - return emailPred.evaluate(with: email) - } guard let searchString = textField.text, !searchString.isEmpty else { return } - if searchString.contains("@"), !isValidEmail(searchString) { return } + if searchString.contains("@"), !utility.isValidEmail(searchString) { return } networking?.getSharees(searchString: searchString) } - + + @IBAction func searchFieldDidChange(textField: UITextField) { + guard let searchString = textField.text else {return} + if searchString.count == 0 { + dropDown.hide() + } else { + networking?.getSharees(searchString: searchString) + } + } + + @IBAction func createLinkClicked(_ sender: Any) { + appDelegate?.adjust.trackEvent(TriggerEvent(CreateLink.rawValue)) + TealiumHelper.shared.trackEvent(title: "magentacloud-app.sharing.create", data: ["": ""]) + self.touchUpInsideButtonMenu(sender) + } + + @IBAction func touchUpInsideButtonMenu(_ sender: Any) { + + guard let metadata = metadata else { return } + let isFilesSharingPublicPasswordEnforced = NCGlobal.shared.capabilityFileSharingPubPasswdEnforced + let shares = NCManageDatabase.shared.getTableShares(metadata: metadata) + + if isFilesSharingPublicPasswordEnforced && shares.firstShareLink == nil { + let alertController = UIAlertController(title: NSLocalizedString("_enforce_password_protection_", comment: ""), message: "", preferredStyle: .alert) + alertController.addTextField { (textField) in + textField.isSecureTextEntry = true + } + alertController.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .default) { (action:UIAlertAction) in }) + let okAction = UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default) {[weak self] (action:UIAlertAction) in + let password = alertController.textFields?.first?.text + self?.networking?.createShareLink(password: password ?? "") + } + + alertController.addAction(okAction) + + present(alertController, animated: true, completion:nil) + } else if shares.firstShareLink == nil { + networking?.createShareLink(password: "") + } else { + networking?.createShareLink(password: "") + } + + } + + @IBAction func selectContactClicked(_ sender: Any) { + let cnPicker = CNContactPickerViewController() + cnPicker.delegate = self + cnPicker.displayedPropertyKeys = [CNContactEmailAddressesKey] + cnPicker.predicateForEnablingContact = NSPredicate(format: "emailAddresses.@count > 0") + cnPicker.predicateForSelectionOfProperty = NSPredicate(format: "emailAddresses.@count > 0") + + self.present(cnPicker, animated: true) + } + func checkEnforcedPassword(shareType: Int, completion: @escaping (String?) -> Void) { guard NCCapabilities.shared.getCapabilities(account: session.account).capabilityFileSharingPubPasswdEnforced, shareType == shareCommon.SHARE_TYPE_LINK || shareType == shareCommon.SHARE_TYPE_EMAIL @@ -216,7 +247,7 @@ class NCShare: UIViewController, NCSharePagingContent { } } -// MARK: - NCShareNetworkingDelegate + // MARK: - NCShareNetworkingDelegate extension NCShare: NCShareNetworkingDelegate { func readShareCompleted() { @@ -224,10 +255,12 @@ extension NCShare: NCShareNetworkingDelegate { } func shareCompleted() { - NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataNCShare) + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource) + self.reloadData() } func unShareCompleted() { + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource) self.reloadData() } @@ -241,18 +274,14 @@ extension NCShare: NCShareNetworkingDelegate { dropDown = DropDown() let appearance = DropDown.appearance() - // Setting up the blur effect - let blurEffect = UIBlurEffect(style: .light) // You can choose .dark, .extraLight, or .light - let blurEffectView = UIVisualEffectView(effect: blurEffect) - blurEffectView.frame = CGRect(x: 0, y: 0, width: 500, height: 20) - - appearance.backgroundColor = .systemBackground + appearance.backgroundColor = .secondarySystemGroupedBackground appearance.cornerRadius = 10 - appearance.shadowColor = .black - appearance.shadowOpacity = 0.2 - appearance.shadowRadius = 30 + appearance.shadowColor = UIColor(white: 0.5, alpha: 1) + appearance.shadowOpacity = 0.9 + appearance.shadowRadius = 25 appearance.animationduration = 0.25 appearance.textColor = .darkGray + appearance.setupMaskedCorners([.layerMaxXMaxYCorner, .layerMinXMaxYCorner]) for sharee in sharees { var label = sharee.label @@ -262,10 +291,16 @@ extension NCShare: NCShareNetworkingDelegate { dropDown.dataSource.append(label) } - dropDown.anchorView = searchField - dropDown.bottomOffset = CGPoint(x: 10, y: searchField.bounds.height) - dropDown.width = searchField.bounds.width - 20 - dropDown.direction = .bottom + dropDown.anchorView = textField + dropDown.bottomOffset = CGPoint(x: 0, y: textField?.bounds.height ?? 0) + dropDown.width = textField?.bounds.width ?? 0 + if (UIDevice.current.userInterfaceIdiom == .phone || UIDevice.current.orientation.isLandscape), UIScreen.main.bounds.width < 1111 { + dropDown.topOffset = CGPoint(x: 0, y: -(textField?.bounds.height ?? 0)) + dropDown.direction = .top + } else { + dropDown.bottomOffset = CGPoint(x: 0, y: (textField?.bounds.height ?? 0) - 80) + dropDown.direction = .any + } dropDown.cellNib = UINib(nibName: "NCSearchUserDropDownCell", bundle: nil) dropDown.customCellConfiguration = { (index: Index, _, cell: DropDownCell) in @@ -275,6 +310,8 @@ extension NCShare: NCShareNetworkingDelegate { } dropDown.selectionAction = { index, _ in + self.textField?.text = "" + self.textField?.resignFirstResponder() let sharee = sharees[index] guard let advancePermission = UIStoryboard(name: "NCShare", bundle: nil).instantiateViewController(withIdentifier: "NCShareAdvancePermission") as? NCShareAdvancePermission, @@ -298,6 +335,19 @@ extension NCShare: NCShareNetworkingDelegate { func downloadLimitSet(to limit: Int, by token: String) { database.createDownloadLimit(account: metadata.account, count: 0, limit: limit, token: token) } + + func checkIsCollaboraFile() -> Bool { + guard let metadata = metadata else { + return false + } + + // EDITORS + let editors = utility.isDirectEditing(account: metadata.account, contentType: metadata.contentType) + let availableRichDocument = utility.isRichDocument(metadata) + + // RichDocument: Collabora + return (availableRichDocument && editors.count == 0) + } } // MARK: - UITableViewDelegate @@ -305,11 +355,7 @@ extension NCShare: NCShareNetworkingDelegate { extension NCShare: UITableViewDelegate { func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - if indexPath.section == 0, indexPath.row == 0 { - // internal cell has description - return 40 - } - return 60 + return indexPath.row == 0 ? UITableView.automaticDimension : 60 } } @@ -318,105 +364,158 @@ extension NCShare: UITableViewDelegate { extension NCShare: UITableViewDataSource { func numberOfSections(in tableView: UITableView) -> Int { - return 2 + return 1 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - var numRows = shares.share?.count ?? 0 - if section == 0 { - if metadata.e2eEncrypted, NCCapabilities.shared.getCapabilities(account: metadata.account).capabilityE2EEApiVersion == NCGlobal.shared.e2eeVersionV12 { - numRows = 1 - } else { - // don't allow link creation if reshare is disabled - numRows = shares.firstShareLink != nil || canReshare ? 2 : 1 - } + var numOfRows = 0 + if let metadataobj = metadata { + shares = NCManageDatabase.shared.getTableShares(metadata: metadataobj) + } + if let shareLink = shares.firstShareLink { + shares.share?.insert(shareLink, at: 0) } - return numRows + + if shares.share != nil { + numOfRows = shares.share!.count + } + return canReshare ? (numOfRows + 1) : numOfRows } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - // Setup default share cells - guard indexPath.section != 0 else { - guard let cell = tableView.dequeueReusableCell(withIdentifier: "cellLink", for: indexPath) as? NCShareLinkCell - else { return UITableViewCell() } - cell.delegate = self - if metadata.e2eEncrypted, NCCapabilities.shared.getCapabilities(account: metadata.account).capabilityE2EEApiVersion == NCGlobal.shared.e2eeVersionV12 { - cell.tableShare = shares.firstShareLink - } else { - if indexPath.row == 1 { - cell.isInternalLink = true - } else if shares.firstShareLink?.isInvalidated != true { - cell.tableShare = shares.firstShareLink - } - } - cell.setupCellUI() + if indexPath.row == 0 { + guard let cell = tableView.dequeueReusableCell(withIdentifier: "NCShareEmailFieldCell", for: indexPath) as? NCShareEmailFieldCell else { return UITableViewCell() } + cell.searchField.addTarget(self, action: #selector(searchFieldDidEndOnExit(textField:)), for: .editingDidEndOnExit) + cell.searchField.addTarget(self, action: #selector(searchFieldDidChange(textField:)), for: .editingChanged) + cell.btnCreateLink.addTarget(self, action: #selector(createLinkClicked(_:)), for: .touchUpInside) + cell.btnContact.addTarget(self, action: #selector(selectContactClicked(_:)), for: .touchUpInside) + cell.labelNoShare.isHidden = (shares.share?.count ?? 0) > 0 + cell.heightLabelNoShare.constant = (shares.share?.count ?? 0) > 0 ? 0 : 25 return cell } - - guard let tableShare = shares.share?[indexPath.row] else { return UITableViewCell() } + + let directory = self.metadata?.directory ?? false + guard let appDelegate = appDelegate, let tableShare = shares.share?[indexPath.row - 1] else { return UITableViewCell() } // LINK if tableShare.shareType == shareCommon.SHARE_TYPE_LINK { - if let cell = tableView.dequeueReusableCell(withIdentifier: "cellLink", for: indexPath) as? NCShareLinkCell { - cell.indexPath = indexPath - cell.tableShare = tableShare - cell.delegate = self - cell.setupCellUI() - return cell + guard let cell = tableView.dequeueReusableCell(withIdentifier: "cellLink", for: indexPath) as? NCShareLinkCell + else { return UITableViewCell() } + cell.tableShare = tableShare + cell.delegate = self + cell.setupCellUI() + if !tableShare.label.isEmpty { + cell.labelTitle.text = String(format: NSLocalizedString("_share_linklabel_", comment: ""), tableShare.label) + } else { + cell.labelTitle.text = directory ? NSLocalizedString("_share_link_folder_", comment: "") : NSLocalizedString("_share_link_file_", comment: "") } + let isEditingAllowed = shareCommon.isEditingEnabled(isDirectory: directory, fileExtension: metadata?.fileExtension ?? "", shareType: tableShare.shareType) + if isEditingAllowed || directory || checkIsCollaboraFile() { + cell.btnQuickStatus.isEnabled = true + cell.labelQuickStatus.textColor = NCBrandColor.shared.brand + cell.imageDownArrow.image = UIImage(named: "downArrow")?.imageColor(NCBrandColor.shared.brand) + } else { + cell.btnQuickStatus.isEnabled = false + cell.labelQuickStatus.textColor = NCBrandColor.shared.optionItem + cell.imageDownArrow.image = UIImage(named: "downArrow")?.imageColor(NCBrandColor.shared.optionItem) + } + + return cell } else { // USER / GROUP etc. if let cell = tableView.dequeueReusableCell(withIdentifier: "cellUser", for: indexPath) as? NCShareUserCell { - cell.indexPath = indexPath cell.tableShare = tableShare cell.delegate = self - cell.setupCellUI(userId: session.userId) - - let fileName = NCSession.shared.getFileName(urlBase: session.urlBase, user: tableShare.shareWith) - let results = NCManageDatabase.shared.getImageAvatarLoaded(fileName: fileName) - - if results.image == nil { - cell.fileAvatarImageView?.image = utility.loadUserImage(for: tableShare.shareWith, displayName: tableShare.shareWithDisplayname, urlBase: metadata.urlBase) + cell.setupCellUI(userId: appDelegate.userId) + let isEditingAllowed = shareCommon.isEditingEnabled(isDirectory: directory, fileExtension: metadata?.fileExtension ?? "", shareType: tableShare.shareType) + if isEditingAllowed || checkIsCollaboraFile() { + cell.btnQuickStatus.isEnabled = true } else { - cell.fileAvatarImageView?.image = results.image - } - - if !(results.tableAvatar?.loaded ?? false), - NCNetworking.shared.downloadAvatarQueue.operations.filter({ ($0 as? NCOperationDownloadAvatar)?.fileName == fileName }).isEmpty { - NCNetworking.shared.downloadAvatarQueue.addOperation(NCOperationDownloadAvatar(user: tableShare.shareWith, fileName: fileName, account: metadata.account, view: tableView)) + cell.btnQuickStatus.isEnabled = false + cell.labelQuickStatus.textColor = NCBrandColor.shared.optionItem + cell.imageDownArrow.image = UIImage(named: "downArrow")?.imageColor(NCBrandColor.shared.optionItem) } - return cell } } return UITableViewCell() } + + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + guard let headerView = Bundle.main.loadNibNamed("NCShareHeaderView", owner: self, options: nil)?.first as? NCShareHeaderView else { + return UIView() + } + headerView.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + headerView.fileName.textColor = NCBrandColor.shared.label + headerView.labelSharing.textColor = NCBrandColor.shared.label + headerView.labelSharingInfo.textColor = NCBrandColor.shared.label + headerView.info.textColor = NCBrandColor.shared.systemGray2 + headerView.ocId = metadata!.ocId + headerView.updateCanReshareUI() + + + if FileManager.default.fileExists(atPath: utilityFileSystem.getDirectoryProviderStorageIconOcId(metadata?.ocId ?? "", etag: metadata?.etag ?? "")) { + headerView.fullWidthImageView.image = UIImage(contentsOfFile: utilityFileSystem.getDirectoryProviderStorageIconOcId(metadata?.ocId ?? "", etag: metadata?.etag ?? "")) + headerView.fullWidthImageView.contentMode = .scaleAspectFill + headerView.imageView.isHidden = true + } else { + if metadata?.directory ?? false { + let image = (metadata?.e2eEncrypted ?? false) ? UIImage(named: "folderEncrypted") : UIImage(named: "folder_nmcloud") + headerView.imageView.image = image + } else if !(metadata?.iconName.isEmpty ?? false) { + headerView.imageView.image = metadata!.fileExtension == "odg" ? UIImage(named: "file-diagram") : UIImage.init(named: metadata!.iconName) + } else { + headerView.imageView.image = UIImage(named: "file") + } + } + + headerView.fileName.text = metadata?.fileNameView + headerView.fileName.textColor = NCBrandColor.shared.label + if metadata!.favorite { + headerView.favorite.setImage(utility.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite, size: 24), for: .normal) + } else { + headerView.favorite.setImage(utility.loadImage(named: "star.fill", color: NCBrandColor.shared.textInfo, size: 24), for: .normal) + } + headerView.info.text = utilityFileSystem.transformedSize(metadata!.size) + ", " + utility.dateDiff(metadata!.date as Date) + return headerView + + } + func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat { + return metadata?.ownerId != appDelegate?.userId ? canReshare ? 400 : 350 : 320 + } + func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + return metadata?.ownerId != appDelegate?.userId ? canReshare ? UITableView.automaticDimension : 350 : 320 + } } -// MARK: - CNContactPickerDelegate +//MARK: CNContactPickerDelegate extension NCShare: CNContactPickerDelegate { func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) { if contact.emailAddresses.count > 1 { showEmailList(arrEmail: contact.emailAddresses.map({$0.value as String})) } else if let email = contact.emailAddresses.first?.value as? String { - searchField?.text = email + textField?.text = email networking?.getSharees(searchString: email) } } - + + func contactPickerDidCancel(_ picker: CNContactPickerViewController) { + self.keyboardWillHide(notification: Notification(name: Notification.Name("dismiss"))) + } + func showEmailList(arrEmail: [String]) { var actions = [NCMenuAction]() for email in arrEmail { actions.append( NCMenuAction( title: email, - icon: utility.loadImage(named: "email", colors: [NCBrandColor.shared.iconImageColor]), + icon: utility.loadImage(named: "email").imageColor(NCBrandColor.shared.brandElement), selected: false, on: false, action: { _ in - self.searchField?.text = email + self.textField?.text = email self.networking?.getSharees(searchString: email) } ) diff --git a/iOSClient/Share/NCShareCommon.swift b/iOSClient/Share/NCShareCommon.swift index da2f6e1189..73d9029728 100644 --- a/iOSClient/Share/NCShareCommon.swift +++ b/iOSClient/Share/NCShareCommon.swift @@ -43,7 +43,7 @@ class NCShareCommon: NSObject { let size: CGFloat = 200 let bottomImage = UIImage(named: "circle_fill")!.image(color: colorCircle, size: size / 2) - let topImage = NCUtility().loadImage(named: imageName, colors: [NCBrandColor.shared.iconImageColor]) + let topImage = UIImage(named: imageName)!.image(color: .white, size: size / 2) UIGraphicsBeginImageContextWithOptions(CGSize(width: size, height: size), false, UIScreen.main.scale) bottomImage.draw(in: CGRect(origin: CGPoint.zero, size: CGSize(width: size, height: size))) topImage.draw(in: CGRect(origin: CGPoint(x: size / 4, y: size / 4), size: CGSize(width: size / 2, height: size / 2))) @@ -69,31 +69,74 @@ class NCShareCommon: NSObject { } } - func getImageShareType(shareType: Int) -> UIImage? { - + func getImageShareType(shareType: Int, isDropDown:Bool = false) -> UIImage? { + switch shareType { case SHARE_TYPE_USER: - return UIImage(named: "shareTypeUser")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) + return UIImage(named: "shareTypeEmail")?.imageColor(NCBrandColor.shared.label) case self.SHARE_TYPE_GROUP: - return UIImage(named: "shareTypeGroup")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) + return UIImage(named: "shareTypeGroup")?.imageColor(NCBrandColor.shared.label) case self.SHARE_TYPE_LINK: - return UIImage(named: "shareTypeLink")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) + return UIImage(named: "shareTypeLink")?.imageColor(NCBrandColor.shared.label) case self.SHARE_TYPE_EMAIL: - return UIImage(named: "shareTypeEmail")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) + return UIImage(named: isDropDown ? "email" : "shareTypeUser")?.imageColor(NCBrandColor.shared.label) case self.SHARE_TYPE_CONTACT: - return UIImage(named: "shareTypeUser")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) + return UIImage(named: "shareTypeUser")?.imageColor(NCBrandColor.shared.label) case self.SHARE_TYPE_REMOTE: - return UIImage(named: "shareTypeUser")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) + return UIImage(named: isDropDown ? "shareTypeUser" : "shareTypeEmail")?.imageColor(NCBrandColor.shared.label) case self.SHARE_TYPE_CIRCLE: - return UIImage(named: "shareTypeCircles")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) + return UIImage(named: "shareTypeCircles")?.imageColor(NCBrandColor.shared.label) case self.SHARE_TYPE_GUEST: - return UIImage(named: "shareTypeUser")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) + return UIImage(named: "shareTypeUser")?.imageColor(NCBrandColor.shared.label) case self.SHARE_TYPE_REMOTE_GROUP: - return UIImage(named: "shareTypeGroup")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) + return UIImage(named: "shareTypeGroup")?.imageColor(NCBrandColor.shared.label) case self.SHARE_TYPE_ROOM: - return UIImage(named: "shareTypeRoom")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) + return UIImage(named: "shareTypeRoom")?.imageColor(NCBrandColor.shared.label) default: - return UIImage(named: "shareTypeUser")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) + return UIImage(named: "shareTypeUser")?.imageColor(NCBrandColor.shared.label) + } + } + + func isLinkShare(shareType: Int) -> Bool { + return shareType == SHARE_TYPE_LINK + } + + func isExternalUserShare(shareType: Int) -> Bool { + return shareType == SHARE_TYPE_EMAIL + } + + func isInternalUser(shareType: Int) -> Bool { + return shareType == SHARE_TYPE_USER + } + + func isFileTypeAllowedForEditing(fileExtension: String, shareType: Int) -> Bool { + if fileExtension == "md" || fileExtension == "txt" { + return true + } else { + return isInternalUser(shareType: shareType) } } + + func isEditingEnabled(isDirectory: Bool, fileExtension: String, shareType: Int) -> Bool { + if !isDirectory {//file + return isFileTypeAllowedForEditing(fileExtension: fileExtension, shareType: shareType) + } else { + return true + } + } + + func isFileDropOptionVisible(isDirectory: Bool, shareType: Int) -> Bool { + return (isDirectory && (isLinkShare(shareType: shareType) || isExternalUserShare(shareType: shareType))) + } + + func isCurrentUserIsFileOwner(fileOwnerId: String) -> Bool { + if let currentUser = NCManageDatabase.shared.getActiveAccount(), currentUser.userId == fileOwnerId { + return true + } + return false + } + + func canReshare(withPermission permission: String) -> Bool { + return permission.contains(NCGlobal.shared.permissionCanShare) + } } diff --git a/iOSClient/Share/NCShareEmailFieldCell.swift b/iOSClient/Share/NCShareEmailFieldCell.swift new file mode 100644 index 0000000000..c39be3b210 --- /dev/null +++ b/iOSClient/Share/NCShareEmailFieldCell.swift @@ -0,0 +1,89 @@ +// +// NCShareEmailFieldCell.swift +// Nextcloud +// +// Created by A200020526 on 01/06/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +import UIKit + +enum Tag { + static let searchField = 999 +} + +class NCShareEmailFieldCell: UITableViewCell { + @IBOutlet weak var searchField: UITextField! + @IBOutlet weak var btnCreateLink: UIButton! + @IBOutlet weak var labelYourShare: UILabel! + @IBOutlet weak var labelShareByMail: UILabel! + @IBOutlet weak var btnContact: UIButton! + @IBOutlet weak var labelNoShare: UILabel! + @IBOutlet weak var heightLabelNoShare: NSLayoutConstraint! + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + setupCell() + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + + func setupCell(){ + self.btnCreateLink.setTitle(NSLocalizedString("_create_link_", comment: ""), for: .normal) + self.btnCreateLink.layer.cornerRadius = 7 + self.btnCreateLink.layer.masksToBounds = true + self.btnCreateLink.layer.borderWidth = 1 + self.btnCreateLink.titleLabel?.font = UIFont.systemFont(ofSize: 17) + self.btnCreateLink.titleLabel!.adjustsFontSizeToFitWidth = true + self.btnCreateLink.titleLabel!.minimumScaleFactor = 0.5 + self.btnCreateLink.layer.borderColor = NCBrandColor.shared.label.cgColor + self.btnCreateLink.setTitleColor(NCBrandColor.shared.label, for: .normal) + self.btnCreateLink.backgroundColor = .clear + + self.labelShareByMail.text = NSLocalizedString("personal_share_by_mail", comment: "") + self.labelShareByMail.textColor = NCBrandColor.shared.shareByEmailTextColor + + labelYourShare.text = NSLocalizedString("_your_shares_", comment: "") + + searchField.layer.cornerRadius = 5 + searchField.layer.masksToBounds = true + searchField.layer.borderWidth = 1 + self.searchField.text = "" + searchField.attributedPlaceholder = NSAttributedString(string: NSLocalizedString("_shareLinksearch_placeholder_", comment: ""), + attributes: [NSAttributedString.Key.foregroundColor: NCBrandColor.shared.gray60]) + searchField.textColor = NCBrandColor.shared.label + searchField.layer.borderColor = NCBrandColor.shared.label.cgColor + searchField.tag = Tag.searchField + setDoneButton(sender: searchField) + + btnContact.layer.cornerRadius = 5 + btnContact.layer.masksToBounds = true + btnContact.layer.borderWidth = 1 + btnContact.layer.borderColor = NCBrandColor.shared.label.cgColor + btnContact.tintColor = NCBrandColor.shared.label + btnContact.setImage(NCUtility().loadImage(named: "contact").image(color: NCBrandColor.shared.label, size: 24), for: .normal) + labelNoShare.textColor = NCBrandColor.shared.textInfo + labelNoShare.numberOfLines = 0 + labelNoShare.font = UIFont.systemFont(ofSize: 17) + labelNoShare.text = NSLocalizedString("no_shares_created", comment: "") + } + + @objc func cancelDatePicker() { + self.searchField.endEditing(true) + } + + func setDoneButton(sender: UITextField) { + //ToolBar + let toolbar = UIToolbar(); + toolbar.sizeToFit() + let doneButton = UIBarButtonItem(title: NSLocalizedString("_done_", comment: ""), style: .plain, target: self, action: #selector(cancelDatePicker)); + let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil) + toolbar.setItems([spaceButton, doneButton], animated: false) + sender.inputAccessoryView = toolbar + } +} diff --git a/iOSClient/Share/NCShareEmailFieldCell.xib b/iOSClient/Share/NCShareEmailFieldCell.xib new file mode 100644 index 0000000000..72cbdfe2d3 --- /dev/null +++ b/iOSClient/Share/NCShareEmailFieldCell.xib @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOSClient/Share/NCShareHeader.swift b/iOSClient/Share/NCShareHeader.swift index a18f2b6114..749197c7af 100644 --- a/iOSClient/Share/NCShareHeader.swift +++ b/iOSClient/Share/NCShareHeader.swift @@ -1,5 +1,5 @@ // -// NCShareHeader.swift +// NCShareAdvancePermissionHeader.swift // Nextcloud // // Created by T-systems on 10/08/21. @@ -22,52 +22,61 @@ // import UIKit -import TagListView -class NCShareHeader: UIView { +class NCShareAdvancePermissionHeader: UIView { @IBOutlet weak var imageView: UIImageView! @IBOutlet weak var fileName: UILabel! @IBOutlet weak var info: UILabel! + @IBOutlet weak var favorite: UIButton! @IBOutlet weak var fullWidthImageView: UIImageView! - @IBOutlet weak var fileNameTopConstraint: NSLayoutConstraint! - @IBOutlet weak var tagListView: TagListView! - - private var heightConstraintWithImage: NSLayoutConstraint? - private var heightConstraintWithoutImage: NSLayoutConstraint? - + var ocId = "" + let utility = NCUtility() + let utilityFileSystem = NCUtilityFileSystem() + func setupUI(with metadata: tableMetadata) { - let utilityFileSystem = NCUtilityFileSystem() - if let image = NCUtility().getImage(ocId: metadata.ocId, etag: metadata.etag, ext: NCGlobal.shared.previewExt1024) { - fullWidthImageView.image = image + backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + fileName.textColor = NCBrandColor.shared.label + info.textColor = NCBrandColor.shared.textInfo + backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + if FileManager.default.fileExists(atPath: utilityFileSystem.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) { + fullWidthImageView.image = utility.getImageMetadata(metadata, for: frame.height) fullWidthImageView.contentMode = .scaleAspectFill - imageView.image = fullWidthImageView.image imageView.isHidden = true } else { if metadata.directory { - imageView.image = metadata.e2eEncrypted ? NCImageCache.shared.getFolderEncrypted(account: metadata.account) : NCImageCache.shared.getFolder(account: metadata.account) + imageView.image = UIImage.init(named: "folder") } else if !metadata.iconName.isEmpty { - imageView.image = NCUtility().loadImage(named: metadata.iconName, useTypeIconFile: true, account: metadata.account) + imageView.image = UIImage.init(named: metadata.iconName) } else { - imageView.image = NCImageCache.shared.getImageFile() + imageView.image = UIImage.init(named: "file") } - - fileNameTopConstraint.constant -= 45 } - + favorite.setNeedsUpdateConstraints() + favorite.layoutIfNeeded() fileName.text = metadata.fileNameView - fileName.textColor = NCBrandColor.shared.textColor - info.textColor = NCBrandColor.shared.textColor2 - info.text = utilityFileSystem.transformedSize(metadata.size) + ", " + NCUtility().getRelativeDateTitle(metadata.date as Date) - - tagListView.addTags(Array(metadata.tags)) - - setNeedsLayout() - layoutIfNeeded() + fileName.textColor = NCBrandColor.shared.fileFolderName + if metadata.favorite { + favorite.setImage(utility.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite, size: 24), for: .normal) + } else { + favorite.setImage(utility.loadImage(named: "star.fill", color: NCBrandColor.shared.textInfo, size: 24), for: .normal) + } + info.textColor = NCBrandColor.shared.optionItem + info.text = utilityFileSystem.transformedSize(metadata.size) + ", " + utility.dateDiff(metadata.date as Date) } - - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - if fullWidthImageView.image != nil { - imageView.isHidden = traitCollection.verticalSizeClass != .compact + + @IBAction func touchUpInsideFavorite(_ sender: UIButton) { + guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return } + NCNetworking.shared.favoriteMetadata(metadata) { error in + if error == .success { + guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(metadata.ocId) else { return } + if metadata.favorite { + self.favorite.setImage(self.utility.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite, size: 24), for: .normal) + } else { + self.favorite.setImage(self.utility.loadImage(named: "star.fill", color: NCBrandColor.shared.textInfo, size: 24), for: .normal) + } + } else { + NCContentPresenter().showError(error: error) + } } } } diff --git a/iOSClient/Share/NCShareHeaderView.xib b/iOSClient/Share/NCShareHeaderView.xib index 44b83d3fc7..b7384fb2ec 100644 --- a/iOSClient/Share/NCShareHeaderView.xib +++ b/iOSClient/Share/NCShareHeaderView.xib @@ -1,149 +1,176 @@ - + - - + - - + + - - + + - - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + - + - - - - - - - - - - - - - - - + + diff --git a/iOSClient/Share/NCShareLinkCell.swift b/iOSClient/Share/NCShareLinkCell.swift index 1db528ce16..45147a5c56 100644 --- a/iOSClient/Share/NCShareLinkCell.swift +++ b/iOSClient/Share/NCShareLinkCell.swift @@ -24,12 +24,16 @@ import UIKit class NCShareLinkCell: UITableViewCell { - @IBOutlet private weak var imageItem: UIImageView! - @IBOutlet private weak var labelTitle: UILabel! - @IBOutlet private weak var descriptionLabel: UILabel! + @IBOutlet weak var imageItem: UIImageView! + @IBOutlet weak var labelTitle: UILabel! + @IBOutlet weak var buttonCopy: UIButton! + @IBOutlet weak var buttonMenu: UIButton! + @IBOutlet weak var status: UILabel! + @IBOutlet weak var btnQuickStatus: UIButton! + @IBOutlet weak var imageDownArrow: UIImageView! + @IBOutlet weak var labelQuickStatus: UILabel! - @IBOutlet private weak var menuButton: UIButton! - @IBOutlet private weak var copyButton: UIButton! + private let iconShare: CGFloat = 200 var tableShare: tableShare? weak var delegate: NCShareLinkCellDelegate? var isInternalLink = false @@ -41,55 +45,49 @@ class NCShareLinkCell: UITableViewCell { tableShare = nil } - func setupCellUI() { - var menuImageName = "ellipsis" - - menuButton.isHidden = isInternalLink - descriptionLabel.isHidden = !isInternalLink - copyButton.isHidden = !isInternalLink && tableShare == nil - if #available(iOS 18.0, *) { - // use NCShareLinkCell image - } else { - copyButton.setImage(UIImage(systemName: "doc.on.doc")?.withTintColor(.label, renderingMode: .alwaysOriginal), for: .normal) - } - copyButton.accessibilityLabel = NSLocalizedString("_copy_", comment: "") + override func awakeFromNib() { + super.awakeFromNib() - menuButton.accessibilityLabel = NSLocalizedString("_more_", comment: "") - menuButton.accessibilityIdentifier = "showShareLinkDetails" + imageItem.image = UIImage(named: "sharebylink")?.image(color: NCBrandColor.shared.label, size: 30) + buttonCopy.setImage(UIImage.init(named: "shareCopy")!.image(color: NCBrandColor.shared.customer, size: 24), for: .normal) + buttonMenu.setImage(UIImage.init(named: "shareMenu")!.image(color: NCBrandColor.shared.customer, size: 24), for: .normal) + labelQuickStatus.textColor = NCBrandColor.shared.customer + } - if isInternalLink { - labelTitle.text = NSLocalizedString("_share_internal_link_", comment: "") - descriptionLabel.text = NSLocalizedString("_share_internal_link_des_", comment: "") - imageItem.image = NCUtility().loadImage(named: "square.and.arrow.up.circle.fill", colors: [NCBrandColor.shared.iconImageColor2]) + func setupCellUI() { + guard let tableShare = tableShare else { + return + } + contentView.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + labelTitle.textColor = NCBrandColor.shared.label + + if tableShare.permissions == NCGlobal.shared.permissionCreateShare { + labelQuickStatus.text = NSLocalizedString("_share_file_drop_", comment: "") } else { - labelTitle.text = NSLocalizedString("_share_link_", comment: "") - if let tableShare = tableShare { - if !tableShare.label.isEmpty { - labelTitle.text? += " (\(tableShare.label))" - } + // Read Only + if CCUtility.isAnyPermission(toEdit: tableShare.permissions) { + labelQuickStatus.text = NSLocalizedString("_share_editing_", comment: "") } else { - menuImageName = "plus" - menuButton.accessibilityLabel = NSLocalizedString("_add_", comment: "") - menuButton.accessibilityIdentifier = "addShareLink" + labelQuickStatus.text = NSLocalizedString("_share_read_only_", comment: "") } - - imageItem.image = NCUtility().loadImage(named: "link.circle.fill", colors: [NCBrandColor.shared.getElement(account: tableShare?.account)]) - menuButton.setImage(NCUtility().loadImage(named: menuImageName, colors: [NCBrandColor.shared.iconImageColor]), for: .normal) } - - labelTitle.textColor = NCBrandColor.shared.textColor } - - @IBAction func touchUpCopy(_ sender: Any) { + + @IBAction func touchUpInsideCopy(_ sender: Any) { delegate?.tapCopy(with: tableShare, sender: sender) } - - @IBAction func touchUpMenu(_ sender: Any) { + + @IBAction func touchUpInsideMenu(_ sender: Any) { delegate?.tapMenu(with: tableShare, sender: sender) } + + @IBAction func quickStatusClicked(_ sender: UIButton) { + delegate?.quickStatus(with: tableShare, sender: sender) + } } protocol NCShareLinkCellDelegate: AnyObject { func tapCopy(with tableShare: tableShare?, sender: Any) func tapMenu(with tableShare: tableShare?, sender: Any) + func quickStatus(with tableShare: tableShare?, sender: Any) } diff --git a/iOSClient/Share/NCShareLinkCell.xib b/iOSClient/Share/NCShareLinkCell.xib index caf3d7dc2e..25549d22a6 100755 --- a/iOSClient/Share/NCShareLinkCell.xib +++ b/iOSClient/Share/NCShareLinkCell.xib @@ -1,127 +1,120 @@ - - + + - - - + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + - - - - - + + + + + + + + - + - - - - - - - - - - - - + + + diff --git a/iOSClient/Share/NCShareNetworking.swift b/iOSClient/Share/NCShareNetworking.swift index bcf2c69e64..c5fd664e20 100644 --- a/iOSClient/Share/NCShareNetworking.swift +++ b/iOSClient/Share/NCShareNetworking.swift @@ -97,6 +97,21 @@ class NCShareNetworking: NSObject { } } } + + func createShareLink(password: String?) { + NCActivityIndicator.shared.start(backgroundView: view) + let filenamePath = utilityFileSystem.getFileNamePath(metadata.fileName, serverUrl: metadata.serverUrl, urlBase: metadata.urlBase, userId: metadata.userId) + NextcloudKit.shared.createShareLink(path: filenamePath) { [self] account, share, data, error in + NCActivityIndicator.shared.stop() + if error == .success && share != nil { + let home = utilityFileSystem.getHomeServer(urlBase: self.metadata.urlBase, userId: self.metadata.userId) + NCManageDatabase.shared.addShare(account: self.metadata.account, home:home, shares: [share!]) + } else if error != .success{ + NCContentPresenter().showError(error: error) + } + self.delegate?.shareCompleted() + } + } func createShare(_ template: Shareable, downloadLimit: DownloadLimitViewModel) { // NOTE: Permissions don't work for creating with file drop! diff --git a/iOSClient/Share/NCSharePaging.swift b/iOSClient/Share/NCSharePaging.swift index b7dc569a9c..28db6c6304 100644 --- a/iOSClient/Share/NCSharePaging.swift +++ b/iOSClient/Share/NCSharePaging.swift @@ -29,7 +29,7 @@ import MarqueeLabel import TagListView protocol NCSharePagingContent { - var textField: UIView? { get } + var textField: UITextField? { get } } class NCSharePaging: UIViewController { @@ -50,21 +50,18 @@ class NCSharePaging: UIViewController { view.backgroundColor = .systemBackground title = NSLocalizedString("_details_", comment: "") - navigationController?.navigationBar.tintColor = NCBrandColor.shared.iconImageColor - navigationItem.leftBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_close_", comment: ""), style: .done, target: self, action: #selector(exitTapped)) - + navigationItem.leftBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_cancel_", comment: ""), style: .done, target: self, action: #selector(exitTapped)) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(applicationDidEnterBackground(notification:)), name: UIApplication.didEnterBackgroundNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(applicationDidEnterBackground(notification:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidEnterBackground), object: nil) // *** MUST BE THE FIRST ONE *** pagingViewController.metadata = metadata pagingViewController.backgroundColor = .systemBackground pagingViewController.menuBackgroundColor = .systemBackground pagingViewController.selectedBackgroundColor = .systemBackground - pagingViewController.indicatorColor = NCBrandColor.shared.getElement(account: metadata.account) - pagingViewController.textColor = NCBrandColor.shared.textColor - pagingViewController.selectedTextColor = NCBrandColor.shared.getElement(account: metadata.account) + pagingViewController.textColor = .label + pagingViewController.selectedTextColor = .label // Pagination addChild(pagingViewController) @@ -76,16 +73,14 @@ class NCSharePaging: UIViewController { height: 1, zIndex: Int.max, spacing: .zero, - insets: .zero + insets: UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5) ) - pagingViewController.borderOptions = .visible(height: 1, zIndex: Int.max, insets: .zero) - // Contrain the paging view to all edges. pagingViewController.view.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ pagingViewController.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), - pagingViewController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor), + pagingViewController.view.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), pagingViewController.view.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), pagingViewController.view.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor) ]) @@ -99,6 +94,7 @@ class NCSharePaging: UIViewController { pagingViewController.select(index: 0) } + (pagingViewController.view as? NCSharePagingView)?.setupConstraints() pagingViewController.reloadMenu() } @@ -113,9 +109,9 @@ class NCSharePaging: UIViewController { self.dismiss(animated: false, completion: nil) } -// pagingViewController.menuItemSize = .fixed( -// width: self.view.bounds.width / CGFloat(self.pages.count), -// height: 40) + pagingViewController.menuItemSize = .fixed( + width: self.view.bounds.width / CGFloat(self.pages.count), + height: 40) } override func viewWillDisappear(_ animated: Bool) { @@ -126,12 +122,17 @@ class NCSharePaging: UIViewController { deinit { NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardDidShowNotification, object: nil) NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil) - NotificationCenter.default.removeObserver(self, name: UIApplication.didEnterBackgroundNotification, object: nil) } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) - self.currentVC?.textField?.resignFirstResponder() + + coordinator.animate(alongsideTransition: nil) { _ in + self.pagingViewController.menuItemSize = .fixed( + width: self.view.bounds.width / CGFloat(self.pages.count), + height: 40) + self.currentVC?.textField?.resignFirstResponder() + } } // MARK: - NotificationCenter & Keyboard & TextField @@ -181,7 +182,7 @@ extension NCSharePaging: PagingViewControllerDataSource { func pagingViewController(_: PagingViewController, viewControllerAt index: Int) -> UIViewController { - let height: CGFloat = 50 + let height = pagingViewController.options.menuHeight + NCSharePagingView.headerHeight + NCSharePagingView.tagHeaderHeight if pages[index] == .activity { guard let viewController = UIStoryboard(name: "NCActivity", bundle: nil).instantiateInitialViewController() as? NCActivity else { @@ -244,11 +245,11 @@ class NCShareHeaderViewController: PagingViewController { } class NCSharePagingView: PagingView { + + static let headerHeight: CGFloat = 90 + static var tagHeaderHeight: CGFloat = 0 var metadata = tableMetadata() - let utilityFileSystem = NCUtilityFileSystem() - let utility = NCUtility() public var headerHeightConstraint: NSLayoutConstraint? - var header: NCShareHeader? // MARK: - View Life Cycle @@ -261,85 +262,75 @@ class NCSharePagingView: PagingView { required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - - override func setupConstraints() { - guard let headerView = Bundle.main.loadNibNamed("NCShareHeader", owner: self, options: nil)?.first as? NCShareHeader else { return } - header = headerView - headerView.backgroundColor = .systemBackground - - let dateFormatter = DateFormatter() - dateFormatter.dateStyle = .short - dateFormatter.timeStyle = .short - dateFormatter.locale = Locale.current - - headerView.setupUI(with: metadata) - - addSubview(headerView) - - collectionView.translatesAutoresizingMaskIntoConstraints = false - headerView.translatesAutoresizingMaskIntoConstraints = false - pageView.translatesAutoresizingMaskIntoConstraints = false - - NSLayoutConstraint.activate([ - collectionView.leadingAnchor.constraint(equalTo: leadingAnchor), - collectionView.trailingAnchor.constraint(equalTo: trailingAnchor), - collectionView.heightAnchor.constraint(equalToConstant: options.menuHeight), - collectionView.topAnchor.constraint(equalTo: headerView.bottomAnchor), - - headerView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor), - headerView.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor), - headerView.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor), - - pageView.leadingAnchor.constraint(equalTo: leadingAnchor), - pageView.trailingAnchor.constraint(equalTo: trailingAnchor), - pageView.bottomAnchor.constraint(equalTo: bottomAnchor), - pageView.topAnchor.constraint(equalTo: headerView.bottomAnchor) - ]) - } } class NCShareHeaderView: UIView { @IBOutlet weak var imageView: UIImageView! - @IBOutlet weak var path: MarqueeLabel! + @IBOutlet weak var fileName: UILabel! @IBOutlet weak var info: UILabel! - @IBOutlet weak var creation: UILabel! - @IBOutlet weak var upload: UILabel! @IBOutlet weak var favorite: UIButton! - @IBOutlet weak var details: UIButton! - @IBOutlet weak var tagListView: TagListView! - + @IBOutlet weak var labelSharing: UILabel! + @IBOutlet weak var labelSharingInfo: UILabel! + @IBOutlet weak var fullWidthImageView: UIImageView! + @IBOutlet weak var canShareInfoView: UIView! + @IBOutlet weak var sharedByLabel: UILabel! + @IBOutlet weak var resharingAllowedLabel: UILabel! + @IBOutlet weak var sharedByImageView: UIImageView! + @IBOutlet weak var constraintTopSharingLabel: NSLayoutConstraint! + let utility = NCUtility() var ocId = "" override func awakeFromNib() { super.awakeFromNib() - let longGesture = UILongPressGestureRecognizer(target: self, action: #selector(self.longTap)) - path.addGestureRecognizer(longGesture) + setupUI() } + func setupUI() { + labelSharing.text = NSLocalizedString("_sharing_", comment: "") + labelSharingInfo.text = NSLocalizedString("_sharing_message_", comment: "") + + if UIScreen.main.bounds.width < 376 { + constraintTopSharingLabel.constant = 15 + } + } + + func updateCanReshareUI() { + let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) + var isCurrentUser = true + if let ownerId = metadata?.ownerId, !ownerId.isEmpty { + isCurrentUser = NCShareCommon().isCurrentUserIsFileOwner(fileOwnerId: ownerId) + } + var canReshare: Bool { + guard let metadata = metadata else { return true } + return ((metadata.sharePermissionsCollaborationServices & NCGlobal.shared.permissionShareShare) != 0) + } + canShareInfoView.isHidden = isCurrentUser + labelSharingInfo.isHidden = !isCurrentUser + + if !isCurrentUser { + sharedByImageView.image = UIImage(named: "cloudUpload")?.image(color: .systemBlue, size: 26) + let ownerName = metadata?.ownerDisplayName ?? "" + sharedByLabel.text = NSLocalizedString("_shared_with_you_by_", comment: "") + " " + ownerName + let resharingAllowedMessage = NSLocalizedString("_share_reshare_allowed_", comment: "") + " " + NSLocalizedString("_sharing_message_", comment: "") + let resharingNotAllowedMessage = NSLocalizedString("_share_reshare_not_allowed_", comment: "") + resharingAllowedLabel.text = canReshare ? resharingAllowedMessage : resharingNotAllowedMessage + } + } + @IBAction func touchUpInsideFavorite(_ sender: UIButton) { guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return } NCNetworking.shared.favoriteMetadata(metadata) { error in if error == .success { guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(metadata.ocId) else { return } - self.favorite.setImage(NCUtility().loadImage( - named: "star.fill", - colors: metadata.favorite ? [NCBrandColor.shared.yellowFavorite] : [NCBrandColor.shared.iconImageColor2], - size: 20), for: .normal) + if metadata.favorite { + self.favorite.setImage(self.utility.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite, size: 24), for: .normal) + } else { + self.favorite.setImage(self.utility.loadImage(named: "star.fill", color: NCBrandColor.shared.textInfo, size: 24), for: .normal) + } } else { NCContentPresenter().showError(error: error) } } } - - @IBAction func touchUpInsideDetails(_ sender: UIButton) { - creation.isHidden = !creation.isHidden - upload.isHidden = !upload.isHidden - } - - @objc func longTap(sender: UIGestureRecognizer) { - UIPasteboard.general.string = path.text - let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_copied_path_") - NCContentPresenter().showInfo(error: error) - } } diff --git a/iOSClient/Share/NCShareUserCell.swift b/iOSClient/Share/NCShareUserCell.swift index 576964010a..0d6aab6b10 100644 --- a/iOSClient/Share/NCShareUserCell.swift +++ b/iOSClient/Share/NCShareUserCell.swift @@ -34,7 +34,8 @@ class NCShareUserCell: UITableViewCell, NCCellProtocol { @IBOutlet weak var btnQuickStatus: UIButton! @IBOutlet weak var labelQuickStatus: UILabel! @IBOutlet weak var imageDownArrow: UIImageView! - + @IBOutlet weak var labelCanEdit: UILabel! + @IBOutlet weak var switchCanEdit: UISwitch! private var index = IndexPath() var tableShare: tableShare? @@ -45,9 +46,6 @@ class NCShareUserCell: UITableViewCell, NCCellProtocol { get { return index } set { index = newValue } } - var fileAvatarImageView: UIImageView? { - return imageItem - } var fileUser: String? { get { return tableShare?.shareWith } set {} @@ -57,41 +55,47 @@ class NCShareUserCell: UITableViewCell, NCCellProtocol { guard let tableShare = tableShare else { return } - self.accessibilityCustomActions = [UIAccessibilityCustomAction( - name: NSLocalizedString("_show_profile_", comment: ""), - target: self, - selector: #selector(tapAvatarImage))] - let permissions = NCPermissions() + contentView.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + labelTitle.text = tableShare.shareWithDisplayname - labelTitle.textColor = NCBrandColor.shared.textColor + labelTitle.textColor = NCBrandColor.shared.label isUserInteractionEnabled = true - labelQuickStatus.isHidden = false - imageDownArrow.isHidden = false + switchCanEdit.isHidden = true + labelCanEdit.isHidden = true buttonMenu.isHidden = false buttonMenu.accessibilityLabel = NSLocalizedString("_more_", comment: "") imageItem.image = NCShareCommon().getImageShareType(shareType: tableShare.shareType) let status = utility.getUserStatus(userIcon: tableShare.userIcon, userStatus: tableShare.userStatus, userMessage: tableShare.userMessage) - imageStatus.image = status.statusImage + imageStatus.image = status.onlineStatus self.status.text = status.statusMessage + + if CCUtility.isAnyPermission(toEdit: tableShare.permissions) { + switchCanEdit.setOn(true, animated: false) + } else { + switchCanEdit.setOn(false, animated: false) + } // If the initiator or the recipient is not the current user, show the list of sharees without any options to edit it. if tableShare.uidOwner != userId && tableShare.uidFileOwner != userId { isUserInteractionEnabled = false - labelQuickStatus.isHidden = true - imageDownArrow.isHidden = true + switchCanEdit.isHidden = true + labelCanEdit.isHidden = true buttonMenu.isHidden = true } btnQuickStatus.accessibilityHint = NSLocalizedString("_user_sharee_footer_", comment: "") btnQuickStatus.setTitle("", for: .normal) btnQuickStatus.contentHorizontalAlignment = .left + btnQuickStatus.isEnabled = true + labelQuickStatus.textColor = NCBrandColor.shared.brand + imageDownArrow.image = UIImage(named: "downArrow")?.imageColor(NCBrandColor.shared.brand) - if tableShare.permissions == permissions.permissionCreateShare { + if tableShare.permissions == NCGlobal.shared.permissionCreateShare { labelQuickStatus.text = NSLocalizedString("_share_file_drop_", comment: "") } else { // Read Only - if permissions.isAnyPermissionToEdit(tableShare.permissions) { + if CCUtility.isAnyPermission(toEdit: tableShare.permissions) { labelQuickStatus.text = NSLocalizedString("_share_editing_", comment: "") } else { labelQuickStatus.text = NSLocalizedString("_share_read_only_", comment: "") @@ -101,11 +105,12 @@ class NCShareUserCell: UITableViewCell, NCCellProtocol { override func awakeFromNib() { super.awakeFromNib() - let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapAvatarImage)) - imageItem?.addGestureRecognizer(tapGesture) + buttonMenu.setImage(UIImage.init(named: "shareMenu")!.image(color: NCBrandColor.shared.customer, size: 24), for: .normal) labelQuickStatus.textColor = NCBrandColor.shared.customer - imageDownArrow.image = utility.loadImage(named: "arrowtriangle.down.circle", colors: [NCBrandColor.shared.customer]) + imageDownArrow.image = UIImage(named: "downArrow")?.imageColor(NCBrandColor.shared.customer) + switchCanEdit.transform = CGAffineTransform(scaleX: 0.75, y: 0.75) + switchCanEdit.onTintColor = NCBrandColor.shared.brandElement } @objc func tapAvatarImage(_ sender: UITapGestureRecognizer) { @@ -154,43 +159,14 @@ class NCSearchUserDropDownCell: DropDownCell, NCCellProtocol { func setupCell(sharee: NKSharee, session: NCSession.Session) { let utility = NCUtility() - imageItem.image = NCShareCommon().getImageShareType(shareType: sharee.shareType) - imageShareeType.image = NCShareCommon().getImageShareType(shareType: sharee.shareType) + imageShareeType.image = NCShareCommon().getImageShareType(shareType: sharee.shareType, isDropDown: true) let status = utility.getUserStatus(userIcon: sharee.userIcon, userStatus: sharee.userStatus, userMessage: sharee.userMessage) - - if let statusImage = status.statusImage { - imageStatus.image = statusImage - imageStatus.makeCircularBackground(withColor: .systemBackground) - } - + imageStatus.image = status.onlineStatus self.status.text = status.statusMessage if self.status.text?.count ?? 0 > 0 { centerTitle.constant = -5 } else { centerTitle.constant = 0 } - - imageItem.image = utility.loadUserImage(for: sharee.shareWith, displayName: nil, urlBase: session.urlBase) - - let fileName = NCSession.shared.getFileName(urlBase: session.urlBase, user: sharee.shareWith) - let results = NCManageDatabase.shared.getImageAvatarLoaded(fileName: fileName) - - if results.image == nil { - let etag = NCManageDatabase.shared.getTableAvatar(fileName: fileName)?.etag - - NextcloudKit.shared.downloadAvatar( - user: sharee.shareWith, - fileNameLocalPath: NCUtilityFileSystem().directoryUserData + "/" + fileName, - sizeImage: NCGlobal.shared.avatarSize, - avatarSizeRounded: NCGlobal.shared.avatarSizeRounded, - etag: etag, account: session.account) { _, imageAvatar, _, etag, _, error in - if error == .success, let etag = etag, let imageAvatar = imageAvatar { - NCManageDatabase.shared.addAvatar(fileName: fileName, etag: etag) - self.imageItem.image = imageAvatar - } else if error.errorCode == NCGlobal.shared.errorNotModified, let imageAvatar = NCManageDatabase.shared.setAvatarLoaded(fileName: fileName) { - self.imageItem.image = imageAvatar - } - } - } } } diff --git a/iOSClient/Share/NCShareUserCell.xib b/iOSClient/Share/NCShareUserCell.xib index df97e61950..9068e45ea3 100755 --- a/iOSClient/Share/NCShareUserCell.xib +++ b/iOSClient/Share/NCShareUserCell.xib @@ -1,30 +1,27 @@ - + - - - + - - + + - - + + - - + + - - + + - @@ -35,124 +32,128 @@ - - + - - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - + diff --git a/iOSClient/Share/ShareDownloadLimitNetwork.swift b/iOSClient/Share/ShareDownloadLimitNetwork.swift new file mode 100644 index 0000000000..9fadc08515 --- /dev/null +++ b/iOSClient/Share/ShareDownloadLimitNetwork.swift @@ -0,0 +1,146 @@ +// +// ShareDownloadLimitNetwork.swift +// Nextcloud +// +// Created by A118830248 on 11/11/21. +// Copyright © 2021 Marino Faggiana. All rights reserved. +// + +import Foundation +import SwiftyJSON +import NextcloudKit +import Alamofire + +class NMCCommunication: NSObject, XMLParserDelegate { + + public static let shared: NMCCommunication = { + let instance = NMCCommunication() + return instance + }() + + var message = "" + var foundCharacters = ""; + var downloadLimit = DownloadLimit() + private lazy var appDelegate = UIApplication.shared.delegate as? AppDelegate + + func getDownloadLimit(token: String, completion: @escaping (_ downloadLimit: DownloadLimit?, _ errorDescription: String) -> Void) { + let baseUrl = appDelegate?.urlBase ?? "" // NCBrandOptions.shared.loginBaseUrl + let endPoint = "/ocs/v2.php/apps/files_downloadlimit/\(token)/limit" + let path = baseUrl+endPoint + do { + var urlRequest = try URLRequest(url: URL(string: path)!, method: .get) + urlRequest.addValue("true", forHTTPHeaderField: "OCS-APIREQUEST") + + let sessionConfiguration = URLSessionConfiguration.default + let urlSession = URLSession(configuration: sessionConfiguration) + + let task = urlSession.dataTask(with: urlRequest) { [self] (data, response, error) in + guard error == nil else { + completion(nil, error?.localizedDescription ?? "") + return + } + + if let httpResponse = response as? HTTPURLResponse { + let statusCode = httpResponse.statusCode + print("url: \(String(describing: httpResponse.url))\nStatus Code: \(statusCode)") + if httpResponse.statusCode == 200 { + let parser = XMLParser(data: data!) + parser.delegate = self + parser.parse() + completion(self.downloadLimit, self.message) + } else { + completion(nil, "Invalid Response code: \(statusCode)") + } + } else { + completion(nil, error?.localizedDescription ?? "Invalid Response") + } + } + task.resume() + } catch { + completion(nil, error.localizedDescription) + } + } + + func setDownloadLimit(deleteLimit: Bool, limit: String, token: String, completion: @escaping (_ success: Bool, _ errorDescription: String) -> Void) { + let baseUrl = appDelegate?.urlBase ?? "" //NCBrandOptions.shared.loginBaseUrl + let endPoint = "/ocs/v2.php/apps/files_downloadlimit/\(token)/limit" + let path = baseUrl+endPoint + do { + + let method = deleteLimit ? HTTPMethod.delete : .put + var urlRequest = try URLRequest(url: URL(string: path)!, method: method) + + urlRequest.addValue("true", forHTTPHeaderField: "OCS-APIREQUEST") + urlRequest.addValue(authorizationToken(), forHTTPHeaderField: "Authorization") + urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type") + + let parameters = ["token": token, "limit": limit] + + let encoder = JSONEncoder() + let jsonData = try encoder.encode(parameters) + urlRequest.httpBody = jsonData + + let sessionConfiguration = URLSessionConfiguration.default + let urlSession = URLSession(configuration: sessionConfiguration) + + let task = urlSession.dataTask(with: urlRequest) { (data, response, error) in + guard error == nil else { + completion(false, error?.localizedDescription ?? "") + return + } + + if let httpResponse = response as? HTTPURLResponse { + let statusCode = httpResponse.statusCode + print("url: \(String(describing: httpResponse.url))\nStatus Code: \(statusCode)") + if httpResponse.statusCode == 200 { + completion(true, error?.localizedDescription ?? "") + } else { + completion(false, "Invalid Response code: \(statusCode)") + } + } else { + completion(false, error?.localizedDescription ?? "Invalid Response") + } + } + task.resume() + } catch { + completion(false, error.localizedDescription) + } + } + + public func authorizationToken() -> String { + let accountDetails = NCManageDatabase.shared.getAllAccount().first + let password = NCKeychain().getPassword(account: accountDetails?.account ?? "") + let username = accountDetails?.user ?? "" + let credential = Data("\(username):\(password)".utf8).base64EncodedString() + return ("Basic \(credential)") + } + + + // MARK:- XML Parser Delegate + public func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) { + + } + public func parser(_ parser: XMLParser, foundCharacters string: String) { + self.foundCharacters += string; + } + + public func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { + if elementName == "limit" { + let limit = self.foundCharacters.replacingOccurrences(of: "\n", with: "") + self.downloadLimit.limit = Int(limit.trimmingCharacters(in: .whitespaces)) + } + if elementName == "count" { + let count = self.foundCharacters.replacingOccurrences(of: "\n", with: "") + self.downloadLimit.count = Int(count.trimmingCharacters(in: .whitespaces)) + } + if elementName == "message"{ + self.message = self.foundCharacters + } + self.foundCharacters = "" + } +} + +struct DownloadLimit: Codable { + var limit: Int? + var count: Int? +} diff --git a/iOSClient/Utility/NCUtility.swift b/iOSClient/Utility/NCUtility.swift index cad1408fa8..5352b6feef 100644 --- a/iOSClient/Utility/NCUtility.swift +++ b/iOSClient/Utility/NCUtility.swift @@ -286,4 +286,11 @@ final class NCUtility: NSObject, Sendable { } return height } + + func isValidEmail(_ email: String) -> Bool { + + let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}" + let emailPred = NSPredicate(format:"SELF MATCHES %@", emailRegEx) + return emailPred.evaluate(with: email) + } } From bf5bf0c98a732fd2a55da3285152677c5a812332 Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Mon, 26 Aug 2024 11:28:46 +0530 Subject: [PATCH 2/4] NMC 1992 - Sharing changes after NC release 5.5.4 --- iOSClient/Activity/NCActivity.swift | 2 +- iOSClient/Menu/NCShare+Menu.swift | 7 +-- iOSClient/Networking/NCService.swift | 7 --- .../Advanced/NCShareAdvancePermission.swift | 58 ++++++++++--------- iOSClient/Share/NCShare.swift | 8 +-- iOSClient/Share/NCShareCommon.swift | 2 +- iOSClient/Share/NCShareHeader.swift | 8 +-- iOSClient/Share/NCShareLinkCell.swift | 9 +-- iOSClient/Share/NCSharePaging.swift | 6 +- iOSClient/Share/NCShareUserCell.swift | 16 ++--- 10 files changed, 59 insertions(+), 64 deletions(-) diff --git a/iOSClient/Activity/NCActivity.swift b/iOSClient/Activity/NCActivity.swift index 8e59f3bd96..d72bc40abf 100644 --- a/iOSClient/Activity/NCActivity.swift +++ b/iOSClient/Activity/NCActivity.swift @@ -32,7 +32,7 @@ class NCActivity: UIViewController, NCSharePagingContent { @IBOutlet weak var tableView: UITableView! var commentView: NCActivityCommentView? - var textField: UIView? { commentView?.newCommentField } + var textField: UITextField? { commentView?.newCommentField } var height: CGFloat = 0 var metadata: tableMetadata? var showComments: Bool = false diff --git a/iOSClient/Menu/NCShare+Menu.swift b/iOSClient/Menu/NCShare+Menu.swift index 6de4cc8444..882e49968e 100644 --- a/iOSClient/Menu/NCShare+Menu.swift +++ b/iOSClient/Menu/NCShare+Menu.swift @@ -118,7 +118,7 @@ extension NCShare { NCMenuAction( title: NSLocalizedString("_share_read_only_", comment: ""), icon: UIImage(), - selected: tableShare.permissions == (NCGlobal.shared.permissionReadShare + NCGlobal.shared.permissionShareShare) || tableShare.permissions == NCGlobal.shared.permissionReadShare, + selected: tableShare.permissions == (permissions.permissionReadShare + permissions.permissionShareShare) || tableShare.permissions == permissions.permissionReadShare, on: false, action: { _ in let canShare = permissions.isPermissionToCanShare(tableShare.permissions) @@ -147,12 +147,11 @@ extension NCShare { actions.append( NCMenuAction( title: NSLocalizedString("_share_file_drop_", comment: ""), - icon: tableShare.permissions == NCGlobal.shared.permissionCreateShare ? UIImage(named: "success")?.image(color: NCBrandColor.shared.customer, size: 25.0) ?? UIImage() : UIImage(), + icon: tableShare.permissions == permissions.permissionCreateShare ? UIImage(named: "success")?.image(color: NCBrandColor.shared.customer, size: 25.0) ?? UIImage() : UIImage(), selected: false, on: false, action: { menuAction in - let permissions = NCGlobal.shared.permissionCreateShare - self.updateSharePermissions(share: tableShare, permissions: permissions) + self.updateSharePermissions(share: tableShare, permissions: permissions.permissionCreateShare) } ) ) diff --git a/iOSClient/Networking/NCService.swift b/iOSClient/Networking/NCService.swift index 90d82f906c..3a85b4debb 100644 --- a/iOSClient/Networking/NCService.swift +++ b/iOSClient/Networking/NCService.swift @@ -183,13 +183,6 @@ class NCService: NSObject { if NCBrandColor.shared.settingThemingColor(account: account) { NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterChangeTheming, userInfo: ["account": account]) } - - // Sharing & Comments - if !NCGlobal.shared.capabilityFileSharingApiEnabled && !NCGlobal.shared.capabilityFilesComments && NCGlobal.shared.capabilityActivity.isEmpty { - self.appDelegate.disableSharesView = true - } else { - self.appDelegate.disableSharesView = false - } // File Sharing if NCGlobal.shared.capabilityFileSharingApiEnabled { diff --git a/iOSClient/Share/Advanced/NCShareAdvancePermission.swift b/iOSClient/Share/Advanced/NCShareAdvancePermission.swift index a94116be1d..bed707e100 100644 --- a/iOSClient/Share/Advanced/NCShareAdvancePermission.swift +++ b/iOSClient/Share/Advanced/NCShareAdvancePermission.swift @@ -25,6 +25,7 @@ import UIKit import NextcloudKit import SVGKit import CloudKit +import XLForm class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelegate, NCShareDetail { func dismissShareAdvanceView(shouldSave: Bool) { @@ -171,7 +172,7 @@ class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelega } func setupHeaderView() { - guard let headerView = (Bundle.main.loadNibNamed("NCShareHeader", owner: self, options: nil)?.first as? NCShareHeader) else { return } + guard let headerView = (Bundle.main.loadNibNamed("NCShareAdvancePermissionHeader", owner: self, options: nil)?.first as? NCShareAdvancePermissionHeader) else { return } headerView.setupUI(with: metadata) headerView.ocId = metadata.ocId headerView.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 190) @@ -185,7 +186,7 @@ class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelega let form : XLFormDescriptor var section : XLFormSectionDescriptor var row : XLFormRowDescriptor - + let permissions = NCPermissions() form = XLFormDescriptor(title: "Other Cells") //Sharing @@ -209,12 +210,12 @@ class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelega row.cellConfig["titleLabel.text"] = NSLocalizedString("_share_read_only_", comment: "") row.height = 44 - if let permission = self.permission, !CCUtility.isAnyPermission(toEdit: permission), permission != NCGlobal.shared.permissionCreateShare { + if let permission = self.permission, !permissions.isAnyPermissionToEdit(permission), permission != permissions.permissionCreateShare { row.cellConfig["imageCheck.image"] = UIImage(named: "success")!.image(color: NCBrandColor.shared.customer, size: 25.0) } if isNewShare { row.cellConfig["imageCheck.image"] = UIImage(named: "success")!.image(color: NCBrandColor.shared.customer, size: 25.0) - self.permission = NCGlobal.shared.permissionReadShare + self.permission = permissions.permissionReadShare } section.addFormRow(row) @@ -225,7 +226,7 @@ class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelega row.cellConfig["titleLabel.text"] = NSLocalizedString("_share_allow_editing_", comment: "") row.height = 44 if let permission = self.permission { - if CCUtility.isAnyPermission(toEdit: permission), permission != NCGlobal.shared.permissionCreateShare { + if permissions.isAnyPermissionToEdit(permission), permission != permissions.permissionCreateShare { row.cellConfig["imageCheck.image"] = UIImage(named: "success")!.image(color: NCBrandColor.shared.customer, size: 25.0) } } @@ -247,7 +248,7 @@ class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelega XLFormViewController.cellClassesForRowDescriptorTypes()["kNMCFilePermissionCell"] = NCFilePermissionCell.self row = XLFormRowDescriptor(tag: "NCFilePermissionCellFileDrop", rowType: "kNMCFilePermissionCell", title: NSLocalizedString("_PERMISSIONS_", comment: "")) row.cellConfig["titleLabel.text"] = NSLocalizedString("_share_file_drop_", comment: "") - if self.permission == NCGlobal.shared.permissionCreateShare { + if self.permission == permissions.permissionCreateShare { row.cellConfig["imageCheck.image"] = UIImage(named: "success")!.image(color: NCBrandColor.shared.customer, size: 25.0) } row.height = 44 @@ -476,11 +477,11 @@ class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelega override func didSelectFormRow(_ formRow: XLFormRowDescriptor!) { guard let metadata = self.metadata else { return } - + let permissions = NCPermissions() switch formRow.tag { case "NCFilePermissionCellRead": - let value = CCUtility.getPermissionsValue(byCanEdit: false, andCanCreate: false, andCanChange: false, andCanDelete: false, andCanShare: canReshareTheShare(), andIsFolder: metadata.directory) + let value = permissions.getPermission(canEdit: false, canCreate: false, canChange: false, canDelete: false, canShare: canReshareTheShare(), isDirectory: metadata.directory) self.permission = value // self.permissions = "RDNVCK" metadata.permissions = "RDNVCK" @@ -497,7 +498,7 @@ class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelega self.reloadForm() break case "kNMCFilePermissionCellEditing": - let value = CCUtility.getPermissionsValue(byCanEdit: true, andCanCreate: true, andCanChange: true, andCanDelete: true, andCanShare: canReshareTheShare(), andIsFolder: metadata.directory) + let value = permissions.getPermission(canEdit: true, canCreate: true, canChange: true, canDelete: true, canShare: canReshareTheShare(), isDirectory: metadata.directory) self.permission = value // self.permissions = "RGDNV" metadata.permissions = "RGDNV" @@ -513,7 +514,7 @@ class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelega self.reloadForm() break case "NCFilePermissionCellFileDrop": - self.permission = NCGlobal.shared.permissionCreateShare + self.permission = permissions.permissionCreateShare // self.permissions = "RGDNVCK" metadata.permissions = "RGDNVCK" if let row : XLFormRowDescriptor = self.form.formRow(withTag: "NCFilePermissionCellRead") { @@ -534,7 +535,7 @@ class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelega func canReshareTheShare() -> Bool { if let permissionValue = self.permission { - let canReshare = CCUtility.isPermission(toCanShare: permissionValue) + let canReshare = NCPermissions().isPermissionToCanShare(permissionValue) return canReshare } else { return false @@ -542,6 +543,7 @@ class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelega } override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { + let permissions = NCPermissions() if let advancePermissionHeaderRow: XLFormRowDescriptor = self.form.formRow(withTag: "NCFilePermissionCellAdvanceTxt") { if let advancePermissionHeaderRowIndexPath = form.indexPath(ofFormRow: advancePermissionHeaderRow), indexPath == advancePermissionHeaderRowIndexPath { let cell = cell as? NCFilePermissionCell @@ -555,7 +557,7 @@ class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelega let cell = cell as? NCFilePermissionEditCell // Can reshare (file) if let permissionValue = self.permission { - let canReshare = CCUtility.isPermission(toCanShare: permissionValue) + let canReshare = permissions.isPermissionToCanShare(permissionValue) cell?.switchControl.isOn = canReshare } else { //new share @@ -568,9 +570,9 @@ class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelega if let hideDownloadRowIndexPath = form.indexPath(ofFormRow: hideDownloadRow), indexPath == hideDownloadRowIndexPath { let cell = cell as? NCFilePermissionEditCell cell?.switchControl.isOn = oldTableShare?.hideDownload ?? false - cell?.titleLabel.isEnabled = !(self.permission == NCGlobal.shared.permissionCreateShare) - cell?.switchControl.isEnabled = !(self.permission == NCGlobal.shared.permissionCreateShare) - cell?.isUserInteractionEnabled = !(self.permission == NCGlobal.shared.permissionCreateShare) + cell?.titleLabel.isEnabled = !(self.permission == permissions.permissionCreateShare) + cell?.switchControl.isEnabled = !(self.permission == permissions.permissionCreateShare) +// cell?.isUserInteractionEnabled = !(self.permission == permissions.permissionCreateShare) } // set password @@ -724,8 +726,8 @@ class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelega } // EDITORS - let editors = NCUtility().isDirectEditing(account: metadata.account, contentType: metadata.contentType) - let availableRichDocument = NCUtility().isRichDocument(metadata) + let editors = NCUtility().editorsDirectEditing(account: metadata.account, contentType: metadata.contentType) + let availableRichDocument = NCUtility().isTypeFileRichDocument(metadata) // RichDocument: Collabora return (availableRichDocument && editors.count == 0) @@ -764,31 +766,31 @@ class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelega } func canReshareValueChanged(isOn: Bool) { - + let permissions = NCPermissions() guard let oldTableShare = oldTableShare, let permission = self.permission else { - self.permission = isOn ? (self.permission ?? 0) + NCGlobal.shared.permissionShareShare : ((self.permission ?? 0) - NCGlobal.shared.permissionShareShare) + self.permission = isOn ? (self.permission ?? 0) + permissions.permissionShareShare : ((self.permission ?? 0) - permissions.permissionShareShare) return } - let canEdit = CCUtility.isAnyPermission(toEdit: permission) - let canCreate = CCUtility.isPermission(toCanCreate: permission) - let canChange = CCUtility.isPermission(toCanChange: permission) - let canDelete = CCUtility.isPermission(toCanDelete: permission) + let canEdit = permissions.isAnyPermissionToEdit(permission) + let canCreate = permissions.isPermissionToCanCreate(permission) + let canChange = permissions.isPermissionToCanChange(permission) + let canDelete = permissions.isPermissionToCanDelete(permission) if metadata.directory { - self.permission = CCUtility.getPermissionsValue(byCanEdit: canEdit, andCanCreate: canCreate, andCanChange: canChange, andCanDelete: canDelete, andCanShare: isOn, andIsFolder: metadata.directory) + self.permission = permissions.getPermission(canEdit: canEdit, canCreate: canCreate, canChange: canChange, canDelete: canDelete, canShare: isOn, isDirectory: metadata.directory) } else { if isOn { if canEdit { - self.permission = CCUtility.getPermissionsValue(byCanEdit: true, andCanCreate: true, andCanChange: true, andCanDelete: true, andCanShare: isOn, andIsFolder: metadata.directory) + self.permission = permissions.getPermission(canEdit: true, canCreate: true, canChange: true, canDelete: true, canShare: isOn, isDirectory: metadata.directory) } else { - self.permission = CCUtility.getPermissionsValue(byCanEdit: false, andCanCreate: false, andCanChange: false, andCanDelete: false, andCanShare: isOn, andIsFolder: metadata.directory) + self.permission = permissions.getPermission(canEdit: false, canCreate: false, canChange: false, canDelete: false, canShare: isOn, isDirectory: metadata.directory) } } else { if canEdit { - self.permission = CCUtility.getPermissionsValue(byCanEdit: true, andCanCreate: true, andCanChange: true, andCanDelete: true, andCanShare: isOn, andIsFolder: metadata.directory) + self.permission = permissions.getPermission(canEdit: true, canCreate: true, canChange: true, canDelete: true, canShare: isOn, isDirectory: metadata.directory) } else { - self.permission = CCUtility.getPermissionsValue(byCanEdit: false, andCanCreate: false, andCanChange: false, andCanDelete: false, andCanShare: isOn, andIsFolder: metadata.directory) + self.permission = permissions.getPermission(canEdit: false, canCreate: false, canChange: false, canDelete: false, canShare: isOn, isDirectory: metadata.directory) } } } diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift index d0ac699b42..d13320f6bf 100644 --- a/iOSClient/Share/NCShare.swift +++ b/iOSClient/Share/NCShare.swift @@ -342,8 +342,8 @@ extension NCShare: NCShareNetworkingDelegate { } // EDITORS - let editors = utility.isDirectEditing(account: metadata.account, contentType: metadata.contentType) - let availableRichDocument = utility.isRichDocument(metadata) + let editors = utility.editorsDirectEditing(account: metadata.account, contentType: metadata.contentType) + let availableRichDocument = utility.isTypeFileRichDocument(metadata) // RichDocument: Collabora return (availableRichDocument && editors.count == 0) @@ -473,9 +473,9 @@ extension NCShare: UITableViewDataSource { headerView.fileName.text = metadata?.fileNameView headerView.fileName.textColor = NCBrandColor.shared.label if metadata!.favorite { - headerView.favorite.setImage(utility.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite, size: 24), for: .normal) + headerView.favorite.setImage(utility.loadImage(named: "star.fill", colors: [NCBrandColor.shared.yellowFavorite], size: 24), for: .normal) } else { - headerView.favorite.setImage(utility.loadImage(named: "star.fill", color: NCBrandColor.shared.textInfo, size: 24), for: .normal) + headerView.favorite.setImage(utility.loadImage(named: "star.fill", colors: [NCBrandColor.shared.textInfo], size: 24), for: .normal) } headerView.info.text = utilityFileSystem.transformedSize(metadata!.size) + ", " + utility.dateDiff(metadata!.date as Date) return headerView diff --git a/iOSClient/Share/NCShareCommon.swift b/iOSClient/Share/NCShareCommon.swift index 73d9029728..a0e6dc4bd7 100644 --- a/iOSClient/Share/NCShareCommon.swift +++ b/iOSClient/Share/NCShareCommon.swift @@ -137,6 +137,6 @@ class NCShareCommon: NSObject { } func canReshare(withPermission permission: String) -> Bool { - return permission.contains(NCGlobal.shared.permissionCanShare) + return permission.contains(NCPermissions().permissionCanShare) } } diff --git a/iOSClient/Share/NCShareHeader.swift b/iOSClient/Share/NCShareHeader.swift index 749197c7af..5df6fc5c96 100644 --- a/iOSClient/Share/NCShareHeader.swift +++ b/iOSClient/Share/NCShareHeader.swift @@ -56,9 +56,9 @@ class NCShareAdvancePermissionHeader: UIView { fileName.text = metadata.fileNameView fileName.textColor = NCBrandColor.shared.fileFolderName if metadata.favorite { - favorite.setImage(utility.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite, size: 24), for: .normal) + favorite.setImage(utility.loadImage(named: "star.fill", colors: [NCBrandColor.shared.yellowFavorite], size: 24), for: .normal) } else { - favorite.setImage(utility.loadImage(named: "star.fill", color: NCBrandColor.shared.textInfo, size: 24), for: .normal) + favorite.setImage(utility.loadImage(named: "star.fill", colors: [NCBrandColor.shared.textInfo], size: 24), for: .normal) } info.textColor = NCBrandColor.shared.optionItem info.text = utilityFileSystem.transformedSize(metadata.size) + ", " + utility.dateDiff(metadata.date as Date) @@ -70,9 +70,9 @@ class NCShareAdvancePermissionHeader: UIView { if error == .success { guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(metadata.ocId) else { return } if metadata.favorite { - self.favorite.setImage(self.utility.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite, size: 24), for: .normal) + self.favorite.setImage(self.utility.loadImage(named: "star.fill", colors: [NCBrandColor.shared.yellowFavorite], size: 24), for: .normal) } else { - self.favorite.setImage(self.utility.loadImage(named: "star.fill", color: NCBrandColor.shared.textInfo, size: 24), for: .normal) + self.favorite.setImage(self.utility.loadImage(named: "star.fill", colors: [NCBrandColor.shared.textInfo], size: 24), for: .normal) } } else { NCContentPresenter().showError(error: error) diff --git a/iOSClient/Share/NCShareLinkCell.swift b/iOSClient/Share/NCShareLinkCell.swift index 45147a5c56..b80bc59f04 100644 --- a/iOSClient/Share/NCShareLinkCell.swift +++ b/iOSClient/Share/NCShareLinkCell.swift @@ -47,25 +47,26 @@ class NCShareLinkCell: UITableViewCell { override func awakeFromNib() { super.awakeFromNib() - + buttonMenu.contentMode = .scaleAspectFill imageItem.image = UIImage(named: "sharebylink")?.image(color: NCBrandColor.shared.label, size: 30) buttonCopy.setImage(UIImage.init(named: "shareCopy")!.image(color: NCBrandColor.shared.customer, size: 24), for: .normal) - buttonMenu.setImage(UIImage.init(named: "shareMenu")!.image(color: NCBrandColor.shared.customer, size: 24), for: .normal) + buttonMenu.setImage(NCImageCache.images.buttonMore.image(color: NCBrandColor.shared.customer, size: 24), for: .normal) labelQuickStatus.textColor = NCBrandColor.shared.customer } func setupCellUI() { + let permissions = NCPermissions() guard let tableShare = tableShare else { return } contentView.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground labelTitle.textColor = NCBrandColor.shared.label - if tableShare.permissions == NCGlobal.shared.permissionCreateShare { + if tableShare.permissions == permissions.permissionCreateShare { labelQuickStatus.text = NSLocalizedString("_share_file_drop_", comment: "") } else { // Read Only - if CCUtility.isAnyPermission(toEdit: tableShare.permissions) { + if permissions.isAnyPermissionToEdit(tableShare.permissions) { labelQuickStatus.text = NSLocalizedString("_share_editing_", comment: "") } else { labelQuickStatus.text = NSLocalizedString("_share_read_only_", comment: "") diff --git a/iOSClient/Share/NCSharePaging.swift b/iOSClient/Share/NCSharePaging.swift index 28db6c6304..5018cee151 100644 --- a/iOSClient/Share/NCSharePaging.swift +++ b/iOSClient/Share/NCSharePaging.swift @@ -303,7 +303,7 @@ class NCShareHeaderView: UIView { } var canReshare: Bool { guard let metadata = metadata else { return true } - return ((metadata.sharePermissionsCollaborationServices & NCGlobal.shared.permissionShareShare) != 0) + return ((metadata.sharePermissionsCollaborationServices & NCPermissions().permissionShareShare) != 0) } canShareInfoView.isHidden = isCurrentUser labelSharingInfo.isHidden = !isCurrentUser @@ -324,9 +324,9 @@ class NCShareHeaderView: UIView { if error == .success { guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(metadata.ocId) else { return } if metadata.favorite { - self.favorite.setImage(self.utility.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite, size: 24), for: .normal) + self.favorite.setImage(self.utility.loadImage(named: "star.fill", colors: [NCBrandColor.shared.yellowFavorite], size: 24), for: .normal) } else { - self.favorite.setImage(self.utility.loadImage(named: "star.fill", color: NCBrandColor.shared.textInfo, size: 24), for: .normal) + self.favorite.setImage(self.utility.loadImage(named: "star.fill", colors: [NCBrandColor.shared.textInfo], size: 24), for: .normal) } } else { NCContentPresenter().showError(error: error) diff --git a/iOSClient/Share/NCShareUserCell.swift b/iOSClient/Share/NCShareUserCell.swift index 0d6aab6b10..5a232b9cf9 100644 --- a/iOSClient/Share/NCShareUserCell.swift +++ b/iOSClient/Share/NCShareUserCell.swift @@ -56,7 +56,7 @@ class NCShareUserCell: UITableViewCell, NCCellProtocol { return } contentView.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground - + let permissions = NCPermissions() labelTitle.text = tableShare.shareWithDisplayname labelTitle.textColor = NCBrandColor.shared.label isUserInteractionEnabled = true @@ -67,10 +67,10 @@ class NCShareUserCell: UITableViewCell, NCCellProtocol { imageItem.image = NCShareCommon().getImageShareType(shareType: tableShare.shareType) let status = utility.getUserStatus(userIcon: tableShare.userIcon, userStatus: tableShare.userStatus, userMessage: tableShare.userMessage) - imageStatus.image = status.onlineStatus + imageStatus.image = status.statusImage self.status.text = status.statusMessage - if CCUtility.isAnyPermission(toEdit: tableShare.permissions) { + if permissions.isAnyPermissionToEdit(tableShare.permissions) { switchCanEdit.setOn(true, animated: false) } else { switchCanEdit.setOn(false, animated: false) @@ -91,11 +91,11 @@ class NCShareUserCell: UITableViewCell, NCCellProtocol { labelQuickStatus.textColor = NCBrandColor.shared.brand imageDownArrow.image = UIImage(named: "downArrow")?.imageColor(NCBrandColor.shared.brand) - if tableShare.permissions == NCGlobal.shared.permissionCreateShare { + if tableShare.permissions == permissions.permissionCreateShare { labelQuickStatus.text = NSLocalizedString("_share_file_drop_", comment: "") } else { // Read Only - if CCUtility.isAnyPermission(toEdit: tableShare.permissions) { + if permissions.isAnyPermissionToEdit(tableShare.permissions) { labelQuickStatus.text = NSLocalizedString("_share_editing_", comment: "") } else { labelQuickStatus.text = NSLocalizedString("_share_read_only_", comment: "") @@ -105,8 +105,8 @@ class NCShareUserCell: UITableViewCell, NCCellProtocol { override func awakeFromNib() { super.awakeFromNib() - - buttonMenu.setImage(UIImage.init(named: "shareMenu")!.image(color: NCBrandColor.shared.customer, size: 24), for: .normal) + buttonMenu.contentMode = .scaleAspectFill + buttonMenu.setImage(NCImageCache.images.buttonMore.image(color: NCBrandColor.shared.customer, size: 24), for: .normal) labelQuickStatus.textColor = NCBrandColor.shared.customer imageDownArrow.image = UIImage(named: "downArrow")?.imageColor(NCBrandColor.shared.customer) switchCanEdit.transform = CGAffineTransform(scaleX: 0.75, y: 0.75) @@ -161,7 +161,7 @@ class NCSearchUserDropDownCell: DropDownCell, NCCellProtocol { let utility = NCUtility() imageShareeType.image = NCShareCommon().getImageShareType(shareType: sharee.shareType, isDropDown: true) let status = utility.getUserStatus(userIcon: sharee.userIcon, userStatus: sharee.userStatus, userMessage: sharee.userMessage) - imageStatus.image = status.onlineStatus + imageStatus.image = status.statusImage self.status.text = status.statusMessage if self.status.text?.count ?? 0 > 0 { centerTitle.constant = -5 From 3e0264bd42ca1f1f62b152fbefa5e5f4c02cbb22 Mon Sep 17 00:00:00 2001 From: TSI-amrutwaghmare <96108296+TSI-amrutwaghmare@users.noreply.github.com> Date: Mon, 27 Nov 2023 17:19:30 +0530 Subject: [PATCH 3/4] NMC 1997 - Sharing customisation unused changes --- iOSClient/Networking/NCService.swift | 14 ++++++++++ iOSClient/Share/NCShare.swift | 40 +++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/iOSClient/Networking/NCService.swift b/iOSClient/Networking/NCService.swift index 3a85b4debb..008182b439 100644 --- a/iOSClient/Networking/NCService.swift +++ b/iOSClient/Networking/NCService.swift @@ -184,6 +184,20 @@ class NCService: NSObject { NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterChangeTheming, userInfo: ["account": account]) } + // File Sharing + if NCGlobal.shared.capabilityFileSharingApiEnabled { + let home = self.utilityFileSystem.getHomeServer(urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId) + NextcloudKit.shared.readShares(parameters: NKShareParameter()) { account, shares, data, error in + if error == .success { + NCManageDatabase.shared.deleteTableShare(account: account) + if let shares = shares, !shares.isEmpty { + NCManageDatabase.shared.addShare(account: account, home: home, shares: shares) + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource) + } + } + } + } + // File Sharing if NCGlobal.shared.capabilityFileSharingApiEnabled { let home = self.utilityFileSystem.getHomeServer(urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId) diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift index d13320f6bf..e27c9bc34a 100644 --- a/iOSClient/Share/NCShare.swift +++ b/iOSClient/Share/NCShare.swift @@ -151,6 +151,44 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent textField?.layer.borderColor = NCBrandColor.shared.brand.cgColor } + @objc func keyboardWillHide(notification: Notification) { + if view.frame.origin.y != 0 { + self.view.frame.origin.y = 0 + } + textField?.layer.borderColor = NCBrandColor.shared.label.cgColor + } + + @objc func keyboardWillShow(notification: Notification) { + if UIDevice.current.userInterfaceIdiom == .phone { + if (UIScreen.main.bounds.width < 374 || UIDevice.current.orientation.isLandscape) { + if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue { + if view.frame.origin.y == 0 { + self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false) + self.view.frame.origin.y -= keyboardSize.height + } + } + } else if UIScreen.main.bounds.height < 850 { + if view.frame.origin.y == 0 { + self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false) + self.view.frame.origin.y -= 70 + } + } else { + if view.frame.origin.y == 0 { + self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false) + self.view.frame.origin.y -= 40 + } + } + } + + if UIDevice.current.userInterfaceIdiom == .pad, UIDevice.current.orientation.isLandscape { + if view.frame.origin.y == 0 { + self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false) + self.view.frame.origin.y -= 230 + } + } + textField?.layer.borderColor = NCBrandColor.shared.brand.cgColor + } + @objc func keyboardWillHide(notification: Notification) { if view.frame.origin.y != 0 { self.view.frame.origin.y = 0 @@ -230,7 +268,7 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent } func checkEnforcedPassword(shareType: Int, completion: @escaping (String?) -> Void) { - guard NCCapabilities.shared.getCapabilities(account: session.account).capabilityFileSharingPubPasswdEnforced, + guard NCGlobal.shared.capabilityFileSharingPubPasswdEnforced, shareType == shareCommon.SHARE_TYPE_LINK || shareType == shareCommon.SHARE_TYPE_EMAIL else { return completion(nil) } From 9abefb8776694fd3688a637ba7ad174dcddd070f Mon Sep 17 00:00:00 2001 From: harshada-15-tsys Date: Tue, 15 Apr 2025 16:09:15 +0530 Subject: [PATCH 4/4] NMC 1997 - Sharing customisation changes --- Nextcloud.xcodeproj/project.pbxproj | 66 ++++++++++++++++++- iOSClient/Activity/NCActivity.swift | 8 +-- iOSClient/Main/NCActionCenter.swift | 2 +- iOSClient/Menu/NCShare+Menu.swift | 1 + iOSClient/Networking/NCService.swift | 20 ++---- iOSClient/Share/NCShare+Helper.swift | 1 + iOSClient/Share/NCShare.swift | 85 ++++++++++--------------- iOSClient/Share/NCShareCommon.swift | 2 +- iOSClient/Share/NCShareHeader.swift | 10 +-- iOSClient/Share/NCShareLinkCell.swift | 2 +- iOSClient/Share/NCShareLinkCell.xib | 8 ++- iOSClient/Share/NCShareNetworking.swift | 13 +++- iOSClient/Share/NCShareUserCell.swift | 2 +- iOSClient/Utility/NCUtility.swift | 22 +++++-- 14 files changed, 153 insertions(+), 89 deletions(-) diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index 05654d1b07..9c974ee011 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -91,7 +91,23 @@ AFCE353327E4ED1900FEA6C2 /* UIToolbar+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353227E4ED1900FEA6C2 /* UIToolbar+Extension.swift */; }; 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 */; }; + B5E2E6D42DAE52B500AB2EDD /* SharingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E2E6D32DAE52B500AB2EDD /* SharingTest.swift */; }; + B5E2E6D72DAE571200AB2EDD /* PasswordInputField.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5E2E6D62DAE571200AB2EDD /* PasswordInputField.xib */; }; + B5E2E6D82DAE571200AB2EDD /* PasswordInputField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E2E6D52DAE571200AB2EDD /* PasswordInputField.swift */; }; + B5E2E6DD2DAE573B00AB2EDD /* NCFilePermissionEditCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5E2E6DC2DAE573B00AB2EDD /* NCFilePermissionEditCell.xib */; }; + B5E2E6DE2DAE573B00AB2EDD /* NCFilePermissionCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5E2E6DA2DAE573B00AB2EDD /* NCFilePermissionCell.xib */; }; + B5E2E6DF2DAE573B00AB2EDD /* NCFilePermissionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E2E6D92DAE573B00AB2EDD /* NCFilePermissionCell.swift */; }; + B5E2E6E02DAE573B00AB2EDD /* NCFilePermissionEditCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E2E6DB2DAE573B00AB2EDD /* NCFilePermissionEditCell.swift */; }; + B5E2E6E22DAE59CD00AB2EDD /* NCShareAdvancePermissionHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5E2E6E12DAE59CD00AB2EDD /* NCShareAdvancePermissionHeader.xib */; }; + B5E2E6E72DAE59F000AB2EDD /* NCShareHeaderCustomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5E2E6E42DAE59F000AB2EDD /* NCShareHeaderCustomCell.xib */; }; + B5E2E6E82DAE59F000AB2EDD /* NCShareTextInputCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5E2E6E62DAE59F000AB2EDD /* NCShareTextInputCell.xib */; }; + B5E2E6E92DAE59F000AB2EDD /* NCShareTextInputCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E2E6E52DAE59F000AB2EDD /* NCShareTextInputCell.swift */; }; + B5E2E6EA2DAE59F000AB2EDD /* NCShareHeaderCustomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E2E6E32DAE59F000AB2EDD /* NCShareHeaderCustomCell.swift */; }; + B5E2E6ED2DAE66AF00AB2EDD /* NCShareEmailFieldCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5E2E6EC2DAE66AF00AB2EDD /* NCShareEmailFieldCell.xib */; }; + B5E2E6EE2DAE66AF00AB2EDD /* NCShareEmailFieldCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E2E6EB2DAE66AF00AB2EDD /* NCShareEmailFieldCell.swift */; }; + B5E2E6F02DAE6E3F00AB2EDD /* ShareDownloadLimitNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E2E6EF2DAE6E3F00AB2EDD /* ShareDownloadLimitNetwork.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 */; }; @@ -1329,7 +1345,22 @@ AFCE353227E4ED1900FEA6C2 /* UIToolbar+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIToolbar+Extension.swift"; sourceTree = ""; }; 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 = ""; }; + B5E2E6D32DAE52B500AB2EDD /* SharingTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharingTest.swift; sourceTree = ""; }; + B5E2E6D52DAE571200AB2EDD /* PasswordInputField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordInputField.swift; sourceTree = ""; }; + B5E2E6D62DAE571200AB2EDD /* PasswordInputField.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PasswordInputField.xib; sourceTree = ""; }; + B5E2E6D92DAE573B00AB2EDD /* NCFilePermissionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCFilePermissionCell.swift; sourceTree = ""; }; + B5E2E6DA2DAE573B00AB2EDD /* NCFilePermissionCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCFilePermissionCell.xib; sourceTree = ""; }; + B5E2E6DB2DAE573B00AB2EDD /* NCFilePermissionEditCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCFilePermissionEditCell.swift; sourceTree = ""; }; + B5E2E6DC2DAE573B00AB2EDD /* NCFilePermissionEditCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCFilePermissionEditCell.xib; sourceTree = ""; }; + B5E2E6E12DAE59CD00AB2EDD /* NCShareAdvancePermissionHeader.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCShareAdvancePermissionHeader.xib; sourceTree = ""; }; + B5E2E6E32DAE59F000AB2EDD /* NCShareHeaderCustomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareHeaderCustomCell.swift; sourceTree = ""; }; + B5E2E6E42DAE59F000AB2EDD /* NCShareHeaderCustomCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCShareHeaderCustomCell.xib; sourceTree = ""; }; + B5E2E6E52DAE59F000AB2EDD /* NCShareTextInputCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareTextInputCell.swift; sourceTree = ""; }; + B5E2E6E62DAE59F000AB2EDD /* NCShareTextInputCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCShareTextInputCell.xib; sourceTree = ""; }; + B5E2E6EB2DAE66AF00AB2EDD /* NCShareEmailFieldCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareEmailFieldCell.swift; sourceTree = ""; }; + B5E2E6EC2DAE66AF00AB2EDD /* NCShareEmailFieldCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCShareEmailFieldCell.xib; sourceTree = ""; }; + B5E2E6EF2DAE6E3F00AB2EDD /* ShareDownloadLimitNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareDownloadLimitNetwork.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 = ""; }; @@ -2118,6 +2149,8 @@ isa = PBXGroup; children = ( AA52EB452D42AC5A0089C348 /* Placeholder.swift */, + B5E2E6D32DAE52B500AB2EDD /* SharingTest.swift */, + AF8ED1FB2757821000B8DBC4 /* NextcloudUnitTests.swift */, ); path = NextcloudUnitTests; sourceTree = ""; @@ -2145,6 +2178,15 @@ isa = PBXGroup; children = ( AA8D316D2D4123B200FE2775 /* DownloadLimit */, + B5E2E6E32DAE59F000AB2EDD /* NCShareHeaderCustomCell.swift */, + B5E2E6E42DAE59F000AB2EDD /* NCShareHeaderCustomCell.xib */, + B5E2E6E52DAE59F000AB2EDD /* NCShareTextInputCell.swift */, + B5E2E6E62DAE59F000AB2EDD /* NCShareTextInputCell.xib */, + B5E2E6E12DAE59CD00AB2EDD /* NCShareAdvancePermissionHeader.xib */, + B5E2E6D92DAE573B00AB2EDD /* NCFilePermissionCell.swift */, + B5E2E6DA2DAE573B00AB2EDD /* NCFilePermissionCell.xib */, + B5E2E6DB2DAE573B00AB2EDD /* NCFilePermissionEditCell.swift */, + B5E2E6DC2DAE573B00AB2EDD /* NCFilePermissionEditCell.xib */, AF93471627E2361E002537EE /* NCShareAdvancePermission.swift */, AF93471827E2361E002537EE /* NCShareAdvancePermissionFooter.swift */, AF93471427E2361E002537EE /* NCShareAdvancePermissionFooter.xib */, @@ -2377,6 +2419,9 @@ F728CE741BF6322C00E69702 /* Share */ = { isa = PBXGroup; children = ( + B5E2E6EF2DAE6E3F00AB2EDD /* ShareDownloadLimitNetwork.swift */, + B5E2E6EB2DAE66AF00AB2EDD /* NCShareEmailFieldCell.swift */, + B5E2E6EC2DAE66AF00AB2EDD /* NCShareEmailFieldCell.xib */, AF93471327E235EB002537EE /* Advanced */, F724377A2C10B83E00C7C68D /* NCPermissions.swift */, F700510022DF63AC003A3356 /* NCShare.storyboard */, @@ -2502,6 +2547,8 @@ F758B41E212C516300515F55 /* Scan document */ = { isa = PBXGroup; children = ( + B5E2E6D52DAE571200AB2EDD /* PasswordInputField.swift */, + B5E2E6D62DAE571200AB2EDD /* PasswordInputField.xib */, F758B457212C564000515F55 /* NCScan.storyboard */, F758B45D212C569C00515F55 /* NCScanCell.swift */, F758B45F212C56A400515F55 /* NCScan.swift */, @@ -3975,9 +4022,14 @@ F758B45A212C564000515F55 /* NCScan.storyboard in Resources */, F765F73225237E3F00391DBE /* NCRecent.storyboard in Resources */, F78F74342163757000C2ADAD /* NCTrash.storyboard in Resources */, + B5E2E6E72DAE59F000AB2EDD /* NCShareHeaderCustomCell.xib in Resources */, + B5E2E6E82DAE59F000AB2EDD /* NCShareTextInputCell.xib in Resources */, F702F30225EE5D2C008F8E80 /* english.txt in Resources */, F757CC8C29E82D0500F31428 /* NCGroupfolders.storyboard in Resources */, F79A65C32191D90F00FF6DCC /* NCSelect.storyboard in Resources */, + B5E2E6DD2DAE573B00AB2EDD /* NCFilePermissionEditCell.xib in Resources */, + B5E2E6ED2DAE66AF00AB2EDD /* NCShareEmailFieldCell.xib in Resources */, + B5E2E6DE2DAE573B00AB2EDD /* NCFilePermissionCell.xib in Resources */, F7226EDC1EE4089300EBECB1 /* Main.storyboard in Resources */, AF56C1DC2784856200D8BAE2 /* NCActivityCommentView.xib in Resources */, F7F4F10B27ECDBDB008676F9 /* Inconsolata-Light.ttf in Resources */, @@ -4000,9 +4052,11 @@ F723B3DD22FC6D1D00301EFE /* NCShareCommentsCell.xib in Resources */, F78ACD4B21903F850088454D /* NCTrashListCell.xib in Resources */, AF93471927E2361E002537EE /* NCShareAdvancePermissionFooter.xib in Resources */, + B5E2E6E22DAE59CD00AB2EDD /* NCShareAdvancePermissionHeader.xib in Resources */, F7725A61251F33BB00D125E0 /* NCFiles.storyboard in Resources */, F7CBC1232BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.xib in Resources */, F700510122DF63AC003A3356 /* NCShare.storyboard in Resources */, + B5E2E6D72DAE571200AB2EDD /* PasswordInputField.xib in Resources */, F787704F22E7019900F287A9 /* NCShareLinkCell.xib in Resources */, F70753F72542A9C000972D44 /* NCViewerMediaPage.storyboard in Resources */, F7F4F10627ECDBDB008676F9 /* Inconsolata-Medium.ttf in Resources */, @@ -4144,6 +4198,7 @@ AA52EB472D42AC9E0089C348 /* Placeholder.swift in Sources */, F372087D2BAB4C0F006B5430 /* TestConstants.swift in Sources */, F78E2D6C29AF02DB0024D4F3 /* Database.swift in Sources */, + B5E2E6D42DAE52B500AB2EDD /* SharingTest.swift in Sources */, F7817CFE29801A3500FFBC65 /* Data+Extension.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -4565,6 +4620,7 @@ 370D26AF248A3D7A00121797 /* NCCellProtocol.swift in Sources */, F32FADA92D1176E3007035E2 /* UIButton+Extension.swift in Sources */, F768822C2C0DD1E7001CF441 /* NCKeychain.swift in Sources */, + B5E2E6EE2DAE66AF00AB2EDD /* NCShareEmailFieldCell.swift in Sources */, F7BFFD282C8846020029A201 /* NCHud.swift in Sources */, F71CD6CA2930D7B1006C95C1 /* NCApplicationHandle.swift in Sources */, F3754A7D2CF87D600009312E /* SetupPasscodeView.swift in Sources */, @@ -4572,6 +4628,8 @@ F3374A842D64AC31002A38F9 /* AssistantLabelStyle.swift in Sources */, F74BAE172C7E2F4E0028D4FA /* FileProviderDomain.swift in Sources */, F76882402C0DD30B001CF441 /* ViewOnAppear.swift in Sources */, + B5E2E6E92DAE59F000AB2EDD /* NCShareTextInputCell.swift in Sources */, + B5E2E6EA2DAE59F000AB2EDD /* NCShareHeaderCustomCell.swift in Sources */, F790110E21415BF600D7B136 /* NCViewerRichDocument.swift in Sources */, F78ACD4021903CC20088454D /* NCGridCell.swift in Sources */, F7D890752BD25C570050B8A6 /* NCCollectionViewCommon+DragDrop.swift in Sources */, @@ -4709,6 +4767,7 @@ F73EF7BF2B02250B0087E6E9 /* NCManageDatabase+GPS.swift in Sources */, F39A1EE22D0AF8A400DAD522 /* Albums.swift in Sources */, F71F6D072B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */, + B5E2E6D82DAE571200AB2EDD /* PasswordInputField.swift in Sources */, F761856C29E98543006EB3B0 /* NCIntroCollectionViewCell.swift in Sources */, F75DD765290ABB25002EB562 /* Intent.intentdefinition in Sources */, F7D4BF012CA1831900A5E746 /* NCCollectionViewCommonPinchGesture.swift in Sources */, @@ -4770,6 +4829,7 @@ F702F30125EE5D2C008F8E80 /* NYMnemonic.m in Sources */, AF93474E27E3F212002537EE /* NCShareNewUserAddComment.swift in Sources */, F7C30DFD291BD0B80017149B /* NCNetworkingE2EEDelete.swift in Sources */, + B5E2E6F02DAE6E3F00AB2EDD /* ShareDownloadLimitNetwork.swift in Sources */, F76882302C0DD1E7001CF441 /* NCFileNameModel.swift in Sources */, F72FD3B5297ED49A00075D28 /* NCManageDatabase+E2EE.swift in Sources */, F73EF7CF2B0225BA0087E6E9 /* NCManageDatabase+Tag.swift in Sources */, @@ -4798,6 +4858,8 @@ AF93471B27E2361E002537EE /* NCShareAdvancePermission.swift in Sources */, F77BC3ED293E528A005F2B08 /* NCConfigServer.swift in Sources */, F7A560422AE1593700BE8FD6 /* NCOperationSaveLivePhoto.swift in Sources */, + B5E2E6DF2DAE573B00AB2EDD /* NCFilePermissionCell.swift in Sources */, + B5E2E6E02DAE573B00AB2EDD /* NCFilePermissionEditCell.swift in Sources */, F7D1C4AC2C9484FD00EC6D44 /* NCMedia+CollectionViewDataSourcePrefetching.swift in Sources */, F7A03E332D426115007AA677 /* NCMoreNavigationController.swift in Sources */, F7401C152C75E6F300649E87 /* NCCapabilities.swift in Sources */, diff --git a/iOSClient/Activity/NCActivity.swift b/iOSClient/Activity/NCActivity.swift index d72bc40abf..77b26d1175 100644 --- a/iOSClient/Activity/NCActivity.swift +++ b/iOSClient/Activity/NCActivity.swift @@ -54,6 +54,7 @@ class NCActivity: UIViewController, NCSharePagingContent { didSet { tableView.tableFooterView?.isHidden = hasActivityToLoad } } var dateAutomaticFetch: Date? + private let appDelegate = (UIApplication.shared.delegate as? AppDelegate)! var session: NCSession.Session { if account.isEmpty { @@ -103,6 +104,7 @@ class NCActivity: UIViewController, NCSharePagingContent { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) + appDelegate.activeViewController = self navigationController?.setNavigationBarAppearance() fetchAll(isInitial: true) } @@ -131,14 +133,10 @@ class NCActivity: UIViewController, NCSharePagingContent { let label = UILabel() label.font = UIFont.systemFont(ofSize: 15) - label.textColor = NCBrandColor.shared.textColor2 + label.textColor = UIColor.systemGray label.textAlignment = .center label.text = NSLocalizedString("_no_activity_footer_", comment: "") view.addSubview(label) - label.translatesAutoresizingMaskIntoConstraints = false - label.topAnchor.constraint(equalTo: view.topAnchor, constant: 20).isActive = true - label.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true - label.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true return view } diff --git a/iOSClient/Main/NCActionCenter.swift b/iOSClient/Main/NCActionCenter.swift index 7908f0ea3f..525bb6129a 100644 --- a/iOSClient/Main/NCActionCenter.swift +++ b/iOSClient/Main/NCActionCenter.swift @@ -300,7 +300,7 @@ class NCActionCenter: NSObject, UIDocumentInteractionControllerDelegate, NCSelec let serverUrlFileName = metadata.serverUrl + "/" + metadata.fileName var page = page - NCActivityIndicator.shared.start(backgroundView: viewController.view) + DispatchQueue.main.async { NCActivityIndicator.shared.start(backgroundView: viewController.view) } NCNetworking.shared.readFile(serverUrlFileName: serverUrlFileName, account: metadata.account, queue: .main) { account, metadata, error in NCActivityIndicator.shared.stop() diff --git a/iOSClient/Menu/NCShare+Menu.swift b/iOSClient/Menu/NCShare+Menu.swift index 882e49968e..deb3a1ee7d 100644 --- a/iOSClient/Menu/NCShare+Menu.swift +++ b/iOSClient/Menu/NCShare+Menu.swift @@ -28,6 +28,7 @@ import NextcloudKit extension NCShare { func toggleShareMenu(for share: tableShare, sendMail: Bool, folder: Bool, sender: Any) { + let capabilities = NCCapabilities.shared.getCapabilities(account: self.metadata.account) var actions = [NCMenuAction]() if !folder { diff --git a/iOSClient/Networking/NCService.swift b/iOSClient/Networking/NCService.swift index 008182b439..d383d408cc 100644 --- a/iOSClient/Networking/NCService.swift +++ b/iOSClient/Networking/NCService.swift @@ -155,8 +155,11 @@ class NCService: NSObject { } private func requestServerCapabilities(account: String, controller: NCMainTabBarController?) { + let session = NCSession.shared.getSession(account: account) NextcloudKit.shared.getCapabilities(account: account, options: NKRequestOptions(queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)) { account, presponseData, error in guard error == .success, let data = presponseData?.data else { + NCBrandColor.shared.settingThemingColor(account: account) + NCImageCache.shared.createImagesBrandCache() return } @@ -181,26 +184,13 @@ class NCService: NSObject { // Theming if NCBrandColor.shared.settingThemingColor(account: account) { + NCImageCache.shared.createImagesBrandCache() NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterChangeTheming, userInfo: ["account": account]) } // File Sharing if NCGlobal.shared.capabilityFileSharingApiEnabled { - let home = self.utilityFileSystem.getHomeServer(urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId) - NextcloudKit.shared.readShares(parameters: NKShareParameter()) { account, shares, data, error in - if error == .success { - NCManageDatabase.shared.deleteTableShare(account: account) - if let shares = shares, !shares.isEmpty { - NCManageDatabase.shared.addShare(account: account, home: home, shares: shares) - NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource) - } - } - } - } - - // File Sharing - if NCGlobal.shared.capabilityFileSharingApiEnabled { - let home = self.utilityFileSystem.getHomeServer(urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId) + let home = self.utilityFileSystem.getHomeServer(session: session) NextcloudKit.shared.readShares(parameters: NKShareParameter()) { account, shares, data, error in if error == .success { NCManageDatabase.shared.deleteTableShare(account: account) diff --git a/iOSClient/Share/NCShare+Helper.swift b/iOSClient/Share/NCShare+Helper.swift index b08bfa9358..6f98012b78 100644 --- a/iOSClient/Share/NCShare+Helper.swift +++ b/iOSClient/Share/NCShare+Helper.swift @@ -92,6 +92,7 @@ class NCTableShareOptions: NCTableShareable { convenience init(sharee: NKSharee, metadata: tableMetadata, password: String?) { self.init(shareType: sharee.shareType, metadata: metadata, password: password) self.shareWith = sharee.shareWith + self.shareWithDisplayname = sharee.label } static func shareLink(metadata: tableMetadata, password: String?) -> NCTableShareOptions { diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift index e27c9bc34a..fbf79f53ff 100644 --- a/iOSClient/Share/NCShare.swift +++ b/iOSClient/Share/NCShare.swift @@ -117,6 +117,7 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent // MARK: - Notification Center @objc func openShareProfile() { + guard let metadata = metadata else { return } self.showProfileMenu(userId: metadata.ownerId, session: session) } @@ -151,44 +152,6 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent textField?.layer.borderColor = NCBrandColor.shared.brand.cgColor } - @objc func keyboardWillHide(notification: Notification) { - if view.frame.origin.y != 0 { - self.view.frame.origin.y = 0 - } - textField?.layer.borderColor = NCBrandColor.shared.label.cgColor - } - - @objc func keyboardWillShow(notification: Notification) { - if UIDevice.current.userInterfaceIdiom == .phone { - if (UIScreen.main.bounds.width < 374 || UIDevice.current.orientation.isLandscape) { - if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue { - if view.frame.origin.y == 0 { - self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false) - self.view.frame.origin.y -= keyboardSize.height - } - } - } else if UIScreen.main.bounds.height < 850 { - if view.frame.origin.y == 0 { - self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false) - self.view.frame.origin.y -= 70 - } - } else { - if view.frame.origin.y == 0 { - self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false) - self.view.frame.origin.y -= 40 - } - } - } - - if UIDevice.current.userInterfaceIdiom == .pad, UIDevice.current.orientation.isLandscape { - if view.frame.origin.y == 0 { - self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false) - self.view.frame.origin.y -= 230 - } - } - textField?.layer.borderColor = NCBrandColor.shared.brand.cgColor - } - @objc func keyboardWillHide(notification: Notification) { if view.frame.origin.y != 0 { self.view.frame.origin.y = 0 @@ -202,7 +165,9 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent // MARK: - @objc func reloadData() { - shares = self.database.getTableShares(metadata: metadata) + if let metadata = metadata { + shares = self.database.getTableShares(metadata: metadata) + } tableView.reloadData() } @@ -215,14 +180,29 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent } @IBAction func searchFieldDidChange(textField: UITextField) { + NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(searchSharees), object: nil) guard let searchString = textField.text else {return} if searchString.count == 0 { dropDown.hide() } else { - networking?.getSharees(searchString: searchString) +// networking?.getSharees(searchString: searchString) + perform(#selector(searchSharees), with: nil, afterDelay: 0.5) } } + @objc private func searchSharees() { + // https://stackoverflow.com/questions/25471114/how-to-validate-an-e-mail-address-in-swift + func isValidEmail(_ email: String) -> Bool { + + let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}" + let emailPred = NSPredicate(format: "SELF MATCHES %@", emailRegEx) + return emailPred.evaluate(with: email) + } + guard let searchString = textField?.text, !searchString.isEmpty else { return } + if searchString.contains("@"), !isValidEmail(searchString) { return } + networking?.getSharees(searchString: searchString) + } + @IBAction func createLinkClicked(_ sender: Any) { appDelegate?.adjust.trackEvent(TriggerEvent(CreateLink.rawValue)) TealiumHelper.shared.trackEvent(title: "magentacloud-app.sharing.create", data: ["": ""]) @@ -232,7 +212,7 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent @IBAction func touchUpInsideButtonMenu(_ sender: Any) { guard let metadata = metadata else { return } - let isFilesSharingPublicPasswordEnforced = NCGlobal.shared.capabilityFileSharingPubPasswdEnforced + let isFilesSharingPublicPasswordEnforced = NCCapabilities.Capabilities().capabilityFileSharingPubPasswdEnforced let shares = NCManageDatabase.shared.getTableShares(metadata: metadata) if isFilesSharingPublicPasswordEnforced && shares.firstShareLink == nil { @@ -268,7 +248,7 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent } func checkEnforcedPassword(shareType: Int, completion: @escaping (String?) -> Void) { - guard NCGlobal.shared.capabilityFileSharingPubPasswdEnforced, + guard NCCapabilities.Capabilities().capabilityFileSharingPubPasswdEnforced, shareType == shareCommon.SHARE_TYPE_LINK || shareType == shareCommon.SHARE_TYPE_EMAIL else { return completion(nil) } @@ -464,7 +444,7 @@ extension NCShare: UITableViewDataSource { if let cell = tableView.dequeueReusableCell(withIdentifier: "cellUser", for: indexPath) as? NCShareUserCell { cell.tableShare = tableShare cell.delegate = self - cell.setupCellUI(userId: appDelegate.userId) + cell.setupCellUI(userId: session.userId) let isEditingAllowed = shareCommon.isEditingEnabled(isDirectory: directory, fileExtension: metadata?.fileExtension ?? "", shareType: tableShare.shareType) if isEditingAllowed || checkIsCollaboraFile() { cell.btnQuickStatus.isEnabled = true @@ -493,18 +473,23 @@ extension NCShare: UITableViewDataSource { headerView.updateCanReshareUI() - if FileManager.default.fileExists(atPath: utilityFileSystem.getDirectoryProviderStorageIconOcId(metadata?.ocId ?? "", etag: metadata?.etag ?? "")) { - headerView.fullWidthImageView.image = UIImage(contentsOfFile: utilityFileSystem.getDirectoryProviderStorageIconOcId(metadata?.ocId ?? "", etag: metadata?.etag ?? "")) + if let image = NCUtility().getImage(ocId: metadata.ocId, etag: metadata.etag, ext: NCGlobal.shared.previewExt1024) { + headerView.fullWidthImageView.image = image +// headerView.fullWidthImageView.image = UIImage(contentsOfFile: utilityFileSystem.getDirectoryProviderStorageIconOcId(metadata?.ocId ?? "", etag: metadata?.etag ?? "")) headerView.fullWidthImageView.contentMode = .scaleAspectFill headerView.imageView.isHidden = true } else { if metadata?.directory ?? false { - let image = (metadata?.e2eEncrypted ?? false) ? UIImage(named: "folderEncrypted") : UIImage(named: "folder_nmcloud") + let image = (metadata?.e2eEncrypted ?? false) ? NCImageCache.shared.getFolderEncrypted() : NCImageCache.shared.getFolder() headerView.imageView.image = image } else if !(metadata?.iconName.isEmpty ?? false) { - headerView.imageView.image = metadata!.fileExtension == "odg" ? UIImage(named: "file-diagram") : UIImage.init(named: metadata!.iconName) + if let image = UIImage.init(named: metadata!.iconName) { + headerView.imageView.image = metadata!.fileExtension == "odg" ? UIImage(named: "diagram") : image + } else { + headerView.imageView.image = metadata!.fileExtension == "odg" ? UIImage(named: "diagram") : NCUtility().loadImage(named: metadata.iconName, useTypeIconFile: true, account: metadata.account) + } } else { - headerView.imageView.image = UIImage(named: "file") + headerView.imageView.image = NCImageCache.shared.getImageFile() } } @@ -520,10 +505,10 @@ extension NCShare: UITableViewDataSource { } func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat { - return metadata?.ownerId != appDelegate?.userId ? canReshare ? 400 : 350 : 320 + return metadata?.ownerId != session?.userId ? canReshare ? 400 : 350 : 320 } func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - return metadata?.ownerId != appDelegate?.userId ? canReshare ? UITableView.automaticDimension : 350 : 320 + return metadata?.ownerId != session?.userId ? canReshare ? UITableView.automaticDimension : 350 : 320 } } diff --git a/iOSClient/Share/NCShareCommon.swift b/iOSClient/Share/NCShareCommon.swift index a0e6dc4bd7..9b05aea1a1 100644 --- a/iOSClient/Share/NCShareCommon.swift +++ b/iOSClient/Share/NCShareCommon.swift @@ -130,7 +130,7 @@ class NCShareCommon: NSObject { } func isCurrentUserIsFileOwner(fileOwnerId: String) -> Bool { - if let currentUser = NCManageDatabase.shared.getActiveAccount(), currentUser.userId == fileOwnerId { + if let currentUser = NCManageDatabase.shared.getActiveTableAccount(), currentUser.userId == fileOwnerId { return true } return false diff --git a/iOSClient/Share/NCShareHeader.swift b/iOSClient/Share/NCShareHeader.swift index 5df6fc5c96..862c8f7008 100644 --- a/iOSClient/Share/NCShareHeader.swift +++ b/iOSClient/Share/NCShareHeader.swift @@ -38,17 +38,17 @@ class NCShareAdvancePermissionHeader: UIView { fileName.textColor = NCBrandColor.shared.label info.textColor = NCBrandColor.shared.textInfo backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground - if FileManager.default.fileExists(atPath: utilityFileSystem.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) { - fullWidthImageView.image = utility.getImageMetadata(metadata, for: frame.height) + if let image = NCUtility().getImage(ocId: metadata.ocId, etag: metadata.etag, ext: NCGlobal.shared.previewExt1024) { + fullWidthImageView.image = image fullWidthImageView.contentMode = .scaleAspectFill imageView.isHidden = true } else { if metadata.directory { - imageView.image = UIImage.init(named: "folder") + imageView.image = metadata.e2eEncrypted ? NCImageCache.shared.getFolderEncrypted() : NCImageCache.shared.getFolder() } else if !metadata.iconName.isEmpty { - imageView.image = UIImage.init(named: metadata.iconName) + imageView.image = NCUtility().loadImage(named: metadata.iconName, useTypeIconFile: true, account: metadata.account) } else { - imageView.image = UIImage.init(named: "file") + imageView.image = NCImageCache.shared.getImageFile() } } favorite.setNeedsUpdateConstraints() diff --git a/iOSClient/Share/NCShareLinkCell.swift b/iOSClient/Share/NCShareLinkCell.swift index b80bc59f04..d1da18080e 100644 --- a/iOSClient/Share/NCShareLinkCell.swift +++ b/iOSClient/Share/NCShareLinkCell.swift @@ -50,7 +50,7 @@ class NCShareLinkCell: UITableViewCell { buttonMenu.contentMode = .scaleAspectFill imageItem.image = UIImage(named: "sharebylink")?.image(color: NCBrandColor.shared.label, size: 30) buttonCopy.setImage(UIImage.init(named: "shareCopy")!.image(color: NCBrandColor.shared.customer, size: 24), for: .normal) - buttonMenu.setImage(NCImageCache.images.buttonMore.image(color: NCBrandColor.shared.customer, size: 24), for: .normal) + buttonMenu.setImage(UIImage.init(named: "shareMenu")!.image(color: NCBrandColor.shared.customer, size: 24), for: .normal) labelQuickStatus.textColor = NCBrandColor.shared.customer } diff --git a/iOSClient/Share/NCShareLinkCell.xib b/iOSClient/Share/NCShareLinkCell.xib index 25549d22a6..816a741846 100755 --- a/iOSClient/Share/NCShareLinkCell.xib +++ b/iOSClient/Share/NCShareLinkCell.xib @@ -24,7 +24,7 @@ @@ -81,6 +86,7 @@ + diff --git a/iOSClient/Share/NCShareNetworking.swift b/iOSClient/Share/NCShareNetworking.swift index c5fd664e20..1c3f0bb520 100644 --- a/iOSClient/Share/NCShareNetworking.swift +++ b/iOSClient/Share/NCShareNetworking.swift @@ -100,12 +100,15 @@ class NCShareNetworking: NSObject { func createShareLink(password: String?) { NCActivityIndicator.shared.start(backgroundView: view) - let filenamePath = utilityFileSystem.getFileNamePath(metadata.fileName, serverUrl: metadata.serverUrl, urlBase: metadata.urlBase, userId: metadata.userId) - NextcloudKit.shared.createShareLink(path: filenamePath) { [self] account, share, data, error in + let filenamePath = utilityFileSystem.getFileNamePath(metadata.fileName, serverUrl: metadata.serverUrl, session: session) + NextcloudKit.shared.createShareLink(path: filenamePath, account: metadata.account) { [self] account, share, data, error in NCActivityIndicator.shared.stop() if error == .success && share != nil { - let home = utilityFileSystem.getHomeServer(urlBase: self.metadata.urlBase, userId: self.metadata.userId) + let home = self.utilityFileSystem.getHomeServer(session: self.session) NCManageDatabase.shared.addShare(account: self.metadata.account, home:home, shares: [share!]) + if !metadata.contentType.contains("directory") { + AnalyticsHelper.shared.trackEventWithMetadata(eventName: .EVENT__SHARE_FILE ,metadata: metadata) + } } else if error != .success{ NCContentPresenter().showError(error: error) } @@ -138,6 +141,10 @@ class NCShareNetworking: NSObject { } NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUpdateShare, userInfo: ["account": self.metadata.account, "serverUrl": self.metadata.serverUrl]) + + if !self.metadata.contentType.contains("directory") { + AnalyticsHelper.shared.trackEventWithMetadata(eventName: .EVENT__SHARE_FILE ,metadata: self.metadata) + } } else { NCContentPresenter().showError(error: error) } diff --git a/iOSClient/Share/NCShareUserCell.swift b/iOSClient/Share/NCShareUserCell.swift index 5a232b9cf9..8e45bb578a 100644 --- a/iOSClient/Share/NCShareUserCell.swift +++ b/iOSClient/Share/NCShareUserCell.swift @@ -106,7 +106,7 @@ class NCShareUserCell: UITableViewCell, NCCellProtocol { override func awakeFromNib() { super.awakeFromNib() buttonMenu.contentMode = .scaleAspectFill - buttonMenu.setImage(NCImageCache.images.buttonMore.image(color: NCBrandColor.shared.customer, size: 24), for: .normal) + buttonMenu.setImage(UIImage.init(named: "shareMenu")!.image(color: NCBrandColor.shared.customer, size: 24), for: .normal) labelQuickStatus.textColor = NCBrandColor.shared.customer imageDownArrow.image = UIImage(named: "downArrow")?.imageColor(NCBrandColor.shared.customer) switchCanEdit.transform = CGAffineTransform(scaleX: 0.75, y: 0.75) diff --git a/iOSClient/Utility/NCUtility.swift b/iOSClient/Utility/NCUtility.swift index 5352b6feef..18b62eac22 100644 --- a/iOSClient/Utility/NCUtility.swift +++ b/iOSClient/Utility/NCUtility.swift @@ -33,6 +33,20 @@ final class NCUtility: NSObject, Sendable { let utilityFileSystem = NCUtilityFileSystem() let global = NCGlobal.shared + @objc func isSimulatorOrTestFlight() -> Bool { + guard let path = Bundle.main.appStoreReceiptURL?.path else { + return false + } + return path.contains("CoreSimulator") || path.contains("sandboxReceipt") + } + + func isSimulator() -> Bool { + guard let path = Bundle.main.appStoreReceiptURL?.path else { + return false + } + return path.contains("CoreSimulator") + } + func isTypeFileRichDocument(_ metadata: tableMetadata) -> Bool { guard metadata.fileNameView != "." else { return false } let fileExtension = (metadata.fileNameView as NSString).pathExtension @@ -110,11 +124,11 @@ final class NCUtility: NSObject, Sendable { } } - func isQuickLookDisplayable(metadata: tableMetadata) -> Bool { + @objc func isQuickLookDisplayable(metadata: tableMetadata) -> Bool { return true } - func ocIdToFileId(ocId: String?) -> String? { + @objc func ocIdToFileId(ocId: String?) -> String? { guard let ocId = ocId else { return nil } let items = ocId.components(separatedBy: "oc") @@ -277,12 +291,12 @@ final class NCUtility: NSObject, Sendable { return fileName } - func getHeightHeaderEmptyData(view: UIView, portraitOffset: CGFloat, landscapeOffset: CGFloat) -> CGFloat { + func getHeightHeaderEmptyData(view: UIView, portraitOffset: CGFloat, landscapeOffset: CGFloat, isHeaderMenuTransferViewEnabled: Bool = false) -> CGFloat { var height: CGFloat = 0 if UIDevice.current.orientation.isPortrait { height = (view.frame.height / 2) - (view.safeAreaInsets.top / 2) + portraitOffset } else { - height = (view.frame.height / 2) + landscapeOffset + height = (view.frame.height / 2) + landscapeOffset + CGFloat(isHeaderMenuTransferViewEnabled ? 35 : 0) } return height }