From 796ba0e1b5a0316aba2c69af46d2876902cefe77 Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Tue, 6 Jun 2023 21:59:06 +0530 Subject: [PATCH 01/24] nmc 1992 - sharing feature customisation aaded --- Brand/NCBrand.swift | 39 + iOSClient/Data/NCManageDatabase+Share.swift | 7 + .../Extensions/DateFormatter+Extension.swift | 10 + iOSClient/Extensions/UIButton+Extension.swift | 22 + iOSClient/Extensions/UIImage+Extension.swift | 11 + iOSClient/Extensions/UIView+Extension.swift | 22 + .../calender.imageset/Contents.json | 12 + .../calender.imageset/default@500w.pdf | Bin 0 -> 4296 bytes .../downArrow.imageset/Contents.json | 21 + .../downArrow.imageset/downArrow@2x.png | Bin 0 -> 1019 bytes .../email.imageset/Contents.json | 10 +- .../Images.xcassets/email.imageset/mail.pdf | Bin 1230 -> 4036 bytes .../file.imageset/Contents.json | 10 +- .../Images.xcassets/file.imageset/file.pdf | Bin 892 -> 24407 bytes .../rename.imageset/Contents.json | 23 + .../rename.imageset/actionSheetRename.png | Bin 0 -> 667 bytes .../rename.imageset/actionSheetRename@2x.png | Bin 0 -> 1221 bytes .../rename.imageset/actionSheetRename@3x.png | Bin 0 -> 1834 bytes .../shareCopy.imageset/Contents.json | 10 +- .../shareCopy.imageset/shareCopy.pdf | Bin 1306 -> 6098 bytes .../shareTypeEmail.imageset/Contents.json | 10 +- .../shareTypeEmail.pdf | Bin 1110 -> 0 bytes .../shareTypeEmail.imageset/user.pdf | Bin 0 -> 6083 bytes .../shareTypeLink.imageset/Contents.json | 10 +- .../shareTypeLink.imageset/shareTypeLink.pdf | Bin 4341 -> 4581 bytes .../shareTypeUser.imageset/Contents.json | 10 +- .../shareTypeUser.imageset/shareTypeUser.pdf | Bin 1111 -> 4045 bytes .../success.imageset/Contents.json | 23 + .../success.imageset/success.png | Bin 0 -> 587 bytes .../success.imageset/success@2x.png | Bin 0 -> 964 bytes .../success.imageset/success@3x.png | Bin 0 -> 1275 bytes .../trash.imageset/Contents.json | 2 +- .../trash.imageset/default@500w.pdf | Bin 0 -> 4348 bytes .../Images.xcassets/trash.imageset/trash.pdf | Bin 58835 -> 0 bytes .../viewInFolder.imageset/Contents.json | 22 + .../viewInFolder.imageset/viewInFolder-1.pdf | Bin 0 -> 5778 bytes .../viewInFolderDark.pdf | Bin 0 -> 5771 bytes iOSClient/Main/NCActionCenter.swift | 29 +- iOSClient/Menu/NCShare+Menu.swift | 63 +- iOSClient/NCGlobal.swift | 10 +- .../Scan document/PasswordInputField.swift | 72 ++ .../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 | 837 +++++++++++++++--- .../NCShareAdvancePermissionFooter.swift | 33 +- .../NCShareAdvancePermissionFooter.xib | 77 +- .../NCShareAdvancePermissionHeader.swift | 41 +- .../NCShareAdvancePermissionHeader.xib | 81 +- .../Advanced/NCShareHeaderCustomCell.swift | 30 + .../Advanced/NCShareHeaderCustomCell.xib | 42 + .../Advanced/NCShareNewUserAddComment.swift | 111 ++- .../Share/Advanced/NCShareTextInputCell.swift | 151 ++++ .../Share/Advanced/NCShareTextInputCell.xib | 80 ++ iOSClient/Share/NCSearchUserDropDownCell.xib | 8 +- iOSClient/Share/NCShare+Helper.swift | 8 +- iOSClient/Share/NCShare+NCCellDelegate.swift | 5 +- iOSClient/Share/NCShare.storyboard | 277 +++--- iOSClient/Share/NCShare.swift | 378 +++++--- iOSClient/Share/NCShareCommon.swift | 67 +- iOSClient/Share/NCShareEmailFieldCell.swift | 75 ++ iOSClient/Share/NCShareEmailFieldCell.xib | 94 ++ iOSClient/Share/NCShareHeaderView.xib | 243 ++--- iOSClient/Share/NCShareLinkCell.swift | 81 +- iOSClient/Share/NCShareLinkCell.xib | 163 ++-- iOSClient/Share/NCShareNetworking.swift | 33 +- iOSClient/Share/NCSharePaging.swift | 147 +-- .../Share/NCShareSectionHeaderView.swift | 86 ++ iOSClient/Share/NCShareSectionHeaderView.xib | 182 ++++ iOSClient/Share/NCShareUserCell.swift | 95 +- iOSClient/Share/NCShareUserCell.xib | 169 ++-- .../Share/ShareDownloadLimitNetwork.swift | 145 +++ 74 files changed, 3612 insertions(+), 1115 deletions(-) create mode 100644 iOSClient/Extensions/UIButton+Extension.swift create mode 100644 iOSClient/Images.xcassets/calender.imageset/Contents.json create mode 100644 iOSClient/Images.xcassets/calender.imageset/default@500w.pdf create mode 100644 iOSClient/Images.xcassets/downArrow.imageset/Contents.json create mode 100644 iOSClient/Images.xcassets/downArrow.imageset/downArrow@2x.png create mode 100644 iOSClient/Images.xcassets/rename.imageset/Contents.json create mode 100644 iOSClient/Images.xcassets/rename.imageset/actionSheetRename.png create mode 100644 iOSClient/Images.xcassets/rename.imageset/actionSheetRename@2x.png create mode 100644 iOSClient/Images.xcassets/rename.imageset/actionSheetRename@3x.png delete mode 100644 iOSClient/Images.xcassets/shareTypeEmail.imageset/shareTypeEmail.pdf create mode 100644 iOSClient/Images.xcassets/shareTypeEmail.imageset/user.pdf create mode 100644 iOSClient/Images.xcassets/success.imageset/Contents.json create mode 100644 iOSClient/Images.xcassets/success.imageset/success.png create mode 100644 iOSClient/Images.xcassets/success.imageset/success@2x.png create mode 100644 iOSClient/Images.xcassets/success.imageset/success@3x.png create mode 100644 iOSClient/Images.xcassets/trash.imageset/default@500w.pdf delete mode 100644 iOSClient/Images.xcassets/trash.imageset/trash.pdf create mode 100644 iOSClient/Images.xcassets/viewInFolder.imageset/Contents.json create mode 100644 iOSClient/Images.xcassets/viewInFolder.imageset/viewInFolder-1.pdf create mode 100644 iOSClient/Images.xcassets/viewInFolder.imageset/viewInFolderDark.pdf 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/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/NCShareEmailFieldCell.swift create mode 100644 iOSClient/Share/NCShareEmailFieldCell.xib create mode 100644 iOSClient/Share/NCShareSectionHeaderView.swift create mode 100644 iOSClient/Share/NCShareSectionHeaderView.xib create mode 100644 iOSClient/Share/ShareDownloadLimitNetwork.swift diff --git a/Brand/NCBrand.swift b/Brand/NCBrand.swift index b5e4c39a11..328f428402 100755 --- a/Brand/NCBrand.swift +++ b/Brand/NCBrand.swift @@ -196,6 +196,18 @@ class NCBrandColor: NSObject { return UIColor(red: 0.0 / 255.0, green: 199.0 / 255.0, blue: 190.0 / 255.0, alpha: 1.0) } } + + @objc public var iconColor: UIColor{ + if #available(iOS 13.0, *) { + if UITraitCollection.current.userInterfaceStyle == .dark { + return UIColor(displayP3Red: 204.0/255.0, green: 204.0/255.0, blue: 204.0/255.0, alpha: 1.0) + }else { + return UIColor(red: 38.0/255.0, green: 38.0/255.0, blue: 38.0/255.0, alpha: 1.0) + } + } else { + return UIColor(red: 38.0/255.0, green: 38.0/255.0, blue: 38.0/255.0, alpha: 1.0) + } + } override init() { brand = customer @@ -365,4 +377,31 @@ class NCBrandColor: NSObject { let palette3 = mixPalette(steps: steps, color1: blue, color2: red) return palette1 + palette2 + palette3 } + + @objc public var notificationAction: UIColor { + return UIColor(red: 0/255.0, green: 153/255.0, blue: 255/255.0, alpha: 1.0) + } + + @objc public var secondarySystemGroupedBackground: UIColor = UIColor.secondarySystemGroupedBackground + @objc public var label: UIColor = UIColor.label + @objc public var backgroundForm: UIColor = UIColor(red: 244.0/255.0, green: 244.0/255.0, blue: 244.0/255.0, alpha: 1.0) + @objc public let graySoft: UIColor = UIColor(red: 162.0/255.0, green: 162.0/255.0, blue: 162.0/255.0, alpha: 0.5) + @objc public let systemGray4: UIColor = UIColor.systemGray4 + @objc public let systemBackground: UIColor = UIColor.systemBackground + @objc public let textInfo: UIColor = UIColor(red: 153.0/255.0, green: 153.0/255.0, blue: 153.0/255.0, alpha: 1.0) + @objc public let systemGray: UIColor = UIColor.systemGray + @objc public let customerDarkGrey: UIColor = UIColor(red: 38.0/255.0, green: 38.0/255.0, blue: 38.0/255.0, alpha: 1.0) + @objc public var fileFolderName: UIColor = UIColor(displayP3Red: 102.0/255.0, green: 102.0/255.0, blue: 102.0/255.0, alpha: 1.0) + @objc public let optionItem: UIColor = UIColor(red: 178.0/255.0, green: 178.0/255.0, blue: 178.0/255.0, alpha: 1.0) + @objc public var singleTitleColorButton: UIColor = UIColor(red: 25.0/255.0, green: 25.0/255.0, blue: 25.0/255.0, alpha: 1.0) + @objc public var shareCellTitleColor: UIColor = UIColor(displayP3Red: 242.0/255.0, green: 242.0/255.0, blue: 242.0/255.0, alpha: 1.0) + @objc public var gray60: UIColor { + if UITraitCollection.current.userInterfaceStyle == .dark { + return UIColor(red: 178.0/255.0, green: 178.0/255.0, blue: 178.0/255.0, alpha: 1.0) + } else { + return UIColor(red: 102.0/255.0, green: 102.0/255.0, blue: 102.0/255.0, alpha: 1.0) + } + } + @objc public var systemGray2: UIColor = UIColor.systemGray2 + @objc public var shareByEmailTextColor: UIColor = UIColor(displayP3Red: 13.0/255.0, green: 57.0/255.0, blue: 223.0/255.0, alpha: 1.0) } diff --git a/iOSClient/Data/NCManageDatabase+Share.swift b/iOSClient/Data/NCManageDatabase+Share.swift index 63071c9cce..ab64d5e7f1 100644 --- a/iOSClient/Data/NCManageDatabase+Share.swift +++ b/iOSClient/Data/NCManageDatabase+Share.swift @@ -72,6 +72,13 @@ class tableShareV2: Object { override static func primaryKey() -> String { return "primaryKey" } + + func setPermission(value: Int) { + let realm = try! Realm() + try! realm.write { + permissions = value + } + } } extension NCManageDatabase { diff --git a/iOSClient/Extensions/DateFormatter+Extension.swift b/iOSClient/Extensions/DateFormatter+Extension.swift index aa126ce786..ef1060864d 100644 --- a/iOSClient/Extensions/DateFormatter+Extension.swift +++ b/iOSClient/Extensions/DateFormatter+Extension.swift @@ -28,6 +28,16 @@ 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 new file mode 100644 index 0000000000..89c7ed2596 --- /dev/null +++ b/iOSClient/Extensions/UIButton+Extension.swift @@ -0,0 +1,22 @@ +// +// UIButton+Extension.swift +// Nextcloud +// +// Created by A200020526 on 30/05/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +import UIKit + +extension UIButton { + + 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/UIImage+Extension.swift b/iOSClient/Extensions/UIImage+Extension.swift index 23d4b4e259..8c4b87efa7 100644 --- a/iOSClient/Extensions/UIImage+Extension.swift +++ b/iOSClient/Extensions/UIImage+Extension.swift @@ -142,6 +142,17 @@ extension UIImage { return newImage } + func imageColor(_ color: UIColor) -> UIImage { + if #available(iOS 13.0, *) { + return self.withTintColor(color, renderingMode: .alwaysOriginal) + } else { + return UIGraphicsImageRenderer(size: size, format: imageRendererFormat).image { _ in + color.set() + withRenderingMode(.alwaysTemplate).draw(at: .zero) + } + } + } + func isEqualToImage(image: UIImage?) -> Bool { if image == nil { return false } let data1: NSData = self.pngData()! as NSData diff --git a/iOSClient/Extensions/UIView+Extension.swift b/iOSClient/Extensions/UIView+Extension.swift index 52d184e0e2..a938f5cc35 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 @@ -45,4 +50,21 @@ extension UIView { hiddenView.fillSuperview() hiddenView.addSubview(view) } + + 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/Images.xcassets/calender.imageset/Contents.json b/iOSClient/Images.xcassets/calender.imageset/Contents.json new file mode 100644 index 0000000000..8f3e754211 --- /dev/null +++ b/iOSClient/Images.xcassets/calender.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "default@500w.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/calender.imageset/default@500w.pdf b/iOSClient/Images.xcassets/calender.imageset/default@500w.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b451f0a735c6d495fc7eafda221408c4d531a5c2 GIT binary patch literal 4296 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 b|GUdi1-X0Ba{1#!BhYX(7y?nlsDu9pF(+zy literal 0 HcmV?d00001 diff --git a/iOSClient/Images.xcassets/downArrow.imageset/Contents.json b/iOSClient/Images.xcassets/downArrow.imageset/Contents.json new file mode 100644 index 0000000000..81ef9bbb37 --- /dev/null +++ b/iOSClient/Images.xcassets/downArrow.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "downArrow@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/downArrow.imageset/downArrow@2x.png b/iOSClient/Images.xcassets/downArrow.imageset/downArrow@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6da8c3c9c530c8b03389d52c6114cf095efd1080 GIT binary patch literal 1019 zcmeAS@N?(olHy`uVBq!ia0vp^k|4~%1|*NXY)uAIjKx9jP7LeL$-D$|T2doC(|mmy zw18|523AHP24;{FAY@>aVqgWc85q16rQz%#Mh&PMCI*J~Oa>OHnkXO*0v}p-VjqUeM)Vdro78it`#v1?;qcoTe4o^QK$Q6r5Y*T z7rxc*6HY5E@#K+jk@%8)zOubGJv#PKc8hgKLgnPi$1CP+T$7!vRrKBicE)9zeB1h*viraFOnWOaH~Pt$ z+8r_vkGi-D3kGh@m4C7Jqw({vTu1Z|#LKpq2J#l)X+LWvZ&*0z`pLOZAK9Nb@?x)h actAX`XJzQmA`4KaW$<+Mb6Mw<&;$SmHdw#_ literal 0 HcmV?d00001 diff --git a/iOSClient/Images.xcassets/email.imageset/Contents.json b/iOSClient/Images.xcassets/email.imageset/Contents.json index 565a76d806..f8fa0bcc0b 100644 --- a/iOSClient/Images.xcassets/email.imageset/Contents.json +++ b/iOSClient/Images.xcassets/email.imageset/Contents.json @@ -1,15 +1,15 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "mail.pdf" + "filename" : "mail.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { "preserves-vector-representation" : true } -} \ No newline at end of file +} diff --git a/iOSClient/Images.xcassets/email.imageset/mail.pdf b/iOSClient/Images.xcassets/email.imageset/mail.pdf index 33d54d385e8115dc37bc9b589b8d0cc135896dce..60d8261613b7f355286f8fc9acdaef9a93aee213 100644 GIT binary patch literal 4036 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 AQUCw| literal 892 zcmaJ=O=uHA6sET_hz0Rja1>Ho|7JG((^hK0WRntW+LGi}18$Q^vbx!^vlEOW6hXn# zB9@{>^xA{if;SI62$dYXwn_y-?L`owf*^_~-=r~t6dZOL=9~BCec$_dp-DS&T03K) z(AKxFJ4nM6^XV&SWQ4>7b0inIKUNmJ;#MmIh)fDzsOA}fnX9ftAQx9G3oaVLF86Im zGTd*U4O4BH>eLKtVci@$N$GL;ATGrV{||{o5c3O)Lby#O;d&B^l7t7(+bquu43Ue> zFUd023^NkJfdsY{RC}7cKX!0~9Z^<0Gm#5J=eODGt`q(9hv&rXTr!=tPkrF4 zGl%Z7-iP(6d3SO7ed_HcF3x>^^Q^cu9elUf=Z5oSxodW*`e^I2_NxB4yS}m8dpr5! z=kLB_eNNAv&7&*&MD)|W@?iGKpYfH=?fBZx^|j|;db;1O-g@aB8Tj#FePN+z_hUGt z#5B1zW$A5M*&EjwCNW1k9xp+2oe~SM0r%;47u2z7$X<9O3L4IMzw zwbRsjUm7B57VxUbLm4m_%*%FDD;DB##BQ9ab;ns=0>XbO{YE-H@K7E}|g zh$tRJw6(Bhn!1ULxP@sTTP^IjFwKMxc3`?Sybm)ppwSU$48k~cV3q*}{==kjT#pGg nEgAPF19l|Mxx~t2kel?29IJ^^eg@JJvZ2Bnq9_!KPbB^V1iB2P diff --git a/iOSClient/Images.xcassets/rename.imageset/Contents.json b/iOSClient/Images.xcassets/rename.imageset/Contents.json new file mode 100644 index 0000000000..f361ec03e2 --- /dev/null +++ b/iOSClient/Images.xcassets/rename.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "actionSheetRename.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "actionSheetRename@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "actionSheetRename@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/rename.imageset/actionSheetRename.png b/iOSClient/Images.xcassets/rename.imageset/actionSheetRename.png new file mode 100644 index 0000000000000000000000000000000000000000..ff3bf49a82138f28981acfa23f8414a1a2778924 GIT binary patch literal 667 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDq2jfr-`A#WBQ# z_ie~-Z>L0&_xG~-+?upYzH&6{Mf{2diU%EnPIC-FC5!q(I>4p)hpb~a?hmT)8c&Xdpq6>@%-3XmvlNL zm^EqRjDYpmjbH4WzG2GSvfr8;Q&+A0zu;oVnx>jr1|}?y5~rVk?mwa)%sc+w2e35j(%~{qnpO4k|(~58BEvs^(VQQLy`N^pUWT%qAs=qH9@OWjh$z95#k` zADwg}ZS(vy%hgK#1vpraO`NlYMPoyZhKSq>f8Xmh>0J z4|b=hTrhVD+>^E~Qd7HOb^NBNwfS=W=`7g^!cT5i*zC)l79!fulzzifzal1BNMo+w zX{i9;D;y`5aXd*)*!$v-nEH$(O1r0j69_xXm2>#$1bwCN9;>u(yK>xVP8U2Vd@ZD! pUv>6bwc?jvD;*p5aldH#<bec9P^Dsbk=nW5UcPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NGFG)l}RA>e5SxsmYK@`rPO$?Q) z2nqg@OKgg1(AYy&5Uhf|h=S189}pF)6p`A4dJyBGP%W+a1GadmEiL{Yyl4&;ECml@ zdx@4dEmZ``p(O<=+8CS0?`c=o*qPaEcC(iZEZLp!&3oT_^Y-n`#AGToVinMs%Ai>nB};lex$`6Tpoe&U|n5Zt3ZYc>sCe){lg&tlxg`7@YQOy1`z$v z0y!qE%M1hpfpxIh$+Wr%AiWxLAx~;FcK}g0&&|y}!0&2-1CQ|G>J!KaVa*-D*Y-TD z?iE=6;&eLC3S<<)n!W=*pKnVlm7?WLz>M%b#=8J>l{i69(k(y zZCa5hFRhAQ6$s)(bR8mxcw!(QvDs|3)6>%_o?JGVCMkrHxd$)pD;VbKOQ2*{pz3_c zhM-6`=M?h${i{H}TR@&t=d#x1$+?^zNG6l_pl3ZPkkEU5QAuvj9n+70s01Ts0n zs>*0A7P|FwZ#1 ze+Rw|(U0=vw8Rw605;}pV6;nt;ii0&Cq9ZCKxFSD`fh;(FF^jkQ#ZkwoME8@_+Zt7 z{6T@GDTl*xQXr!XEOfx-ay`ck(3uT$DS)N)=}06pr3*uWQpGPZW?~;UEVS2ME7u9< zI*~eOHK&h?KXb-o!vT(Ze@00gP((Ehd^v(aB(UjBE@4<~x@vD%0~CEiJj zjQV9dfatm;Qn;^5BognbB1wJ2!^8B^GQ25rV3FlYq|`&qMw{WRWdxWzGD;ytUM6b# zh`v^j$J2%Fp}gM&r~If;luq0um460h`2gEVTrIGDRX$WW0~i!Roj-!}PA_u5BODI@ zkSn0`AUG;K50Z~ja}OIuxEeFZ@@8NH#LuC8zNA5!QI`}=PEI!C-Y-4t^}9F&H}%qA j&|8Q=Ap(U6sEfca37KeXt`J#?00000NkvXXu0mjfY4sJZ literal 0 HcmV?d00001 diff --git a/iOSClient/Images.xcassets/rename.imageset/actionSheetRename@3x.png b/iOSClient/Images.xcassets/rename.imageset/actionSheetRename@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..27f7dff1cff1d4d35c6fee9e4ca9767c6ad1f7ec GIT binary patch literal 1834 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 TEGhx}!qC9dm`hdF)!z*O%2U{2 diff --git a/iOSClient/Images.xcassets/shareTypeEmail.imageset/Contents.json b/iOSClient/Images.xcassets/shareTypeEmail.imageset/Contents.json index 00298ac4b4..ffff08a617 100644 --- a/iOSClient/Images.xcassets/shareTypeEmail.imageset/Contents.json +++ b/iOSClient/Images.xcassets/shareTypeEmail.imageset/Contents.json @@ -1,15 +1,15 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "shareTypeEmail.pdf" + "filename" : "user.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { "preserves-vector-representation" : true } -} \ No newline at end of file +} diff --git a/iOSClient/Images.xcassets/shareTypeEmail.imageset/shareTypeEmail.pdf b/iOSClient/Images.xcassets/shareTypeEmail.imageset/shareTypeEmail.pdf deleted file mode 100644 index 48b0f832f5a36d18dc4ba683cf64b947cf3ebb4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1110 zcmY!laBpkQ!zW}-e&uR^YwB~SvaI5R)bC9xz`LBqw$$iUFjz}(2((7?dJ$W+_FKplvH z>U{H4@GG&i<4Vm-0Xe}4;S{&boD!g=`ffQu<6Tmd^HWl}^nFtE(n~TFj7<&g>=cSi zfUeEus+f~I$=mOU1CPu1+O9Pd4YvJG{>`!`vaq4!yizmEo%ls}IDOm}ZJx2t{N<+8 zvX`Wab$g!A^V^gq;QVV-+^O`F|CdTlzP{@3p1)O^=gUvC-}~ryxaaKh+iROn9#+=R zzu$VNU#WDb$f`uyLkj|?NIjpl(>^XHEJR#YP;5nRcysou#|(ZROaJt)IKA}<=Q`J_ zs)SzS`;+*?GHi<_t7nFktys(&(Yya&l+}_ulM~D`r?1xas+Je#I?hwo`ueQFwoh>_ z$KH#YB$=L1nVyugN}0*G;MbNJ%>|dv`8wxsG+EW$-ZsZajc+n@|Ep;}D;|kWwk$hU z&-cdqm~>G4({_eFZYOn_&b2d7_RTzI;Kp3g8P;F@iRW@okz|aBq>##jR0VzK#FE6E{B&SaNlZ^IRxkm|2O;7V#Dyj= zh;pzhVDiZ?%_~tbjI^|a= zL>mAFjg2hz42&%;Ef6fAcIW)OlGHq)ZJ<;d1oCYWkc;kJkfBg_Cntiu=j5xP@0VYc zo0x;}Tt!i88kd2BITtXiK!Jjpsj0E4LYe|x%n%p^AfS*37c(>kh9;VrsX3-PGb5lI z(bSoln`4Msm;p0COkGJ)VrEWi5vUvp&a6rWx=ueRKfgo)6yHGadgi6&D}c%hP}~-m TBo>u`ePLl~!KJF|>hA^sk*IkL diff --git a/iOSClient/Images.xcassets/shareTypeEmail.imageset/user.pdf b/iOSClient/Images.xcassets/shareTypeEmail.imageset/user.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6985e202b039b5ad774b8f29253e7eea0ab3703e GIT binary patch literal 6083 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 D@0eu$ literal 0 HcmV?d00001 diff --git a/iOSClient/Images.xcassets/shareTypeLink.imageset/Contents.json b/iOSClient/Images.xcassets/shareTypeLink.imageset/Contents.json index ee5aa2c64b..53055a1b95 100644 --- a/iOSClient/Images.xcassets/shareTypeLink.imageset/Contents.json +++ b/iOSClient/Images.xcassets/shareTypeLink.imageset/Contents.json @@ -1,15 +1,15 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "shareTypeLink.pdf" + "filename" : "shareTypeLink.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { "preserves-vector-representation" : true } -} \ No newline at end of file +} diff --git a/iOSClient/Images.xcassets/shareTypeLink.imageset/shareTypeLink.pdf b/iOSClient/Images.xcassets/shareTypeLink.imageset/shareTypeLink.pdf index d10d218cd12a9823202013c799985ce96363a63f..d2a882d380c7e910330745e423fb768a123fa6d0 100644 GIT binary patch literal 4581 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 G;Qs(txBAck literal 4341 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 diff --git a/iOSClient/Images.xcassets/shareTypeUser.imageset/Contents.json b/iOSClient/Images.xcassets/shareTypeUser.imageset/Contents.json index 874a5b2007..11ca2fc9dd 100644 --- a/iOSClient/Images.xcassets/shareTypeUser.imageset/Contents.json +++ b/iOSClient/Images.xcassets/shareTypeUser.imageset/Contents.json @@ -1,15 +1,15 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "shareTypeUser.pdf" + "filename" : "shareTypeUser.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { "preserves-vector-representation" : true } -} \ No newline at end of file +} diff --git a/iOSClient/Images.xcassets/shareTypeUser.imageset/shareTypeUser.pdf b/iOSClient/Images.xcassets/shareTypeUser.imageset/shareTypeUser.pdf index 03d855dcc4f8b16f227ca4beb6dc1b0ef4797e0d..62d278bb89c39c33e75a940ae8e8baa681a76dbc 100644 GIT binary patch literal 4045 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 ZDL*>Mi%j$Kd!Z5X@+ZI$h?c%K_+M@Y@oE47 literal 1111 zcmY!laBpkQ!zW}-e&uR^YwB~SvaI5R)bC9xz`LBqw$$iUFjz}(2((7?dRz*5`5KplvH z>U{H4@GG&i<4Vm-0Xe}4;S{&boD!g=`ffQu<6Tmd^HWl}^nFtE(n~TFj7^Q~>=cSi zfUeEus+bcS}-etr-;Y0{N#GbW$uy;-Cjm*oDeC_r^{`syRI`O;o_yPTe?)y~pzNV-F8 z-l?RP^LI{6D{}n!Vq@B8@jUMx3I)?U-rqTK_HDe*!o-EQg!6VRKI~f>^1QFDz`@-j ze6Ljmd24z1xz)%Q>9g;d7`@Kly;`Ihy2mcu{MfIoL$ZEH6#Os=-S zR9)rkZ&BafxHu3LH_)Jl#*#52mO?5EQWf-_6H5|v^3#E7B{4mcNHwtL54!zoty~ro|CVFzF&S( zZek9?a}`CYXJDCEJ#3{8Qdi6&-h4zv-2;2^Gg&!@eTB@XI@&q0;sS6#cgp( SVo?d$7Z#S5T&k+B{%!#1QF?X& diff --git a/iOSClient/Images.xcassets/success.imageset/Contents.json b/iOSClient/Images.xcassets/success.imageset/Contents.json new file mode 100644 index 0000000000..858785f7a8 --- /dev/null +++ b/iOSClient/Images.xcassets/success.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "success.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "success@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "success@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/success.imageset/success.png b/iOSClient/Images.xcassets/success.imageset/success.png new file mode 100644 index 0000000000000000000000000000000000000000..b1d2459a4be85c8ee5a26f661f61aeba5a8545f0 GIT binary patch literal 587 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB7>k44ofy`glX(f`xTHpSruq6Z zXaU(A42G$TlC0TWzSWdSpS4N|DZ_xKM`*;Y>%$B+ol zx6=&0jyQ<4nRn`RM?|RfCTw=Sw8Y~f<2SCRh#hYP*X(H)pO`ChP?=+%!iF}LR)wVL zH@Lb}YX48-6*fPaw#hiyBW~hJpL=`$KR$c<3=iAhuaYl}70j92?tD0V(e}Kx+U&?_ zrBhT+TJPEVO!L#eUF)iM#puoVOym)by{>=ApytZOz}))81@lvHvb<%K(^|{rc6p2Z zVS{%E7n(Si8XPGUWjV;*Fy(51u#bo$H=Jna_(AmTo5a|5kz=~;lD`#F7+Vngo z*SE8!@t>Fg+ij=LwnnpP=NIdH&xy_1(|h_lgK_HlWi~0Vml-+FzF9hR(djEa@AS)` znBV*HY%BYWuck@H=Wd%ZDMs*yc)E-5G`-ssygc())~qy_MbDq?-+DwTF^civN!%8j=PV9-3X5l6(7pWp3g5=|+tSeoI*1HGh-*(J%RfwM|v{;q{Kc>p>Ce>FVdQ I&MBb@0Djiw#Q*>R literal 0 HcmV?d00001 diff --git a/iOSClient/Images.xcassets/success.imageset/success@2x.png b/iOSClient/Images.xcassets/success.imageset/success@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9832eda02817e9a73a501c1e9d2e10ad327476a2 GIT binary patch literal 964 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 diff --git a/iOSClient/Images.xcassets/viewInFolder.imageset/Contents.json b/iOSClient/Images.xcassets/viewInFolder.imageset/Contents.json new file mode 100644 index 0000000000..2ea287530d --- /dev/null +++ b/iOSClient/Images.xcassets/viewInFolder.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "filename" : "viewInFolder-1.pdf", + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "viewInFolderDark.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/viewInFolder.imageset/viewInFolder-1.pdf b/iOSClient/Images.xcassets/viewInFolder.imageset/viewInFolder-1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..bb8489ccd90bc7fc08313aec3b149bc7111107f0 GIT binary patch literal 5778 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 C7s~7a literal 0 HcmV?d00001 diff --git a/iOSClient/Images.xcassets/viewInFolder.imageset/viewInFolderDark.pdf b/iOSClient/Images.xcassets/viewInFolder.imageset/viewInFolderDark.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1f59694303aa7750396bbb264d8f5e2840e51fc6 GIT binary patch literal 5771 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 literal 0 HcmV?d00001 diff --git a/iOSClient/Main/NCActionCenter.swift b/iOSClient/Main/NCActionCenter.swift index 9000bb5904..305657e866 100644 --- a/iOSClient/Main/NCActionCenter.swift +++ b/iOSClient/Main/NCActionCenter.swift @@ -252,36 +252,11 @@ 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 NCGlobal.shared.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 14cc2f34fa..00a81a14f5 100644 --- a/iOSClient/Menu/NCShare+Menu.swift +++ b/iOSClient/Menu/NCShare+Menu.swift @@ -25,43 +25,62 @@ import Foundation import NextcloudKit extension NCShare { - func toggleShareMenu(for share: tableShare) { + 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: NCUtility.shared.loadImage(named: "shareAdd"), - action: { _ in - self.makeNewLinkShare() + title: NSLocalizedString("_open_in_", comment: ""), + icon: NCUtility.shared.loadImage(named: "viewInFolder").imageColor(NCBrandColor.shared.brandElement), + action: { menuAction in + NCShareCommon.shared.copyLink(link: share.url, viewController: self, sender: sender) } ) ) } + + actions.append( NCMenuAction( - title: NSLocalizedString("_details_", comment: ""), - icon: NCUtility.shared.loadImage(named: "pencil"), + title: NSLocalizedString("_advance_permissions_", comment: ""), + icon: NCUtility.shared.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.oldTableShare = tableShare(value: share) + advancePermission.oldTableShare = share//tableShare(value: share) advancePermission.metadata = self.metadata navigationController.pushViewController(advancePermission, animated: true) } ) ) - + + if sendMail { + actions.append( + NCMenuAction( + title: NSLocalizedString("_send_new_email_", comment: ""), + icon: NCUtility.shared.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: ""), - icon: NCUtility.shared.loadImage(named: "trash"), + icon: NCUtility.shared.loadImage(named: "trash").imageColor(NCBrandColor.shared.brandElement), action: { _ in Task { if share.shareType != NCShareCommon.shared.SHARE_TYPE_LINK, let metadata = self.metadata, metadata.e2eEncrypted && NCGlobal.shared.capabilityE2EEApiVersion == NCGlobal.shared.e2eeVersionV20 { @@ -90,7 +109,7 @@ extension NCShare { actions.append( NCMenuAction( title: NSLocalizedString("_share_read_only_", comment: ""), - icon: NCUtility.shared.loadImage(named: "eye"), + icon: UIImage(), selected: tableShare.permissions == (NCGlobal.shared.permissionReadShare + NCGlobal.shared.permissionShareShare) || tableShare.permissions == NCGlobal.shared.permissionReadShare, on: false, action: { _ in @@ -104,7 +123,7 @@ extension NCShare { actions.append( NCMenuAction( title: isDirectory ? NSLocalizedString("_share_allow_upload_", comment: "") : NSLocalizedString("_share_editing_", comment: ""), - icon: NCUtility.shared.loadImage(named: "pencil"), + icon: UIImage(), selected: hasUploadPermission(tableShare: tableShare), on: false, action: { _ in @@ -114,7 +133,21 @@ extension NCShare { } ) ) - + + if isDirectory, + NCShareCommon.shared.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 + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterStatusFileDrop, object: tableShare) + } + ) + ) + } self.presentMenu(with: actions) } diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift index f96ed1dc3a..3cfbb9032f 100644 --- a/iOSClient/NCGlobal.swift +++ b/iOSClient/NCGlobal.swift @@ -388,7 +388,15 @@ class NCGlobal: NSObject { 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" + // TIP // let tipNCViewerPDFThumbnail = "tipncviewerpdfthumbnail" diff --git a/iOSClient/Scan document/PasswordInputField.swift b/iOSClient/Scan document/PasswordInputField.swift new file mode 100644 index 0000000000..6f7a9609c7 --- /dev/null +++ b/iOSClient/Scan document/PasswordInputField.swift @@ -0,0 +1,72 @@ +// +// 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 + } + + 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 c24dd276e7..41c7cde505 100644 --- a/iOSClient/Share/Advanced/NCShareAdvancePermission.swift +++ b/iOSClient/Share/Advanced/NCShareAdvancePermission.swift @@ -26,46 +26,39 @@ import NextcloudKit import SVGKit import CloudKit -class NCShareAdvancePermission: UITableViewController, NCShareAdvanceFotterDelegate, NCShareDetail { +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 { - if isNewShare { - let serverUrl = metadata.serverUrl + "/" + metadata.fileName - if share.shareType != NCShareCommon.shared.SHARE_TYPE_LINK, metadata.e2eEncrypted, - NCGlobal.shared.capabilityE2EEApiVersion == NCGlobal.shared.e2eeVersionV20 { - if NCNetworkingE2EE.shared.isInUpload(account: metadata.account, serverUrl: serverUrl) { - let error = NKError(errorCode: NCGlobal.shared.errorE2EEUploadInProgress, errorDescription: NSLocalizedString("_e2e_in_upload_", comment: "")) - return NCContentPresenter.shared.showInfo(error: error) - } - let error = await NCNetworkingE2EE().uploadMetadata(account: metadata.account, serverUrl: serverUrl, userId: metadata.userId, addUserId: share.shareWith, removeUserId: nil) - if error != .success { - NCContentPresenter.shared.showError(error: error) - return + if isNewShare { + 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) +// networking?.createShare(option: share) + } 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(option: share) - } else { - networking?.updateShare(option: share) - } + + networking?.updateShare(option: share) + navigationController?.popViewController(animated: true) } - navigationController?.popViewController(animated: true) } var oldTableShare: tableShare? @@ -74,17 +67,27 @@ class NCShareAdvancePermission: UITableViewController, NCShareAdvanceFotterDeleg var metadata: tableMetadata! var shareConfig: NCShareConfig! var networking: NCShareNetworking? - + let tableViewBottomInset: CGFloat = 80.0 + lazy var shareType: Int = { + isNewShare ? share.shareType : oldTableShare?.shareType ?? NCShareCommon.shared.SHARE_TYPE_USER + }() + static let displayDateFormat = "dd. MMM. yyyy" + var downloadLimit: DownloadLimit? + override func viewDidLoad() { super.viewDidLoad() self.shareConfig = NCShareConfig(parentMetadata: metadata, share: share) - - tableView.estimatedRowHeight = tableView.rowHeight - tableView.rowHeight = UITableView.automaticDimension self.setNavigationTitle() - self.navigationItem.hidesBackButton = true // disbale pull to dimiss isModalInPresentation = true + self.tableView.separatorStyle = UITableViewCell.SeparatorStyle.none + 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() { @@ -93,114 +96,706 @@ 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) // 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("NCShareAdvancePermissionHeader", owner: self, options: nil)?.first as? NCShareAdvancePermissionHeader) 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 = oldTableShare?.permissions, !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) + } + 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 = oldTableShare?.permissions { + 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.shared.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 oldTableShare?.permissions == 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 } - override func numberOfSections(in tableView: UITableView) -> Int { - return 2 + switch formRow.tag { + case "NCFilePermissionCellRead": + + let value = CCUtility.getPermissionsValue(byCanEdit: false, andCanCreate: false, andCanChange: false, andCanDelete: false, andCanShare: canReshareTheShare(), andIsFolder: metadata.directory) + share.permissions = value + self.oldTableShare?.setPermission(value: 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) + } + } + + self.reloadForm() + break + case "kNMCFilePermissionCellEditing": + let value = CCUtility.getPermissionsValue(byCanEdit: true, andCanCreate: true, andCanChange: true, andCanDelete: true, andCanShare: canReshareTheShare(), andIsFolder: metadata.directory) + share.permissions = value + self.oldTableShare?.setPermission(value: 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": + share.permissions = NCGlobal.shared.permissionCreateShare + + self.oldTableShare?.setPermission(value: 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 ? NCGlobal.shared.permissionMaxFolderShare : NCGlobal.shared.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 = oldTableShare?.permissions { + 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 = oldTableShare?.permissions { + 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 = !(share.permissions == NCGlobal.shared.permissionCreateShare) + cell?.switchControl.isEnabled = !(share.permissions == NCGlobal.shared.permissionCreateShare) + cell?.isUserInteractionEnabled = !(share.permissions == 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.shared.isDirectEditing(account: metadata.account, contentType: metadata.contentType) + let availableRichDocument = NCUtility.shared.isRichDocument(metadata) + + // RichDocument: Collabora + return (availableRichDocument && editors.count == 0) + } + + func isFileDropOptionVisible() -> Bool { + return (metadata.directory && (isLinkShare() || isExternalUserShare())) + } + + func isLinkShare() -> Bool { + return NCShareCommon.shared.isLinkShare(shareType: shareType) + } + + func isExternalUserShare() -> Bool { + return NCShareCommon.shared.isExternalUserShare(shareType: shareType) + } + + func isInternalUser() -> Bool { + return NCShareCommon.shared.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 else { + self.oldTableShare?.setPermission(value: 0) + self.share.permissions = 0 return } - switch cellConfig { - 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() + let canEdit = CCUtility.isAnyPermission(toEdit: oldTableShare.permissions) + let canCreate = CCUtility.isPermission(toCanCreate: oldTableShare.permissions) + let canChange = CCUtility.isPermission(toCanChange: oldTableShare.permissions) + let canDelete = CCUtility.isPermission(toCanDelete: oldTableShare.permissions) + + var permission: Int = 0 + + if metadata.directory { + permission = CCUtility.getPermissionsValue(byCanEdit: canEdit, andCanCreate: canCreate, andCanChange: canChange, andCanDelete: canDelete, andCanShare: isOn, andIsFolder: metadata.directory) + } else { + if isOn { + if canEdit { + permission = CCUtility.getPermissionsValue(byCanEdit: true, andCanCreate: true, andCanChange: true, andCanDelete: true, andCanShare: isOn, andIsFolder: metadata.directory) + } else { + permission = CCUtility.getPermissionsValue(byCanEdit: false, andCanCreate: false, andCanChange: false, andCanDelete: false, andCanShare: isOn, andIsFolder: metadata.directory) + } + } else { + if canEdit { + permission = CCUtility.getPermissionsValue(byCanEdit: true, andCanCreate: true, andCanChange: true, andCanDelete: true, andCanShare: isOn, andIsFolder: metadata.directory) + } else { + permission = CCUtility.getPermissionsValue(byCanEdit: false, andCanCreate: false, andCanChange: false, andCanDelete: false, andCanShare: isOn, andIsFolder: metadata.directory) + } } - self.present(alertController, animated: true) } + self.oldTableShare?.setPermission(value: permission) + self.share.permissions = permission + + } + + 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) } } diff --git a/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.swift b/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.swift index d8d94aa410..ce15a5705e 100644 --- a/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.swift +++ b/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.swift @@ -32,32 +32,33 @@ class NCShareAdvancePermissionFooter: UIView { @IBOutlet weak var buttonCancel: UIButton! @IBOutlet weak var buttonNext: UIButton! weak var delegate: NCShareAdvanceFotterDelegate? - + func setupUI(delegate: NCShareAdvanceFotterDelegate?) { 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 = UIColor.systemGray.cgColor - buttonCancel.backgroundColor = .secondarySystemBackground - buttonCancel.addTarget(self, action: #selector(cancelClicked), for: .touchUpInside) - buttonCancel.setTitleColor(.systemGray, for: .normal) - - buttonNext.setTitle(NSLocalizedString(delegate?.isNewShare == true ? "_share_" : "_save_", comment: ""), for: .normal) - buttonNext.layer.cornerRadius = 25 + 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 - buttonNext.backgroundColor = NCBrandColor.shared.brand - buttonNext.addTarget(self, action: #selector(nextClicked), for: .touchUpInside) - buttonNext.setTitleColor(NCBrandColor.shared.brandText, for: .normal) } - + @objc func cancelClicked() { delegate?.dismissShareAdvanceView(shouldSave: false) } - + @objc func nextClicked() { delegate?.dismissShareAdvanceView(shouldSave: true) } diff --git a/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.xib b/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.xib index 40b515e7d5..f38b4931fb 100644 --- a/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.xib +++ b/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.xib @@ -1,65 +1,60 @@ - + - + - - - + + - + + - + - - - - - - - + - + - - - - - - - + + + - - + + - + - - - - - - - - diff --git a/iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.swift b/iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.swift index e5291e8c2d..5cd55f7298 100644 --- a/iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.swift +++ b/iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.swift @@ -27,25 +27,54 @@ 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! - + var ocId = "" + func setupUI(with metadata: tableMetadata) { + backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + fileName.textColor = NCBrandColor.shared.label + info.textColor = NCBrandColor.shared.textInfo + backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground if FileManager.default.fileExists(atPath: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) { fullWidthImageView.image = NCUtility.shared.getImageMetadata(metadata, for: frame.height) fullWidthImageView.contentMode = .scaleAspectFill imageView.isHidden = true } else { if metadata.directory { - imageView.image = metadata.e2eEncrypted ? UIImage(named: "folderEncrypted") : UIImage(named: "folder") + imageView.image = UIImage.init(named: "folder") } else if !metadata.iconName.isEmpty { - imageView.image = UIImage(named: metadata.iconName) + imageView.image = UIImage.init(named: metadata.iconName) } else { - imageView.image = NCBrandColor.cacheImages.file + imageView.image = UIImage.init(named: "file") } } + favorite.setNeedsUpdateConstraints() + favorite.layoutIfNeeded() fileName.text = metadata.fileNameView - fileName.textColor = .label - info.textColor = .secondaryLabel + fileName.textColor = NCBrandColor.shared.fileFolderName + if metadata.favorite { + favorite.setImage(NCUtility.shared.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite, size: 24), for: .normal) + } else { + favorite.setImage(NCUtility.shared.loadImage(named: "star.fill", color: NCBrandColor.shared.textInfo, size: 24), for: .normal) + } + info.textColor = NCBrandColor.shared.optionItem info.text = CCUtility.transformedSize(metadata.size) + ", " + CCUtility.dateDiff(metadata.date as Date) } + + @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(NCUtility.shared.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite, size: 24), for: .normal) + } else { + self.favorite.setImage(NCUtility.shared.loadImage(named: "star.fill", color: NCBrandColor.shared.textInfo, size: 24), for: .normal) + } + } else { + NCContentPresenter.shared.showError(error: error) + } + } + } } diff --git a/iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.xib b/iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.xib index beb60d8c5e..858193894a 100644 --- a/iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.xib +++ b/iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.xib @@ -1,67 +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 c9a19f2740..8a39d92ce3 100644 --- a/iOSClient/Share/Advanced/NCShareNewUserAddComment.swift +++ b/iOSClient/Share/Advanced/NCShareNewUserAddComment.swift @@ -26,41 +26,59 @@ import NextcloudKit import SVGKit class NCShareNewUserAddComment: UIViewController, NCShareDetail { - + @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: 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) + changeTheming() + setupHeader() + } - 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) - } - - noteTextField.inputAccessoryView = toolbar.wrappedSafeAreaContainer - + @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: "") + } + + 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 @@ -68,29 +86,48 @@ class NCShareNewUserAddComment: UIViewController, NCShareDetail { 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 + } + + @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 } - - noteTextField.scrollIndicatorInsets = noteTextField.contentInset } } 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 fa63960bcf..6c2ffde821 100755 --- a/iOSClient/Share/NCSearchUserDropDownCell.xib +++ b/iOSClient/Share/NCSearchUserDropDownCell.xib @@ -1,9 +1,9 @@ - + - + @@ -29,7 +29,7 @@ diff --git a/iOSClient/Share/NCShareLinkCell.swift b/iOSClient/Share/NCShareLinkCell.swift index 59c1c6164e..109bdf8622 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 private weak var menuButton: UIButton! - @IBOutlet private weak var copyButton: UIButton! + @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! + + private let iconShare: CGFloat = 200 var tableShare: tableShare? weak var delegate: NCShareLinkCellDelegate? var isInternalLink = false @@ -40,55 +44,50 @@ class NCShareLinkCell: UITableViewCell { isInternalLink = false tableShare = nil } + + override func awakeFromNib() { + super.awakeFromNib() - func setupCellUI() { - var imageName: String - var imageBGColor: UIColor - var menuImageName = "shareMenu" - - menuButton.isHidden = isInternalLink - descriptionLabel.isHidden = !isInternalLink - copyButton.isHidden = !isInternalLink && tableShare == nil - copyButton.accessibilityLabel = NSLocalizedString("_copy_", comment: "") - menuButton.accessibilityLabel = NSLocalizedString("_more_", comment: "") + 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 { - imageName = "shareInternalLink" - imageBGColor = .gray - labelTitle.text = NSLocalizedString("_share_internal_link_", comment: "") - descriptionLabel.text = NSLocalizedString("_share_internal_link_des_", comment: "") + 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 = "shareAdd" - menuButton.accessibilityLabel = NSLocalizedString("_add_", comment: "") + labelQuickStatus.text = NSLocalizedString("_share_read_only_", comment: "") } - - imageName = "sharebylink" - imageBGColor = NCBrandColor.shared.brandElement - - menuButton.setImage(UIImage(named: menuImageName)?.image(color: .gray, size: 50), for: .normal) } - - labelTitle.textColor = .label - imageItem.image = NCShareCommon.shared.createLinkAvatar(imageName: imageName, colorCircle: imageBGColor) - copyButton.setImage(UIImage(named: "shareCopy")?.image(color: .gray, size: 50), for: .normal) } - - @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 b5172d16f8..c3f13f8fec 100755 --- a/iOSClient/Share/NCShareLinkCell.xib +++ b/iOSClient/Share/NCShareLinkCell.xib @@ -1,107 +1,120 @@ - + - - + - + - + - - + + - - + + - - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + - - - - - + + + + + + + + - + - - - diff --git a/iOSClient/Share/NCShareNetworking.swift b/iOSClient/Share/NCShareNetworking.swift index e17da597c9..edcb449874 100644 --- a/iOSClient/Share/NCShareNetworking.swift +++ b/iOSClient/Share/NCShareNetworking.swift @@ -25,9 +25,7 @@ import NextcloudKit class NCShareNetworking: NSObject { - // swiftlint:disable force_cast private let appDelegate = UIApplication.shared.delegate as! AppDelegate - // swiftlint:enable force_cast weak var delegate: NCShareNetworkingDelegate? var view: UIView @@ -50,12 +48,12 @@ class NCShareNetworking: NSObject { let filenamePath = CCUtility.returnFileNamePath(fromFileName: metadata.fileName, serverUrl: metadata.serverUrl, urlBase: metadata.urlBase, userId: metadata.userId, account: metadata.account)! let parameter = NKShareParameter(path: filenamePath) - NextcloudKit.shared.readShares(parameters: parameter) { account, shares, _, error in + NextcloudKit.shared.readShares(parameters: parameter) { account, shares, data, error in if error == .success, let shares = shares { - NCManageDatabase.shared.deleteTableShare(account: account, path: "/" + filenamePath) + NCManageDatabase.shared.deleteTableShare(account: account) let home = NCUtilityFileSystem.shared.getHomeServer(urlBase: self.metadata.urlBase, userId: self.metadata.userId) - NCManageDatabase.shared.addShare(account: self.metadata.account, home: home, shares: shares) - NextcloudKit.shared.getGroupfolders { account, results, _, error in + NCManageDatabase.shared.addShare(account: self.metadata.account, home:home, shares: shares) + NextcloudKit.shared.getGroupfolders() { account, results, data, error in if showLoadingIndicator { NCActivityIndicator.shared.stop() } @@ -73,19 +71,34 @@ class NCShareNetworking: NSObject { } } } + + func createShareLink(password: String?) { + NCActivityIndicator.shared.start(backgroundView: view) + let filenamePath = CCUtility.returnFileNamePath(fromFileName: metadata.fileName, serverUrl: metadata.serverUrl, urlBase: metadata.urlBase, userId: metadata.userId, account: metadata.account)! + NextcloudKit.shared.createShareLink(path: filenamePath) { account, share, data, error in + NCActivityIndicator.shared.stop() + if error == .success && share != nil { + let home = NCUtilityFileSystem.shared.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.shared.showError(error: error) + } + self.delegate?.shareCompleted() + } + } func createShare(option: NCTableShareable) { // NOTE: Permissions don't work for creating with file drop! // https://github.com/nextcloud/server/issues/17504 - // NOTE: Can't save label and expirationDate in the same request. + // NOTE: Can't save label, expirationDate, and note in same request. // Library update needed: // https://github.com/nextcloud/ios-communication-library/pull/104 NCActivityIndicator.shared.start(backgroundView: view) let filenamePath = CCUtility.returnFileNamePath(fromFileName: metadata.fileName, serverUrl: metadata.serverUrl, urlBase: metadata.urlBase, userId: metadata.userId, account: metadata.account)! - NextcloudKit.shared.createShare(path: filenamePath, shareType: option.shareType, shareWith: option.shareWith, password: option.password, note: option.note, permissions: option.permissions, attributes: option.attributes) { _, share, _, error in + NextcloudKit.shared.createShare(path: filenamePath, shareType: option.shareType, shareWith: option.shareWith, password: option.password, permissions: option.permissions, attributes: option.attributes) { (account, share, data, error) in NCActivityIndicator.shared.stop() if error == .success, let share = share { option.idShare = share.idShare @@ -116,7 +129,7 @@ class NCShareNetworking: NSObject { func updateShare(option: NCTableShareable) { NCActivityIndicator.shared.start(backgroundView: view) - NextcloudKit.shared.updateShare(idShare: option.idShare, password: option.password, expireDate: option.expDateString, permissions: option.permissions, note: option.note, label: option.label, hideDownload: option.hideDownload, attributes: option.attributes) { _, share, _, error in + NextcloudKit.shared.updateShare(idShare: option.idShare, password: option.password, expireDate: option.expDateString, permissions: option.permissions, note: option.note, label: option.label, hideDownload: option.hideDownload, attributes: option.attributes) { account, share, data, error in NCActivityIndicator.shared.stop() if error == .success, let share = share { let home = NCUtilityFileSystem.shared.getHomeServer(urlBase: self.metadata.urlBase, userId: self.metadata.userId) @@ -131,7 +144,7 @@ class NCShareNetworking: NSObject { func getSharees(searchString: String) { NCActivityIndicator.shared.start(backgroundView: view) - NextcloudKit.shared.searchSharees(search: searchString) { _, sharees, _, error in + NextcloudKit.shared.searchSharees(search: searchString) { _, sharees, data, error in NCActivityIndicator.shared.stop() if error == .success { self.delegate?.getSharees(sharees: sharees) diff --git a/iOSClient/Share/NCSharePaging.swift b/iOSClient/Share/NCSharePaging.swift index 64bde1f20f..2676d08f2d 100644 --- a/iOSClient/Share/NCSharePaging.swift +++ b/iOSClient/Share/NCSharePaging.swift @@ -52,7 +52,7 @@ class NCSharePaging: UIViewController { view.backgroundColor = .systemBackground title = NSLocalizedString("_details_", comment: "") - 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: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidEnterBackground), object: nil) @@ -265,129 +265,72 @@ class NCSharePagingView: PagingView { fatalError("init(coder:) has not been implemented") } - override func setupConstraints() { - - guard let headerView = Bundle.main.loadNibNamed("NCShareHeaderView", owner: self, options: nil)?.first as? NCShareHeaderView else { return } - headerView.backgroundColor = .systemBackground - headerView.ocId = metadata.ocId - - let dateFormatter = DateFormatter() - dateFormatter.dateStyle = .short - dateFormatter.timeStyle = .short - dateFormatter.locale = Locale.current - - if FileManager.default.fileExists(atPath: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) { - headerView.imageView.image = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) - } else { - if metadata.directory { - let image = metadata.e2eEncrypted ? UIImage(named: "folderEncrypted") : UIImage(named: "folder") - headerView.imageView.image = image?.image(color: NCBrandColor.shared.brandElement, size: image?.size.width ?? 0) - headerView.imageView.image = headerView.imageView.image?.colorizeFolder(metadata: metadata) - } else if !metadata.iconName.isEmpty { - headerView.imageView.image = UIImage(named: metadata.iconName) - } else { - headerView.imageView.image = UIImage(named: "file") - } - } - headerView.path.text = NCUtilityFileSystem.shared.getPath(path: metadata.path, user: metadata.user, fileName: metadata.fileName) - headerView.path.textColor = .label - headerView.path.trailingBuffer = headerView.path.frame.width - if metadata.favorite { - headerView.favorite.setImage(NCUtility.shared.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite, size: 20), for: .normal) - } else { - headerView.favorite.setImage(NCUtility.shared.loadImage(named: "star.fill", color: .systemGray, size: 20), for: .normal) - } - headerView.info.text = CCUtility.transformedSize(metadata.size) + ", " + NSLocalizedString("_modified_", comment: "") + " " + dateFormatter.string(from: metadata.date as Date) - headerView.info.textColor = .systemGray - headerView.creation.text = NSLocalizedString("_creation_", comment: "") + " " + dateFormatter.string(from: metadata.creationDate as Date) - headerView.creation.textColor = .systemGray - headerView.upload.text = NSLocalizedString("_upload_", comment: "") + " " + dateFormatter.string(from: metadata.uploadDate as Date) - headerView.upload.textColor = .systemGray - - headerView.details.setTitleColor(.label, for: .normal) - headerView.details.setTitle(NSLocalizedString("_details_", comment: ""), for: .normal) - headerView.details.layer.cornerRadius = 9 - headerView.details.layer.masksToBounds = true - headerView.details.layer.backgroundColor = UIColor(red: 152.0 / 255.0, green: 167.0 / 255.0, blue: 181.0 / 255.0, alpha: 0.8).cgColor - - for tag in metadata.tags { - headerView.tagListView.addTag(tag) - } - - if metadata.tags.isEmpty { - NCSharePagingView.tagHeaderHeight = 0 - } else { - NCSharePagingView.tagHeaderHeight = headerView.tagListView.intrinsicContentSize.height + 10 - } - - 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: topAnchor), - headerView.leadingAnchor.constraint(equalTo: leadingAnchor), - headerView.trailingAnchor.constraint(equalTo: trailingAnchor), - headerView.heightAnchor.constraint(equalToConstant: NCSharePagingView.headerHeight + NCSharePagingView.tagHeaderHeight), - - pageView.leadingAnchor.constraint(equalTo: leadingAnchor), - pageView.trailingAnchor.constraint(equalTo: trailingAnchor), - pageView.bottomAnchor.constraint(equalTo: bottomAnchor), - pageView.topAnchor.constraint(equalTo: topAnchor, constant: 10) - ]) - } } 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! 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 < 350 { + constraintTopSharingLabel.constant = 15 + } + } + + func updateCanReshareUI() { + let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) + var isCurrentUser = true + if let ownerId = metadata?.ownerId, !ownerId.isEmpty { + isCurrentUser = NCShareCommon.shared.isCurrentUserIsFileOwner(fileOwnerId: ownerId) + } + let canReshare = NCShareCommon.shared.canReshare(withPermission: metadata?.permissions ?? "") + 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: "") + 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.shared.loadImage( - named: "star.fill", - color: metadata.favorite ? NCBrandColor.shared.yellowFavorite : .systemGray, - size: 20), for: .normal) + if metadata.favorite { + self.favorite.setImage(NCUtility.shared.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite, size: 24), for: .normal) + } else { + self.favorite.setImage(NCUtility.shared.loadImage(named: "star.fill", color: NCBrandColor.shared.textInfo, size: 24), for: .normal) + } } else { NCContentPresenter.shared.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.shared.showInfo(error: error) - } } diff --git a/iOSClient/Share/NCShareSectionHeaderView.swift b/iOSClient/Share/NCShareSectionHeaderView.swift new file mode 100644 index 0000000000..ee405437f6 --- /dev/null +++ b/iOSClient/Share/NCShareSectionHeaderView.swift @@ -0,0 +1,86 @@ +// +// NCShareSectionHeaderView.swift +// Nextcloud +// +// Created by A200020526 on 04/03/22. +// Copyright © 2022 Marino Faggiana. All rights reserved. +// + +import UIKit + +class NCShareSectionHeaderView: UITableViewHeaderFooterView { + + @IBOutlet weak var imageView: UIImageView! + @IBOutlet weak var fileName: UILabel! + @IBOutlet weak var info: UILabel! + @IBOutlet weak var favorite: UIButton! + @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! + + private let appDelegate = UIApplication.shared.delegate as! AppDelegate + var ocId = "" + + static var nib: UINib { + return UINib(nibName: identifier, bundle: nil) + } + + static var identifier: String { + return String(describing: self) + } + + override func awakeFromNib() { + super.awakeFromNib() + setupUI() + } + + func setupUI() { + labelSharing.text = NSLocalizedString("_sharing_", comment: "") + labelSharingInfo.text = NSLocalizedString("_sharing_message_", comment: "") + + if UIScreen.main.bounds.width < 350 { + constraintTopSharingLabel.constant = 15 + } + } + + func updateCanReshareUI() { + let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) + var isCurrentUser = true + if let ownerId = metadata?.ownerId, !ownerId.isEmpty { + isCurrentUser = NCShareCommon.shared.isCurrentUserIsFileOwner(fileOwnerId: ownerId) + } + let canReshare = NCShareCommon.shared.canReshare(withPermission: metadata?.permissions ?? "") + 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: "") + let resharingNotAllowedMessage = NSLocalizedString("_share_reshare_not_allowed_", comment: "") + resharingAllowedLabel.text = canReshare ? resharingAllowedMessage : resharingNotAllowedMessage + } + } + + @IBAction func touchUpInsideFavorite(_ sender: UIButton) { + if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) { + NCNetworking.shared.favoriteMetadata(metadata) { error in + if error == .success { + if !metadata.favorite { + self.favorite.setImage(NCUtility.shared.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite, size: 24), for: .normal) + } else { + self.favorite.setImage(NCUtility.shared.loadImage(named: "star.fill", color: NCBrandColor.shared.textInfo, size: 24), for: .normal) + } + } else { + NCContentPresenter.shared.showError(error: error) + } + } + } + } +} diff --git a/iOSClient/Share/NCShareSectionHeaderView.xib b/iOSClient/Share/NCShareSectionHeaderView.xib new file mode 100644 index 0000000000..e961e99153 --- /dev/null +++ b/iOSClient/Share/NCShareSectionHeaderView.xib @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOSClient/Share/NCShareUserCell.swift b/iOSClient/Share/NCShareUserCell.swift index 2e4efffdff..3ff19fabae 100644 --- a/iOSClient/Share/NCShareUserCell.swift +++ b/iOSClient/Share/NCShareUserCell.swift @@ -28,25 +28,19 @@ class NCShareUserCell: UITableViewCell, NCCellProtocol { @IBOutlet weak var imageItem: UIImageView! @IBOutlet weak var labelTitle: UILabel! + @IBOutlet weak var labelCanEdit: UILabel! + @IBOutlet weak var switchCanEdit: UISwitch! @IBOutlet weak var buttonMenu: UIButton! @IBOutlet weak var imageStatus: UIImageView! @IBOutlet weak var status: UILabel! @IBOutlet weak var btnQuickStatus: UIButton! + @IBOutlet weak var labelQuickStatus: UILabel! @IBOutlet weak var imageDownArrow: UIImageView! - private var index = IndexPath() - var tableShare: tableShare? weak var delegate: NCShareUserCellDelegate? - var indexPath: IndexPath { - get { return index } - set { index = newValue } - } - var fileAvatarImageView: UIImageView? { - return imageItem - } var fileUser: String? { get { return tableShare?.shareWith } set {} @@ -56,36 +50,40 @@ class NCShareUserCell: UITableViewCell, NCCellProtocol { guard let tableShare = tableShare else { return } - self.accessibilityCustomActions = [UIAccessibilityCustomAction( - name: NSLocalizedString("_show_profile_", comment: ""), - target: self, - selector: #selector(tapAvatarImage))] - + contentView.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground labelTitle.text = tableShare.shareWithDisplayname - labelTitle.textColor = .label + labelTitle.textColor = NCBrandColor.shared.label + labelCanEdit.text = NSLocalizedString("_share_permission_edit_", comment: "") + labelCanEdit.textColor = NCBrandColor.shared.iconColor isUserInteractionEnabled = true - labelQuickStatus.isHidden = false - imageDownArrow.isHidden = false + switchCanEdit.isHidden = true//false + labelCanEdit.isHidden = true//false buttonMenu.isHidden = false - buttonMenu.accessibilityLabel = NSLocalizedString("_more_", comment: "") imageItem.image = NCShareCommon.shared.getImageShareType(shareType: tableShare.shareType) - let status = NCUtility.shared.getUserStatus(userIcon: tableShare.userIcon, userStatus: tableShare.userStatus, userMessage: tableShare.userMessage) 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 - buttonMenu.isHidden = true + isUserInteractionEnabled = false + 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 == NCGlobal.shared.permissionCreateShare { labelQuickStatus.text = NSLocalizedString("_share_file_drop_", comment: "") } else { @@ -100,12 +98,11 @@ class NCShareUserCell: UITableViewCell, NCCellProtocol { override func awakeFromNib() { super.awakeFromNib() - let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapAvatarImage)) - imageItem?.addGestureRecognizer(tapGesture) - - buttonMenu.setImage(UIImage(named: "shareMenu")?.image(color: .gray, size: 50), for: .normal) + switchCanEdit.transform = CGAffineTransform(scaleX: 0.75, y: 0.75) + switchCanEdit.onTintColor = NCBrandColor.shared.brandElement + buttonMenu.setImage(UIImage.init(named: "shareMenu")!.image(color: NCBrandColor.shared.customer, size: 24), for: .normal) labelQuickStatus.textColor = NCBrandColor.shared.customer - imageDownArrow.image = NCUtility.shared.loadImage(named: "arrowtriangle.down.fill", color: NCBrandColor.shared.customer) + imageDownArrow.image = UIImage(named: "downArrow")?.imageColor(NCBrandColor.shared.customer) } @objc func tapAvatarImage(_ sender: UITapGestureRecognizer) { @@ -138,12 +135,7 @@ class NCSearchUserDropDownCell: DropDownCell, NCCellProtocol { @IBOutlet weak var centerTitle: NSLayoutConstraint! private var user: String = "" - private var index = IndexPath() - var indexPath: IndexPath { - get { return index } - set { index = newValue } - } var fileAvatarImageView: UIImageView? { return imageItem } @@ -153,8 +145,7 @@ class NCSearchUserDropDownCell: DropDownCell, NCCellProtocol { } func setupCell(sharee: NKSharee, baseUrl: NCUserBaseUrl) { - imageItem.image = NCShareCommon.shared.getImageShareType(shareType: sharee.shareType) - imageShareeType.image = NCShareCommon.shared.getImageShareType(shareType: sharee.shareType) + imageShareeType.image = NCShareCommon.shared.getImageShareType(shareType: sharee.shareType, isDropDown: true) let status = NCUtility.shared.getUserStatus(userIcon: sharee.userIcon, userStatus: sharee.userStatus, userMessage: sharee.userMessage) imageStatus.image = status.onlineStatus self.status.text = status.statusMessage @@ -163,31 +154,5 @@ class NCSearchUserDropDownCell: DropDownCell, NCCellProtocol { } else { centerTitle.constant = 0 } - - imageItem.image = NCUtility.shared.loadUserImage( - for: sharee.shareWith, - displayName: nil, - userBaseUrl: baseUrl) - - let fileName = baseUrl.userBaseUrl + "-" + sharee.shareWith + ".png" - if NCManageDatabase.shared.getImageAvatarLoaded(fileName: fileName) == nil { - let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName - let etag = NCManageDatabase.shared.getTableAvatar(fileName: fileName)?.etag - - NextcloudKit.shared.downloadAvatar( - user: sharee.shareWith, - fileNameLocalPath: fileNameLocalPath, - sizeImage: NCGlobal.shared.avatarSize, - avatarSizeRounded: NCGlobal.shared.avatarSizeRounded, - etag: etag) { _, 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 ee4046f986..d4a63e809b 100755 --- a/iOSClient/Share/NCShareUserCell.xib +++ b/iOSClient/Share/NCShareUserCell.xib @@ -1,26 +1,26 @@ - + - + - + - + - - + + - - + + @@ -32,101 +32,128 @@ - - + - - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + - diff --git a/iOSClient/Share/ShareDownloadLimitNetwork.swift b/iOSClient/Share/ShareDownloadLimitNetwork.swift new file mode 100644 index 0000000000..94322559c3 --- /dev/null +++ b/iOSClient/Share/ShareDownloadLimitNetwork.swift @@ -0,0 +1,145 @@ +// +// 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() + + func getDownloadLimit(token: String, completion: @escaping (_ downloadLimit: DownloadLimit?, _ errorDescription: String) -> Void) { + let baseUrl = 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 = 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 = CCUtility.getPassword(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? +} From 73c83e7033e7f945a894a4faa087b96cfc9b5ab5 Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Tue, 6 Jun 2023 23:36:37 +0530 Subject: [PATCH 02/24] nmc 1992 - ncsharesectionheaderview.swift file lint issue resolve --- iOSClient/Share/NCShareSectionHeaderView.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/iOSClient/Share/NCShareSectionHeaderView.swift b/iOSClient/Share/NCShareSectionHeaderView.swift index ee405437f6..dd0fff1458 100644 --- a/iOSClient/Share/NCShareSectionHeaderView.swift +++ b/iOSClient/Share/NCShareSectionHeaderView.swift @@ -22,8 +22,7 @@ class NCShareSectionHeaderView: UITableViewHeaderFooterView { @IBOutlet weak var resharingAllowedLabel: UILabel! @IBOutlet weak var sharedByImageView: UIImageView! @IBOutlet weak var constraintTopSharingLabel: NSLayoutConstraint! - - private let appDelegate = UIApplication.shared.delegate as! AppDelegate + var ocId = "" static var nib: UINib { From 05d7271bdce395b7b8e008c205e987a4abaefe47 Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Tue, 6 Jun 2023 23:51:11 +0530 Subject: [PATCH 03/24] nmc 1992 - Lint issue fix for NCShare.swift file --- iOSClient/Share/NCShare.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift index f775a9db76..98dd45ffe4 100644 --- a/iOSClient/Share/NCShare.swift +++ b/iOSClient/Share/NCShare.swift @@ -356,7 +356,7 @@ extension NCShare: UITableViewDataSource { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { if indexPath.row == 0 { - let cell = tableView.dequeueReusableCell(withIdentifier: "NCShareEmailFieldCell", for: indexPath) as! NCShareEmailFieldCell + 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) @@ -411,7 +411,9 @@ extension NCShare: UITableViewDataSource { } func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - let headerView = Bundle.main.loadNibNamed("NCShareHeaderView", owner: self, options: nil)?.first as! NCShareHeaderView + 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 From 2650b04dffadf239598261a22cf8df3a73fcbced Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Wed, 7 Jun 2023 15:16:43 +0530 Subject: [PATCH 04/24] nmc 1992 - Share screen Header width update and image shown in header --- iOSClient/Share/NCShare.storyboard | 8 ++++---- iOSClient/Share/NCShare.swift | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/iOSClient/Share/NCShare.storyboard b/iOSClient/Share/NCShare.storyboard index 7b9968e571..07aa53cf74 100644 --- a/iOSClient/Share/NCShare.storyboard +++ b/iOSClient/Share/NCShare.storyboard @@ -52,10 +52,10 @@ - + - + @@ -71,9 +71,9 @@ - + - + diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift index 98dd45ffe4..33f7cad9c9 100644 --- a/iOSClient/Share/NCShare.swift +++ b/iOSClient/Share/NCShare.swift @@ -424,7 +424,7 @@ extension NCShare: UITableViewDataSource { if FileManager.default.fileExists(atPath: CCUtility.getDirectoryProviderStorageIconOcId(metadata?.ocId, etag: metadata?.etag)) { - headerView.imageView.image = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata?.ocId, etag: metadata?.etag)) + headerView.fullWidthImageView.image = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata?.ocId, etag: metadata?.etag)) headerView.fullWidthImageView.contentMode = .scaleAspectFill headerView.imageView.isHidden = true } else { From ae6fa5d166c63bb37e0d9aca40ff2dd4558bb93f Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Thu, 8 Jun 2023 16:11:38 +0530 Subject: [PATCH 05/24] nmc 1992 - Unit test case added for sharing --- Tests/NextcloudUnitTests/SharingTest.swift | 232 +++++++++++++++++++++ iOSClient/Menu/NCShare+Menu.swift | 2 +- 2 files changed, 233 insertions(+), 1 deletion(-) create mode 100644 Tests/NextcloudUnitTests/SharingTest.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/Menu/NCShare+Menu.swift b/iOSClient/Menu/NCShare+Menu.swift index 00a81a14f5..e4c3b1307b 100644 --- a/iOSClient/Menu/NCShare+Menu.swift +++ b/iOSClient/Menu/NCShare+Menu.swift @@ -151,7 +151,7 @@ extension NCShare { self.presentMenu(with: actions) } - fileprivate func hasUploadPermission(tableShare: tableShare) -> Bool { + func hasUploadPermission(tableShare: tableShare) -> Bool { let uploadPermissions = [ NCGlobal.shared.permissionMaxFileShare, NCGlobal.shared.permissionMaxFolderShare, From 2c388800e21a914c89517bb29ceabb034ac8c221 Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Fri, 9 Jun 2023 17:03:12 +0530 Subject: [PATCH 06/24] nmc 1992 - merging conflict resolve of ncbrand.swift --- Brand/NCBrand.swift | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Brand/NCBrand.swift b/Brand/NCBrand.swift index 328f428402..88fac9d58c 100755 --- a/Brand/NCBrand.swift +++ b/Brand/NCBrand.swift @@ -404,4 +404,19 @@ class NCBrandColor: NSObject { } @objc public var systemGray2: UIColor = UIColor.systemGray2 @objc public var shareByEmailTextColor: UIColor = UIColor(displayP3Red: 13.0/255.0, green: 57.0/255.0, blue: 223.0/255.0, alpha: 1.0) + @objc public var memoryConsuptionBackground: UIColor { + if UITraitCollection.current.userInterfaceStyle == .dark { + return UIColor(red: 25.0/255.0, green: 25.0/255.0, blue: 25.0/255.0, alpha: 1.0) + } else { + return UIColor(red: 244.0/255.0, green: 244.0/255.0, blue: 244.0/255.0, alpha: 1.0) + } + } + @objc public var nmcGray0: UIColor{ + if UITraitCollection.current.userInterfaceStyle == .dark { + return UIColor(displayP3Red: 242.0/255.0, green: 242.0/255.0, blue: 242.0/255.0, alpha: 1.0) + }else { + return UIColor(red: 19.0/255.0, green: 19.0/255.0, blue: 19.0/255.0, alpha: 1.0) + } + } + @objc public var commonViewInfoText: UIColor = UIColor(displayP3Red: 102.0/255.0, green: 102.0/255.0, blue: 102.0/255.0, alpha: 1.0) } From 4d3b0a2620f07badf01036e75e2e924aba10630e Mon Sep 17 00:00:00 2001 From: Shweta Waikar Date: Tue, 13 Jun 2023 15:33:21 +0530 Subject: [PATCH 07/24] NMC 1992 NCBrand updated --- Brand/NCBrand.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Brand/NCBrand.swift b/Brand/NCBrand.swift index 88fac9d58c..6b60874890 100755 --- a/Brand/NCBrand.swift +++ b/Brand/NCBrand.swift @@ -419,4 +419,6 @@ class NCBrandColor: NSObject { } } @objc public var commonViewInfoText: UIColor = UIColor(displayP3Red: 102.0/255.0, green: 102.0/255.0, blue: 102.0/255.0, alpha: 1.0) + @objc public let progressColorGreen60: UIColor = UIColor(red: 115.0/255.0, green: 195.0/255.0, blue: 84.0/255.0, alpha: 1.0) + @objc public var seperatorRename: UIColor = UIColor(red: 235.0/255.0, green: 235.0/255.0, blue: 235.0/255.0, alpha: 1.0) } From e47a25c9c89219493b20209474c81538ea51c0f5 Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Wed, 14 Jun 2023 12:18:32 +0530 Subject: [PATCH 08/24] nmc 1992 - merging conflict resolve after master update with 4.8.3 --- iOSClient/Share/NCShare.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift index 33f7cad9c9..29e1804301 100644 --- a/iOSClient/Share/NCShare.swift +++ b/iOSClient/Share/NCShare.swift @@ -185,7 +185,7 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent @IBAction func touchUpInsideButtonMenu(_ sender: Any) { guard let metadata = metadata else { return } - let isFilesSharingPublicPasswordEnforced = NCManageDatabase.shared.getCapabilitiesServerBool(account: metadata.account, elements: NCElementsJSON.shared.capabilitiesFileSharingPubPasswdEnforced, exists: false) + let isFilesSharingPublicPasswordEnforced = NCGlobal.shared.capabilityFileSharingPubPasswdEnforced let shares = NCManageDatabase.shared.getTableShares(metadata: metadata) if isFilesSharingPublicPasswordEnforced && shares.firstShareLink == nil { From 93085f9bb8c6e6ecbd1a026bd806d016f8829bcd Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Thu, 15 Jun 2023 17:22:05 +0530 Subject: [PATCH 09/24] nmc 1992 - merging conflict resolve after Dashboard cluster --- Brand/NCBrand.swift | 2 ++ iOSClient/Share/NCShare.swift | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Brand/NCBrand.swift b/Brand/NCBrand.swift index 6b60874890..b6ff3ab070 100755 --- a/Brand/NCBrand.swift +++ b/Brand/NCBrand.swift @@ -421,4 +421,6 @@ class NCBrandColor: NSObject { @objc public var commonViewInfoText: UIColor = UIColor(displayP3Red: 102.0/255.0, green: 102.0/255.0, blue: 102.0/255.0, alpha: 1.0) @objc public let progressColorGreen60: UIColor = UIColor(red: 115.0/255.0, green: 195.0/255.0, blue: 84.0/255.0, alpha: 1.0) @objc public var seperatorRename: UIColor = UIColor(red: 235.0/255.0, green: 235.0/255.0, blue: 235.0/255.0, alpha: 1.0) + @objc public let gray: UIColor = UIColor(red: 104.0/255.0, green: 104.0/255.0, blue: 104.0/255.0, alpha: 1.0) + @objc public var nmcIconSharedWithMe: UIColor = UIColor(displayP3Red: 0.0/255.0, green: 153.0/255.0, blue: 255.0/255.0, alpha: 1.0) } diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift index 29e1804301..ac097a2215 100644 --- a/iOSClient/Share/NCShare.swift +++ b/iOSClient/Share/NCShare.swift @@ -225,7 +225,7 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent } func shareCompleted() { - NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataNCShare) + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSourceNetworkForced) } func unShareCompleted() { From 26a7297f2462513d9009d64f5a07c86cd8824c87 Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Mon, 19 Jun 2023 11:09:07 +0530 Subject: [PATCH 10/24] NMC 1992 - download limit issue fix --- iOSClient/Share/ShareDownloadLimitNetwork.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/iOSClient/Share/ShareDownloadLimitNetwork.swift b/iOSClient/Share/ShareDownloadLimitNetwork.swift index 94322559c3..c15fe512c1 100644 --- a/iOSClient/Share/ShareDownloadLimitNetwork.swift +++ b/iOSClient/Share/ShareDownloadLimitNetwork.swift @@ -24,7 +24,7 @@ class NMCCommunication: NSObject, XMLParserDelegate { func getDownloadLimit(token: String, completion: @escaping (_ downloadLimit: DownloadLimit?, _ errorDescription: String) -> Void) { let baseUrl = NCBrandOptions.shared.loginBaseUrl - let endPoint = "ocs/v2.php/apps/files_downloadlimit/\(token)/limit" + 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) @@ -62,7 +62,7 @@ class NMCCommunication: NSObject, XMLParserDelegate { func setDownloadLimit(deleteLimit: Bool, limit: String, token: String, completion: @escaping (_ success: Bool, _ errorDescription: String) -> Void) { let baseUrl = NCBrandOptions.shared.loginBaseUrl - let endPoint = "ocs/v2.php/apps/files_downloadlimit/\(token)/limit" + let endPoint = "/ocs/v2.php/apps/files_downloadlimit/\(token)/limit" let path = baseUrl+endPoint do { From 640ad77e8fddedaf23a0183d4291991cb8ccf21b Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Tue, 20 Jun 2023 17:59:44 +0530 Subject: [PATCH 11/24] nmc 1992 - resolve merging conflict of image extension --- iOSClient/Extensions/UIImage+Extension.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOSClient/Extensions/UIImage+Extension.swift b/iOSClient/Extensions/UIImage+Extension.swift index 8c4b87efa7..0c31752d27 100644 --- a/iOSClient/Extensions/UIImage+Extension.swift +++ b/iOSClient/Extensions/UIImage+Extension.swift @@ -141,7 +141,7 @@ extension UIImage { return newImage } - + func imageColor(_ color: UIColor) -> UIImage { if #available(iOS 13.0, *) { return self.withTintColor(color, renderingMode: .alwaysOriginal) From ef9e25860c0ef8053c98294e6f5e94176138f7d6 Mon Sep 17 00:00:00 2001 From: Shweta Waikar Date: Fri, 23 Jun 2023 13:06:07 +0530 Subject: [PATCH 12/24] NMC 1992 Changed background color for view --- iOSClient/Share/NCShare.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift index ac097a2215..5e5a9f6e35 100644 --- a/iOSClient/Share/NCShare.swift +++ b/iOSClient/Share/NCShare.swift @@ -56,12 +56,12 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent override func viewDidLoad() { super.viewDidLoad() - view.backgroundColor = .systemBackground + view.backgroundColor = .secondarySystemGroupedBackground tableView.dataSource = self tableView.delegate = self tableView.allowsSelection = false - tableView.backgroundColor = .systemBackground + tableView.backgroundColor = .secondarySystemGroupedBackground tableView.register(UINib(nibName: "NCShareLinkCell", bundle: nil), forCellReuseIdentifier: "cellLink") tableView.register(UINib(nibName: "NCShareUserCell", bundle: nil), forCellReuseIdentifier: "cellUser") @@ -243,7 +243,7 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent dropDown = DropDown() let appearance = DropDown.appearance() - appearance.backgroundColor = .systemBackground + appearance.backgroundColor = .secondarySystemGroupedBackground appearance.cornerRadius = 10 appearance.shadowColor = UIColor(white: 0.5, alpha: 1) appearance.shadowOpacity = 0.9 From 9ec0b4ad774151079a397e3ede241dc8bf6853b4 Mon Sep 17 00:00:00 2001 From: Shweta Waikar Date: Fri, 23 Jun 2023 16:11:39 +0530 Subject: [PATCH 13/24] NMC 1992 header height fix --- iOSClient/Share/NCShare.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift index 5e5a9f6e35..cfc4adf563 100644 --- a/iOSClient/Share/NCShare.swift +++ b/iOSClient/Share/NCShare.swift @@ -124,7 +124,7 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent } 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 -= 120 + self.view.frame.origin.y -= 70 } } else { if view.frame.origin.y == 0 { From bce339a6c81dcc716123bb3ace1dff241a065df1 Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Sat, 24 Jun 2023 17:51:56 +0530 Subject: [PATCH 14/24] NMC 1992 - Share permission update issue fix --- iOSClient/Menu/NCShare+Menu.swift | 3 +- .../Advanced/NCShareAdvancePermission.swift | 31 +++++++++++-------- iOSClient/Share/NCShare.swift | 1 + 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/iOSClient/Menu/NCShare+Menu.swift b/iOSClient/Menu/NCShare+Menu.swift index e4c3b1307b..2a7353ee59 100644 --- a/iOSClient/Menu/NCShare+Menu.swift +++ b/iOSClient/Menu/NCShare+Menu.swift @@ -143,7 +143,8 @@ extension NCShare { selected: false, on: false, action: { menuAction in - NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterStatusFileDrop, object: tableShare) + let permissions = NCGlobal.shared.permissionCreateShare + self.updateSharePermissions(share: tableShare, permissions: permissions) } ) ) diff --git a/iOSClient/Share/Advanced/NCShareAdvancePermission.swift b/iOSClient/Share/Advanced/NCShareAdvancePermission.swift index 41c7cde505..11a446188e 100644 --- a/iOSClient/Share/Advanced/NCShareAdvancePermission.swift +++ b/iOSClient/Share/Advanced/NCShareAdvancePermission.swift @@ -28,17 +28,18 @@ import CloudKit class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelegate, NCShareDetail { func dismissShareAdvanceView(shouldSave: Bool) { - if isNewShare { - 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) -// networking?.createShare(option: share) - } else { - if let downloadSwitchCell = getDownloadLimitSwitchCell() { - let isDownloadLimitOn = downloadSwitchCell.switchControl.isOn + if shouldSave { + if isNewShare { + 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) + // networking?.createShare(option: share) + } else { + if let downloadSwitchCell = getDownloadLimitSwitchCell() { + let isDownloadLimitOn = downloadSwitchCell.switchControl.isOn if !isDownloadLimitOn { setDownloadLimit(deleteLimit: true, limit: "") } else { @@ -55,8 +56,11 @@ class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelega setDownloadLimit(deleteLimit: false, limit: enteredDownloadLimit) } } - - networking?.updateShare(option: share) + + networking?.updateShare(option: share) + navigationController?.popViewController(animated: true) + } + } else { navigationController?.popViewController(animated: true) } } @@ -185,6 +189,7 @@ class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelega } if isNewShare { row.cellConfig["imageCheck.image"] = UIImage(named: "success")!.image(color: NCBrandColor.shared.customer, size: 25.0) + share.permissions = NCGlobal.shared.permissionReadShare } section.addFormRow(row) diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift index cfc4adf563..fb7829d359 100644 --- a/iOSClient/Share/NCShare.swift +++ b/iOSClient/Share/NCShare.swift @@ -226,6 +226,7 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent func shareCompleted() { NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSourceNetworkForced) + self.reloadData() } func unShareCompleted() { From 6aeb0ed06b83e7a3df933c4e4d06c58771b61acf Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Mon, 26 Jun 2023 12:25:46 +0530 Subject: [PATCH 15/24] nmc 1992 - can reshare permission update --- iOSClient/Share/Advanced/NCShareAdvancePermission.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOSClient/Share/Advanced/NCShareAdvancePermission.swift b/iOSClient/Share/Advanced/NCShareAdvancePermission.swift index 11a446188e..487be5745a 100644 --- a/iOSClient/Share/Advanced/NCShareAdvancePermission.swift +++ b/iOSClient/Share/Advanced/NCShareAdvancePermission.swift @@ -746,7 +746,7 @@ class NCShareAdvancePermission: XLFormViewController, NCShareAdvanceFotterDelega guard let oldTableShare = oldTableShare else { self.oldTableShare?.setPermission(value: 0) - self.share.permissions = 0 + self.share.permissions = isOn ? self.share.permissions + NCGlobal.shared.permissionShareShare : self.share.permissions return } From dd863d541c2e381906ad87a5a2e68e8b685433e1 Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Mon, 26 Jun 2023 17:51:20 +0530 Subject: [PATCH 16/24] NMC 1992 - Share status update issue fix --- Nextcloud.xcodeproj/project.pbxproj | 4 ++++ iOSClient/Extensions/UIToolbar+Extension.swift | 15 +++++++++++++++ iOSClient/Networking/NCService.swift | 14 ++++++++++++++ iOSClient/Scan document/PasswordInputField.swift | 3 +++ .../Share/Advanced/NCShareNewUserAddComment.swift | 3 +++ iOSClient/Share/NCShare.swift | 4 +++- iOSClient/Share/NCShareNetworking.swift | 1 - 7 files changed, 42 insertions(+), 2 deletions(-) diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index a06a7f32a3..c4a396904d 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 370D26AF248A3D7A00121797 /* NCCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370D26AE248A3D7A00121797 /* NCCellProtocol.swift */; }; 371B5A2E23D0B04500FAFAE9 /* NCMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371B5A2D23D0B04500FAFAE9 /* NCMenu.swift */; }; 3781B9B023DB2B7E006B4B1D /* AppDelegate+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3781B9AF23DB2B7E006B4B1D /* AppDelegate+Menu.swift */; }; + 56548E2B2A49B95C00D58443 /* PasswordInputField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56548E2A2A49B95C00D58443 /* PasswordInputField.swift */; }; 8491B1CD273BBA82001C8C5B /* UIViewController+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8491B1CC273BBA82001C8C5B /* UIViewController+Menu.swift */; }; AF1A9B6427D0CA1E00F17A9E /* UIAlertController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1A9B6327D0CA1E00F17A9E /* UIAlertController+Extension.swift */; }; AF1A9B6527D0CC0500F17A9E /* UIAlertController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1A9B6327D0CA1E00F17A9E /* UIAlertController+Extension.swift */; }; @@ -792,6 +793,7 @@ 371B5A2D23D0B04500FAFAE9 /* NCMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMenu.swift; sourceTree = ""; }; 371B5A3223D0BD5500FAFAE9 /* FloatingPanel.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FloatingPanel.framework; path = Carthage/Build/iOS/FloatingPanel.framework; sourceTree = ""; }; 3781B9AF23DB2B7E006B4B1D /* AppDelegate+Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+Menu.swift"; sourceTree = ""; }; + 56548E2A2A49B95C00D58443 /* PasswordInputField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordInputField.swift; sourceTree = ""; }; 8491B1CC273BBA82001C8C5B /* UIViewController+Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Menu.swift"; sourceTree = ""; }; AF1A9B6327D0CA1E00F17A9E /* UIAlertController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIAlertController+Extension.swift"; sourceTree = ""; }; AF22B20B277C6F4D00DAB0CC /* NCShareCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareCell.swift; sourceTree = ""; }; @@ -1897,6 +1899,7 @@ F758B41E212C516300515F55 /* Scan document */ = { isa = PBXGroup; children = ( + 56548E2A2A49B95C00D58443 /* PasswordInputField.swift */, F758B457212C564000515F55 /* NCScan.storyboard */, F758B45D212C569C00515F55 /* NCScanCell.swift */, F758B45F212C56A400515F55 /* NCScan.swift */, @@ -3736,6 +3739,7 @@ F78071091EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m in Sources */, F79B646026CA661600838ACA /* UIControl+Extension.swift in Sources */, F7CA212D25F1333300826ABB /* NCAccountRequest.swift in Sources */, + 56548E2B2A49B95C00D58443 /* PasswordInputField.swift in Sources */, F765F73125237E3F00391DBE /* NCRecent.swift in Sources */, F76B3CCE1EAE01BD00921AC9 /* NCBrand.swift in Sources */, F359D8672A7D03420023F405 /* NCUtility+Exif.swift in Sources */, diff --git a/iOSClient/Extensions/UIToolbar+Extension.swift b/iOSClient/Extensions/UIToolbar+Extension.swift index 53e63fca1b..7ea64fe36e 100644 --- a/iOSClient/Extensions/UIToolbar+Extension.swift +++ b/iOSClient/Extensions/UIToolbar+Extension.swift @@ -57,6 +57,21 @@ 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/Networking/NCService.swift b/iOSClient/Networking/NCService.swift index efbb778e43..a5287dc3ad 100644 --- a/iOSClient/Networking/NCService.swift +++ b/iOSClient/Networking/NCService.swift @@ -201,6 +201,20 @@ class NCService: NSObject { } else { self.appDelegate.disableSharesView = false } + + // File Sharing + if NCGlobal.shared.capabilityFileSharingApiEnabled { + let home = NCUtilityFileSystem.shared.getHomeServer(urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId) + NextcloudKit.shared.readShares(parameters: NKShareParameter(), options: options) { 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 NCGlobal.shared.capabilityServerVersionMajor >= NCGlobal.shared.nextcloudVersion18 { diff --git a/iOSClient/Scan document/PasswordInputField.swift b/iOSClient/Scan document/PasswordInputField.swift index 6f7a9609c7..c2b893324b 100644 --- a/iOSClient/Scan document/PasswordInputField.swift +++ b/iOSClient/Scan document/PasswordInputField.swift @@ -20,6 +20,9 @@ class PasswordInputField: XLFormBaseCell,UITextFieldDelegate { 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) { diff --git a/iOSClient/Share/Advanced/NCShareNewUserAddComment.swift b/iOSClient/Share/Advanced/NCShareNewUserAddComment.swift index 8a39d92ce3..3d9fc76141 100644 --- a/iOSClient/Share/Advanced/NCShareNewUserAddComment.swift +++ b/iOSClient/Share/Advanced/NCShareNewUserAddComment.swift @@ -74,6 +74,9 @@ class NCShareNewUserAddComment: UIViewController, NCShareDetail { 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() + } } func setupHeader(){ diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift index fb7829d359..6b41bf1159 100644 --- a/iOSClient/Share/NCShare.swift +++ b/iOSClient/Share/NCShare.swift @@ -225,11 +225,12 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent } func shareCompleted() { - NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSourceNetworkForced) + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource) self.reloadData() } func unShareCompleted() { + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource) self.reloadData() } @@ -280,6 +281,7 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent } dropDown.selectionAction = { index, _ in + self.textField?.text = "" self.textField?.resignFirstResponder() let sharee = sharees[index] guard diff --git a/iOSClient/Share/NCShareNetworking.swift b/iOSClient/Share/NCShareNetworking.swift index edcb449874..f029f4ada5 100644 --- a/iOSClient/Share/NCShareNetworking.swift +++ b/iOSClient/Share/NCShareNetworking.swift @@ -50,7 +50,6 @@ class NCShareNetworking: NSObject { NextcloudKit.shared.readShares(parameters: parameter) { account, shares, data, error in if error == .success, let shares = shares { - NCManageDatabase.shared.deleteTableShare(account: account) let home = NCUtilityFileSystem.shared.getHomeServer(urlBase: self.metadata.urlBase, userId: self.metadata.userId) NCManageDatabase.shared.addShare(account: self.metadata.account, home:home, shares: shares) NextcloudKit.shared.getGroupfolders() { account, results, data, error in From d34941d9277167a6f2e4444e7aa9a283fda3e0f0 Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Tue, 27 Jun 2023 22:44:27 +0530 Subject: [PATCH 17/24] NMC 1992 - Re sharing message string update --- iOSClient/Share/NCShare.swift | 10 +++++----- iOSClient/Share/NCSharePaging.swift | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift index 6b41bf1159..cf1ef2b00c 100644 --- a/iOSClient/Share/NCShare.swift +++ b/iOSClient/Share/NCShare.swift @@ -340,7 +340,7 @@ extension NCShare: UITableViewDataSource { shares.share?.insert(shareLink, at: 0) } - self.tableView.setEmptyMessage(NSLocalizedString("", comment: "")) + self.tableView.setEmptyMessage(NSLocalizedString("", comment: ""), isReshared: (metadata?.ownerId != appDelegate?.userId)) if shares.share != nil { numOfRows = shares.share!.count } @@ -349,7 +349,7 @@ extension NCShare: UITableViewDataSource { messageView.removeFromSuperview() } if canReshare { - self.tableView.setEmptyMessage(NSLocalizedString("no_shares_created", comment: "")) + self.tableView.setEmptyMessage(NSLocalizedString("no_shares_created", comment: ""), isReshared: (metadata?.ownerId != appDelegate?.userId)) } } else { self.tableView.restore() @@ -456,14 +456,14 @@ extension NCShare: UITableViewDataSource { return 320 } func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - return 320 + return metadata?.ownerId != appDelegate?.userId ? 350 : 320 } } extension UITableView { - func setEmptyMessage(_ message: String) { - let messageLabel = UILabel(frame: CGRect(x: 16, y: 515, width: self.bounds.size.width, height: 20)) + func setEmptyMessage(_ message: String, isReshared: Bool) { + let messageLabel = UILabel(frame: CGRect(x: 16, y: isReshared ? 545 : 515, width: self.bounds.size.width, height: 20)) messageLabel.text = message messageLabel.textColor = NCBrandColor.shared.textInfo messageLabel.numberOfLines = 0 diff --git a/iOSClient/Share/NCSharePaging.swift b/iOSClient/Share/NCSharePaging.swift index 2676d08f2d..d7d919f084 100644 --- a/iOSClient/Share/NCSharePaging.swift +++ b/iOSClient/Share/NCSharePaging.swift @@ -312,7 +312,7 @@ class NCShareHeaderView: UIView { 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: "") + let resharingAllowedMessage = NSLocalizedString("_share_reshare_allowed_", comment: "") + " " + NSLocalizedString("_sharing_message_", comment: "") let resharingNotAllowedMessage = NSLocalizedString("_share_reshare_not_allowed_", comment: "") resharingAllowedLabel.text = canReshare ? resharingAllowedMessage : resharingNotAllowedMessage } From c584f197d4c04178c8c07c1e5060c32f95c46609 Mon Sep 17 00:00:00 2001 From: Shweta Waikar Date: Wed, 5 Jul 2023 16:47:38 +0530 Subject: [PATCH 18/24] NMC 1992 - Login url changes for Login Screen --- iOSClient/Share/ShareDownloadLimitNetwork.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/iOSClient/Share/ShareDownloadLimitNetwork.swift b/iOSClient/Share/ShareDownloadLimitNetwork.swift index c15fe512c1..41a55f9324 100644 --- a/iOSClient/Share/ShareDownloadLimitNetwork.swift +++ b/iOSClient/Share/ShareDownloadLimitNetwork.swift @@ -21,9 +21,10 @@ class NMCCommunication: NSObject, XMLParserDelegate { 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 = NCBrandOptions.shared.loginBaseUrl + let baseUrl = appDelegate?.urlBase ?? "" // NCBrandOptions.shared.loginBaseUrl let endPoint = "/ocs/v2.php/apps/files_downloadlimit/\(token)/limit" let path = baseUrl+endPoint do { @@ -61,7 +62,7 @@ class NMCCommunication: NSObject, XMLParserDelegate { } func setDownloadLimit(deleteLimit: Bool, limit: String, token: String, completion: @escaping (_ success: Bool, _ errorDescription: String) -> Void) { - let baseUrl = NCBrandOptions.shared.loginBaseUrl + let baseUrl = appDelegate?.urlBase ?? "" //NCBrandOptions.shared.loginBaseUrl let endPoint = "/ocs/v2.php/apps/files_downloadlimit/\(token)/limit" let path = baseUrl+endPoint do { From 32bb19b20f1b5313d4cca75eb8633b4197322e00 Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Wed, 19 Jul 2023 15:53:17 +0530 Subject: [PATCH 19/24] NMC 1992 - Configuration changes removed to avoid conflicts --- Nextcloud.xcodeproj/project.pbxproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index c4a396904d..a06a7f32a3 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -16,7 +16,6 @@ 370D26AF248A3D7A00121797 /* NCCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370D26AE248A3D7A00121797 /* NCCellProtocol.swift */; }; 371B5A2E23D0B04500FAFAE9 /* NCMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371B5A2D23D0B04500FAFAE9 /* NCMenu.swift */; }; 3781B9B023DB2B7E006B4B1D /* AppDelegate+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3781B9AF23DB2B7E006B4B1D /* AppDelegate+Menu.swift */; }; - 56548E2B2A49B95C00D58443 /* PasswordInputField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56548E2A2A49B95C00D58443 /* PasswordInputField.swift */; }; 8491B1CD273BBA82001C8C5B /* UIViewController+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8491B1CC273BBA82001C8C5B /* UIViewController+Menu.swift */; }; AF1A9B6427D0CA1E00F17A9E /* UIAlertController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1A9B6327D0CA1E00F17A9E /* UIAlertController+Extension.swift */; }; AF1A9B6527D0CC0500F17A9E /* UIAlertController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1A9B6327D0CA1E00F17A9E /* UIAlertController+Extension.swift */; }; @@ -793,7 +792,6 @@ 371B5A2D23D0B04500FAFAE9 /* NCMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMenu.swift; sourceTree = ""; }; 371B5A3223D0BD5500FAFAE9 /* FloatingPanel.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FloatingPanel.framework; path = Carthage/Build/iOS/FloatingPanel.framework; sourceTree = ""; }; 3781B9AF23DB2B7E006B4B1D /* AppDelegate+Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+Menu.swift"; sourceTree = ""; }; - 56548E2A2A49B95C00D58443 /* PasswordInputField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordInputField.swift; sourceTree = ""; }; 8491B1CC273BBA82001C8C5B /* UIViewController+Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Menu.swift"; sourceTree = ""; }; AF1A9B6327D0CA1E00F17A9E /* UIAlertController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIAlertController+Extension.swift"; sourceTree = ""; }; AF22B20B277C6F4D00DAB0CC /* NCShareCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareCell.swift; sourceTree = ""; }; @@ -1899,7 +1897,6 @@ F758B41E212C516300515F55 /* Scan document */ = { isa = PBXGroup; children = ( - 56548E2A2A49B95C00D58443 /* PasswordInputField.swift */, F758B457212C564000515F55 /* NCScan.storyboard */, F758B45D212C569C00515F55 /* NCScanCell.swift */, F758B45F212C56A400515F55 /* NCScan.swift */, @@ -3739,7 +3736,6 @@ F78071091EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m in Sources */, F79B646026CA661600838ACA /* UIControl+Extension.swift in Sources */, F7CA212D25F1333300826ABB /* NCAccountRequest.swift in Sources */, - 56548E2B2A49B95C00D58443 /* PasswordInputField.swift in Sources */, F765F73125237E3F00391DBE /* NCRecent.swift in Sources */, F76B3CCE1EAE01BD00921AC9 /* NCBrand.swift in Sources */, F359D8672A7D03420023F405 /* NCUtility+Exif.swift in Sources */, From 467406c9acf57153c1481208f6fa7429aa6e1f7b Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Mon, 31 Jul 2023 14:44:42 +0530 Subject: [PATCH 20/24] NMC 1992 - (NMC - 2388) - The Share Settings window appears empty after app in background --- iOSClient/Share/NCShare.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift index cf1ef2b00c..2e56a08def 100644 --- a/iOSClient/Share/NCShare.swift +++ b/iOSClient/Share/NCShare.swift @@ -70,6 +70,7 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent NotificationCenter.default.addObserver(self, selector: #selector(reloadData), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataNCShare), 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) + NotificationCenter.default.addObserver(self, selector: #selector(appWillEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil) guard let metadata = metadata else { return } reloadData() @@ -150,6 +151,9 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent textField?.layer.borderColor = NCBrandColor.shared.label.cgColor } + @objc func appWillEnterForeground(notification: Notification) { + reloadData() + } // MARK: - @objc func reloadData() { @@ -177,8 +181,8 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent } @IBAction func createLinkClicked(_ sender: Any) { -// appDelegate.adjust.trackEvent(TriggerEvent(CreateLink.rawValue)) -// TealiumHelper.shared.trackEvent(title: "magentacloud-app.sharing.create", data: ["": ""]) + appDelegate?.adjust.trackEvent(TriggerEvent(CreateLink.rawValue)) + TealiumHelper.shared.trackEvent(title: "magentacloud-app.sharing.create", data: ["": ""]) self.touchUpInsideButtonMenu(sender) } From 28e2431a9e34fe7fbf3afb2de658e84963d3fe3e Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Wed, 2 Aug 2023 11:56:15 +0530 Subject: [PATCH 21/24] NMC 1992 - share list not update after sharing with multiple users or links --- iOSClient/Share/NCShareNetworking.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/iOSClient/Share/NCShareNetworking.swift b/iOSClient/Share/NCShareNetworking.swift index f029f4ada5..edcb449874 100644 --- a/iOSClient/Share/NCShareNetworking.swift +++ b/iOSClient/Share/NCShareNetworking.swift @@ -50,6 +50,7 @@ class NCShareNetworking: NSObject { NextcloudKit.shared.readShares(parameters: parameter) { account, shares, data, error in if error == .success, let shares = shares { + NCManageDatabase.shared.deleteTableShare(account: account) let home = NCUtilityFileSystem.shared.getHomeServer(urlBase: self.metadata.urlBase, userId: self.metadata.userId) NCManageDatabase.shared.addShare(account: self.metadata.account, home:home, shares: shares) NextcloudKit.shared.getGroupfolders() { account, results, data, error in From 9472c46ee0240d57337944b87761b3fd0740e0f8 Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Mon, 18 Sep 2023 14:26:35 +0530 Subject: [PATCH 22/24] NMC 1992, NMC 2457 - file specific shares delete --- iOSClient/Data/NCManageDatabase+Share.swift | 18 ++++++++++++++++++ iOSClient/Share/NCShareNetworking.swift | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/iOSClient/Data/NCManageDatabase+Share.swift b/iOSClient/Data/NCManageDatabase+Share.swift index ab64d5e7f1..0db0ef12c7 100644 --- a/iOSClient/Data/NCManageDatabase+Share.swift +++ b/iOSClient/Data/NCManageDatabase+Share.swift @@ -260,6 +260,24 @@ extension NCManageDatabase { NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)") } } + + /// Delete shares of specific file + /// - Parameters: + /// - account: account url for specific user + /// - filePath: file path of media which shares need to delete + func deleteTableShare(account: String, filePath: String) { + + do { + let realm = try Realm() + + try realm.write { + let result = realm.objects(tableShare.self).filter("account == %@ AND path == %@", account, "/"+filePath) + realm.delete(result) + } + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)") + } + } // There is currently only one share attribute “download” from the scope “permissions”. This attribute is only valid for user and group shares, not for public link shares. func setAttibuteDownload(state: Bool) -> String? { diff --git a/iOSClient/Share/NCShareNetworking.swift b/iOSClient/Share/NCShareNetworking.swift index edcb449874..64078616e2 100644 --- a/iOSClient/Share/NCShareNetworking.swift +++ b/iOSClient/Share/NCShareNetworking.swift @@ -50,7 +50,7 @@ class NCShareNetworking: NSObject { NextcloudKit.shared.readShares(parameters: parameter) { account, shares, data, error in if error == .success, let shares = shares { - NCManageDatabase.shared.deleteTableShare(account: account) + NCManageDatabase.shared.deleteTableShare(account: account, filePath: filenamePath) let home = NCUtilityFileSystem.shared.getHomeServer(urlBase: self.metadata.urlBase, userId: self.metadata.userId) NCManageDatabase.shared.addShare(account: self.metadata.account, home:home, shares: shares) NextcloudKit.shared.getGroupfolders() { account, results, data, error in From 6d0ed19fb0d35712e1662685e0968f13fa708f51 Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Mon, 25 Sep 2023 12:55:16 +0530 Subject: [PATCH 23/24] NMC 1992 - NMC 2568 - Contact Button for Sharing --- .../contact.imageset/Contents.json | 12 +++ .../contact.imageset/contact.svg | 7 ++ iOSClient/Share/NCShare.swift | 49 ++++++++++ iOSClient/Share/NCShareEmailFieldCell.swift | 8 ++ iOSClient/Share/NCShareEmailFieldCell.xib | 92 +++++++++++-------- 5 files changed, 132 insertions(+), 36 deletions(-) create mode 100644 iOSClient/Images.xcassets/contact.imageset/Contents.json create mode 100644 iOSClient/Images.xcassets/contact.imageset/contact.svg diff --git a/iOSClient/Images.xcassets/contact.imageset/Contents.json b/iOSClient/Images.xcassets/contact.imageset/Contents.json new file mode 100644 index 0000000000..212bb4dfb1 --- /dev/null +++ b/iOSClient/Images.xcassets/contact.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "contact.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/contact.imageset/contact.svg b/iOSClient/Images.xcassets/contact.imageset/contact.svg new file mode 100644 index 0000000000..6b3f9684ae --- /dev/null +++ b/iOSClient/Images.xcassets/contact.imageset/contact.svg @@ -0,0 +1,7 @@ + + + 01_24px/icon/user_file/contacts/default + + + + \ No newline at end of file diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift index 2e56a08def..67c6d8c497 100644 --- a/iOSClient/Share/NCShare.swift +++ b/iOSClient/Share/NCShare.swift @@ -28,6 +28,7 @@ import Parchment import DropDown import NextcloudKit import MarqueeLabel +import ContactsUI class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent { @@ -214,6 +215,16 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent } + @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 NCGlobal.shared.capabilityFileSharingPubPasswdEnforced, shareType == NCShareCommon.shared.SHARE_TYPE_LINK || shareType == NCShareCommon.shared.SHARE_TYPE_EMAIL @@ -367,6 +378,7 @@ extension NCShare: UITableViewDataSource { 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) return cell } @@ -464,6 +476,43 @@ extension NCShare: UITableViewDataSource { } } +//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 { + textField?.text = email + networking?.getSharees(searchString: email) + } + } + + func contactPickerDidCancel(_ picker: CNContactPickerViewController) { + print("Cancel Contact Picker") + 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: NCUtility.shared.loadImage(named: "email").imageColor(NCBrandColor.shared.brandElement), + selected: false, + on: false, + action: { _ in + self.textField?.text = email + self.networking?.getSharees(searchString: email) + } + ) + ) + } + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + self.presentMenu(with: actions) + } + } +} extension UITableView { func setEmptyMessage(_ message: String, isReshared: Bool) { diff --git a/iOSClient/Share/NCShareEmailFieldCell.swift b/iOSClient/Share/NCShareEmailFieldCell.swift index 62fe1d949c..89f9c7e9f6 100644 --- a/iOSClient/Share/NCShareEmailFieldCell.swift +++ b/iOSClient/Share/NCShareEmailFieldCell.swift @@ -17,6 +17,7 @@ class NCShareEmailFieldCell: UITableViewCell { @IBOutlet weak var btnCreateLink: UIButton! @IBOutlet weak var labelYourShare: UILabel! @IBOutlet weak var labelShareByMail: UILabel! + @IBOutlet weak var btnContact: UIButton! override func awakeFromNib() { super.awakeFromNib() @@ -57,6 +58,13 @@ class NCShareEmailFieldCell: UITableViewCell { 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(UIImage(named: "contact"), for: .normal) } @objc func cancelDatePicker() { diff --git a/iOSClient/Share/NCShareEmailFieldCell.xib b/iOSClient/Share/NCShareEmailFieldCell.xib index 94b906da57..f80d9db660 100644 --- a/iOSClient/Share/NCShareEmailFieldCell.xib +++ b/iOSClient/Share/NCShareEmailFieldCell.xib @@ -1,94 +1,114 @@ - + - + + - + - + - + - - + + - + - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - + + + + - + - - - - + + + + + + + + + + + From 6386b22b82e6675553c1433c83303af181b5e076 Mon Sep 17 00:00:00 2001 From: Amrut Waghmare Date: Wed, 27 Sep 2023 15:38:08 +0530 Subject: [PATCH 24/24] NMC1992 - sharing - 2568 - Reshare message overlapping and contact icon color in dark mode --- iOSClient/Share/NCShare.swift | 1 - iOSClient/Share/NCShareEmailFieldCell.swift | 2 +- iOSClient/Share/NCSharePaging.swift | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift index 67c6d8c497..bb8bd42c21 100644 --- a/iOSClient/Share/NCShare.swift +++ b/iOSClient/Share/NCShare.swift @@ -488,7 +488,6 @@ extension NCShare: CNContactPickerDelegate { } func contactPickerDidCancel(_ picker: CNContactPickerViewController) { - print("Cancel Contact Picker") self.keyboardWillHide(notification: Notification(name: Notification.Name("dismiss"))) } diff --git a/iOSClient/Share/NCShareEmailFieldCell.swift b/iOSClient/Share/NCShareEmailFieldCell.swift index 89f9c7e9f6..4acb9fc787 100644 --- a/iOSClient/Share/NCShareEmailFieldCell.swift +++ b/iOSClient/Share/NCShareEmailFieldCell.swift @@ -64,7 +64,7 @@ class NCShareEmailFieldCell: UITableViewCell { btnContact.layer.borderWidth = 1 btnContact.layer.borderColor = NCBrandColor.shared.label.cgColor btnContact.tintColor = NCBrandColor.shared.label - btnContact.setImage(UIImage(named: "contact"), for: .normal) + btnContact.setImage(NCUtility.shared.loadImage(named: "contact").image(color: NCBrandColor.shared.label, size: 24), for: .normal) } @objc func cancelDatePicker() { diff --git a/iOSClient/Share/NCSharePaging.swift b/iOSClient/Share/NCSharePaging.swift index d7d919f084..ad37aa29e9 100644 --- a/iOSClient/Share/NCSharePaging.swift +++ b/iOSClient/Share/NCSharePaging.swift @@ -293,7 +293,7 @@ class NCShareHeaderView: UIView { labelSharing.text = NSLocalizedString("_sharing_", comment: "") labelSharingInfo.text = NSLocalizedString("_sharing_message_", comment: "") - if UIScreen.main.bounds.width < 350 { + if UIScreen.main.bounds.width < 376 { constraintTopSharingLabel.constant = 15 } }