Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/ios.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarino Faggiana <ios@nextcloud.com>2022-08-17 16:47:15 +0300
committerGitHub <noreply@github.com>2022-08-17 16:47:15 +0300
commit8ac246aa2169c65fad90731833dd2391c9b5ecef (patch)
tree42ba7ce9003ea8e1e5fe27868ae0311b52745ba4
parente2e52363b045d31542c49c5e12bf517362b69df2 (diff)
parentd75ad526259d469b2ba4cceb91a1a5cb86030c56 (diff)
Merge pull request #2120 from nextcloud/develop4.4.1
Version 4.4.1
-rw-r--r--.swiftlint.yml7
-rw-r--r--Animation.gifbin983612 -> 930295 bytes
-rw-r--r--Cartfile.resolved2
-rw-r--r--File Provider Extension/FileProviderData.swift2
-rw-r--r--File Provider Extension/FileProviderExtension.swift2
-rw-r--r--Nextcloud.xcodeproj/project.pbxproj180
-rw-r--r--README.md17
-rw-r--r--Share/NCShareExtension+DataSource.swift13
-rw-r--r--Share/NCShareExtension+Files.swift16
-rw-r--r--Share/NCShareExtension+NCDelegate.swift4
-rw-r--r--Share/NCShareExtension.swift20
-rw-r--r--iOSClient/Account Request/NCAccountRequest.storyboard (renamed from iOSClient/Main/Account Request/NCAccountRequest.storyboard)0
-rw-r--r--iOSClient/Account Request/NCAccountRequest.swift (renamed from iOSClient/Main/Account Request/NCAccountRequest.swift)27
-rw-r--r--iOSClient/Activity/NCActivity.swift52
-rw-r--r--iOSClient/Activity/NCActivityTableViewCell.swift84
-rw-r--r--iOSClient/AppDelegate.swift52
-rw-r--r--iOSClient/BackgroundImageColor/NCBackgroundImageColor.storyboard257
-rw-r--r--iOSClient/BackgroundImageColor/NCBackgroundImageColor.swift298
-rwxr-xr-xiOSClient/Brand/NCBrand.swift224
-rw-r--r--iOSClient/Brand/Nextcloud-Bridging-Header.h (renamed from iOSClient/Nextcloud-Bridging-Header.h)0
-rwxr-xr-xiOSClient/Brand/iOSClient.plist6
-rw-r--r--iOSClient/Color/NCColorPicker.storyboard293
-rw-r--r--iOSClient/Color/NCColorPicker.swift224
-rw-r--r--iOSClient/Data/NCDataSource.swift569
-rw-r--r--iOSClient/Data/NCDatabase.swift20
-rw-r--r--iOSClient/Data/NCManageDatabase+Account.swift72
-rw-r--r--iOSClient/Data/NCManageDatabase+Activity.swift32
-rw-r--r--iOSClient/Data/NCManageDatabase+Metadata.swift49
-rw-r--r--iOSClient/Data/NCManageDatabase.swift84
-rw-r--r--iOSClient/Diagnostics/NCCapabilitiesViewController.swift37
-rw-r--r--iOSClient/EmptyView/NCEmptyDataSet.swift21
-rw-r--r--iOSClient/Extensions/Array+Extensions.swift41
-rw-r--r--iOSClient/Extensions/String+Extensions.swift4
-rw-r--r--iOSClient/Extensions/UIImage+Extensions.swift13
-rw-r--r--iOSClient/Extensions/UINavigationController+Extension.swift32
-rw-r--r--iOSClient/Extensions/UITabBarController+Extension.swift32
-rw-r--r--iOSClient/Extensions/UIViewController+Extension.swift64
-rw-r--r--iOSClient/Favorites/NCFavorite.swift37
-rw-r--r--iOSClient/FileViewInFolder/NCFileViewInFolder.storyboard53
-rw-r--r--iOSClient/FileViewInFolder/NCFileViewInFolder.swift152
-rw-r--r--iOSClient/Files/NCFiles.swift120
-rw-r--r--iOSClient/Images.xcassets/buttonAddFolder.imageset/Contents.json23
-rw-r--r--iOSClient/Images.xcassets/buttonAddFolder.imageset/icons8-add-folder-24(@1x).pngbin0 -> 296 bytes
-rw-r--r--iOSClient/Images.xcassets/buttonAddFolder.imageset/icons8-add-folder-48(@2x)-1.pngbin0 -> 429 bytes
-rw-r--r--iOSClient/Images.xcassets/buttonAddFolder.imageset/icons8-add-folder-72(@3x).pngbin0 -> 617 bytes
-rw-r--r--iOSClient/Images.xcassets/buttonAddImage.imageset/Contents.json23
-rw-r--r--iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image-upload-24(@1x).pngbin0 -> 641 bytes
-rw-r--r--iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image-upload-48(@2x).pngbin0 -> 1191 bytes
-rw-r--r--iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image-upload-72(@3x).pngbin0 -> 2035 bytes
-rw-r--r--iOSClient/Images.xcassets/buttonAddScan.imageset/Contents.json23
-rw-r--r--iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan-24(@1x).pngbin0 -> 798 bytes
-rw-r--r--iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan-48(@2x).pngbin0 -> 905 bytes
-rw-r--r--iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan-72(@3x).pngbin0 -> 1308 bytes
-rw-r--r--iOSClient/Images.xcassets/icon-calendar.imageset/Contents.json12
-rw-r--r--iOSClient/Images.xcassets/icon-calendar.imageset/icons8-calendario.svg1
-rw-r--r--iOSClient/Images.xcassets/icon-confirm.imageset/Contents.json12
-rw-r--r--iOSClient/Images.xcassets/icon-confirm.imageset/icon-confirm.svg1
-rw-r--r--iOSClient/Images.xcassets/icon-contacts.imageset/Contents.json12
-rw-r--r--iOSClient/Images.xcassets/icon-contacts.imageset/icons8-gruppo-utente-uomo-uomo.svg1
-rw-r--r--iOSClient/Images.xcassets/icon-deck.imageset/Contents.json12
-rw-r--r--iOSClient/Images.xcassets/icon-deck.imageset/deck.svg9
-rw-r--r--iOSClient/Images.xcassets/icon-mail.imageset/Contents.json12
-rw-r--r--iOSClient/Images.xcassets/icon-mail.imageset/icons8-nuovo-messaggio.svg1
-rw-r--r--iOSClient/Images.xcassets/icon-pages.imageset/Contents.json12
-rw-r--r--iOSClient/Images.xcassets/icon-pages.imageset/icon-pages.svg1
-rw-r--r--iOSClient/Images.xcassets/icon-talk.imageset/Contents.json12
-rw-r--r--iOSClient/Images.xcassets/icon-talk.imageset/app-dark.svg1
-rw-r--r--iOSClient/Images.xcassets/palette.imageset/Contents.json12
-rw-r--r--iOSClient/Images.xcassets/palette.imageset/palette.svg1
-rw-r--r--iOSClient/Images.xcassets/rgb.imageset/Contents.json12
-rw-r--r--iOSClient/Images.xcassets/rgb.imageset/rgb.svg1
-rw-r--r--iOSClient/Login/NCLogin.swift2
-rw-r--r--iOSClient/Login/NCLoginWeb.swift26
-rw-r--r--iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift19
-rw-r--r--iOSClient/Main/Collection Common/NCCollectionViewCommon.swift1593
-rw-r--r--iOSClient/Main/Collection Common/NCGridCell.swift88
-rw-r--r--iOSClient/Main/Collection Common/NCGridCell.xib54
-rwxr-xr-xiOSClient/Main/Collection Common/NCListCell.swift104
-rwxr-xr-xiOSClient/Main/Collection Common/NCListCell.xib6
-rw-r--r--iOSClient/Main/Collection Common/NCSelectableNavigationView.swift10
-rw-r--r--iOSClient/Main/Create cloud/NCCreateFormUploadAssets.swift89
-rw-r--r--iOSClient/Main/Create cloud/NCCreateFormUploadConflict.swift83
-rw-r--r--iOSClient/Main/Create cloud/NCCreateFormUploadDocuments.swift89
-rw-r--r--iOSClient/Main/Create cloud/NCCreateFormUploadScanDocument.swift43
-rw-r--r--iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift26
-rw-r--r--iOSClient/Main/NCCellProtocol.swift92
-rw-r--r--iOSClient/Main/NCFunctionCenter.swift168
-rw-r--r--iOSClient/Main/NCMainNavigationController.swift20
-rw-r--r--iOSClient/Main/NCMainTabBar.swift32
-rw-r--r--iOSClient/Main/NCPickerViewController.swift3
-rw-r--r--iOSClient/Main/Section Header Footer/NCSectionFooter.xib59
-rw-r--r--iOSClient/Main/Section Header Footer/NCSectionHeader.xib (renamed from iOSClient/Trash/Section/NCTrashSectionFooter.xib)25
-rw-r--r--iOSClient/Main/Section Header Footer/NCSectionHeaderFooter.swift321
-rw-r--r--iOSClient/Main/Section Header Footer/NCSectionHeaderMenu.xib168
-rw-r--r--iOSClient/Media/Cell/NCGridMediaCell.swift26
-rw-r--r--iOSClient/Media/NCMedia.swift156
-rw-r--r--iOSClient/Menu/NCCollectionViewCommon+Menu.swift57
-rw-r--r--iOSClient/Menu/NCMedia+Menu.swift4
-rw-r--r--iOSClient/Menu/NCMenuAction.swift8
-rw-r--r--iOSClient/Menu/NCViewer+Menu.swift2
-rw-r--r--iOSClient/Menu/UIViewController+Menu.swift2
-rw-r--r--iOSClient/NCGlobal.swift62
-rw-r--r--iOSClient/Networking/NCAutoUpload.swift266
-rw-r--r--iOSClient/Networking/NCNetworking.swift719
-rw-r--r--iOSClient/Networking/NCNetworkingCheckRemoteUser.swift7
-rw-r--r--iOSClient/Networking/NCNetworkingChunkedUpload.swift212
-rw-r--r--iOSClient/Networking/NCNetworkingE2EE.swift34
-rw-r--r--iOSClient/Networking/NCNetworkingProcessUpload.swift167
-rw-r--r--iOSClient/Networking/NCOperationQueue.swift300
-rw-r--r--iOSClient/Networking/NCService.swift255
-rw-r--r--iOSClient/Notification/NCNotification.swift44
-rw-r--r--iOSClient/Offline/NCOffline.swift96
-rw-r--r--iOSClient/Recent/NCRecent.swift27
-rw-r--r--iOSClient/Rename file/NCRenameFile.swift12
-rw-r--r--iOSClient/RichWorkspace/NCRichWorkspaceCommon.swift8
-rw-r--r--iOSClient/RichWorkspace/NCViewerRichWorkspace.swift11
-rwxr-xr-xiOSClient/ScanDocument/NCScan.swift51
-rw-r--r--iOSClient/Select/NCSelect.swift272
-rwxr-xr-xiOSClient/Settings/CCAdvanced.m51
-rw-r--r--iOSClient/Settings/NCEndToEndInitialize.swift8
-rw-r--r--iOSClient/Settings/NCManageAutoUploadFileName.swift1
-rw-r--r--iOSClient/Settings/NCManageEndToEndEncryption.m7
-rw-r--r--iOSClient/Settings/NCSettings.m6
-rw-r--r--iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.swift10
-rw-r--r--iOSClient/Share/NCShare+NCCellDelegate.swift2
-rw-r--r--iOSClient/Share/NCShare.swift12
-rw-r--r--iOSClient/Share/NCShareCommentsCell.swift9
-rw-r--r--iOSClient/Share/NCShareNetworking.swift20
-rw-r--r--iOSClient/Share/NCSharePaging.swift17
-rw-r--r--iOSClient/Share/NCShareUserCell.swift26
-rw-r--r--iOSClient/Shares/NCShares.swift27
-rw-r--r--iOSClient/Supporting Files/af.lproj/Localizable.stringsbin106806 -> 111880 bytes
-rw-r--r--iOSClient/Supporting Files/an.lproj/InfoPlist.strings (renamed from iOSClient/Supporting Files/kk.lproj/InfoPlist.strings)bin1696 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/an.lproj/Localizable.strings (renamed from iOSClient/Supporting Files/kk.lproj/Localizable.strings)bin106160 -> 111234 bytes
-rw-r--r--iOSClient/Supporting Files/ar.lproj/Localizable.stringsbin104208 -> 109312 bytes
-rw-r--r--iOSClient/Supporting Files/ast.lproj/Localizable.stringsbin107106 -> 112190 bytes
-rw-r--r--iOSClient/Supporting Files/az.lproj/Localizable.stringsbin106500 -> 111558 bytes
-rw-r--r--iOSClient/Supporting Files/be.lproj/Localizable.stringsbin106250 -> 111320 bytes
-rw-r--r--iOSClient/Supporting Files/bg_BG.lproj/Localizable.stringsbin112782 -> 118496 bytes
-rw-r--r--iOSClient/Supporting Files/bn_BD.lproj/Localizable.stringsbin106412 -> 111486 bytes
-rw-r--r--iOSClient/Supporting Files/br.lproj/Localizable.stringsbin110822 -> 115856 bytes
-rw-r--r--iOSClient/Supporting Files/bs.lproj/Localizable.stringsbin106476 -> 111548 bytes
-rw-r--r--iOSClient/Supporting Files/ca.lproj/Localizable.stringsbin113582 -> 118536 bytes
-rw-r--r--iOSClient/Supporting Files/cs-CZ.lproj/Localizable.stringsbin109294 -> 114622 bytes
-rw-r--r--iOSClient/Supporting Files/cy_GB.lproj/Localizable.stringsbin106432 -> 111508 bytes
-rw-r--r--iOSClient/Supporting Files/da.lproj/Localizable.stringsbin106766 -> 111828 bytes
-rw-r--r--iOSClient/Supporting Files/de.lproj/Localizable.stringsbin116136 -> 121602 bytes
-rw-r--r--iOSClient/Supporting Files/el.lproj/Localizable.stringsbin117476 -> 122264 bytes
-rw-r--r--iOSClient/Supporting Files/en-GB.lproj/Localizable.stringsbin106270 -> 111338 bytes
-rw-r--r--iOSClient/Supporting Files/en.lproj/Localizable.strings63
-rw-r--r--iOSClient/Supporting Files/eo.lproj/Localizable.stringsbin106914 -> 111982 bytes
-rw-r--r--iOSClient/Supporting Files/es-419.lproj/Localizable.stringsbin110312 -> 115354 bytes
-rw-r--r--iOSClient/Supporting Files/es-AR.lproj/Localizable.stringsbin109306 -> 114400 bytes
-rw-r--r--iOSClient/Supporting Files/es-CL.lproj/Localizable.stringsbin110944 -> 116284 bytes
-rw-r--r--iOSClient/Supporting Files/es-CO.lproj/Localizable.stringsbin110952 -> 115940 bytes
-rw-r--r--iOSClient/Supporting Files/es-CR.lproj/Localizable.stringsbin110942 -> 115930 bytes
-rw-r--r--iOSClient/Supporting Files/es-DO.lproj/Localizable.stringsbin110950 -> 115938 bytes
-rw-r--r--iOSClient/Supporting Files/es-EC.lproj/Localizable.stringsbin110948 -> 115936 bytes
-rw-r--r--iOSClient/Supporting Files/es-GT.lproj/Localizable.stringsbin110942 -> 115932 bytes
-rw-r--r--iOSClient/Supporting Files/es-HN.lproj/Localizable.stringsbin110304 -> 115344 bytes
-rw-r--r--iOSClient/Supporting Files/es-MX.lproj/Localizable.stringsbin111128 -> 116116 bytes
-rw-r--r--iOSClient/Supporting Files/es-NI.lproj/Localizable.stringsbin110294 -> 115334 bytes
-rw-r--r--iOSClient/Supporting Files/es-PA.lproj/Localizable.stringsbin110294 -> 115334 bytes
-rw-r--r--iOSClient/Supporting Files/es-PE.lproj/Localizable.stringsbin110294 -> 115334 bytes
-rw-r--r--iOSClient/Supporting Files/es-PR.lproj/Localizable.stringsbin110294 -> 115334 bytes
-rw-r--r--iOSClient/Supporting Files/es-PY.lproj/Localizable.stringsbin110320 -> 115360 bytes
-rw-r--r--iOSClient/Supporting Files/es-SV.lproj/Localizable.stringsbin110942 -> 115930 bytes
-rw-r--r--iOSClient/Supporting Files/es-UY.lproj/Localizable.stringsbin110318 -> 115358 bytes
-rw-r--r--iOSClient/Supporting Files/es.lproj/Localizable.stringsbin113708 -> 119316 bytes
-rw-r--r--iOSClient/Supporting Files/et_EE.lproj/Localizable.stringsbin106706 -> 111796 bytes
-rw-r--r--iOSClient/Supporting Files/eu.lproj/Localizable.stringsbin113150 -> 118394 bytes
-rw-r--r--iOSClient/Supporting Files/fa.lproj/Localizable.stringsbin107034 -> 112090 bytes
-rw-r--r--iOSClient/Supporting Files/fi-FI.lproj/Localizable.stringsbin108998 -> 114086 bytes
-rw-r--r--iOSClient/Supporting Files/fo.lproj/Localizable.stringsbin106174 -> 111250 bytes
-rw-r--r--iOSClient/Supporting Files/fr.lproj/InfoPlist.stringsbin1856 -> 2058 bytes
-rw-r--r--iOSClient/Supporting Files/fr.lproj/Localizable.stringsbin117844 -> 123344 bytes
-rw-r--r--iOSClient/Supporting Files/gd.lproj/Localizable.stringsbin107690 -> 112778 bytes
-rw-r--r--iOSClient/Supporting Files/gl.lproj/Localizable.stringsbin113324 -> 118244 bytes
-rw-r--r--iOSClient/Supporting Files/he.lproj/Localizable.stringsbin104242 -> 109310 bytes
-rw-r--r--iOSClient/Supporting Files/hi_IN.lproj/Localizable.stringsbin106160 -> 111226 bytes
-rw-r--r--iOSClient/Supporting Files/hr.lproj/Localizable.stringsbin111286 -> 116382 bytes
-rw-r--r--iOSClient/Supporting Files/hsb.lproj/Localizable.stringsbin106164 -> 111232 bytes
-rw-r--r--iOSClient/Supporting Files/hu.lproj/Localizable.stringsbin111692 -> 117032 bytes
-rw-r--r--iOSClient/Supporting Files/hy.lproj/Localizable.stringsbin106450 -> 111504 bytes
-rw-r--r--iOSClient/Supporting Files/ia.lproj/Localizable.stringsbin106880 -> 111966 bytes
-rw-r--r--iOSClient/Supporting Files/id.lproj/Localizable.stringsbin106966 -> 112060 bytes
-rw-r--r--iOSClient/Supporting Files/ig.lproj/Localizable.stringsbin106148 -> 111214 bytes
-rw-r--r--iOSClient/Supporting Files/is.lproj/Localizable.stringsbin108416 -> 113510 bytes
-rw-r--r--iOSClient/Supporting Files/it.lproj/Localizable.stringsbin113536 -> 119042 bytes
-rw-r--r--iOSClient/Supporting Files/ja-JP.lproj/Localizable.stringsbin88866 -> 93230 bytes
-rw-r--r--iOSClient/Supporting Files/ka-GE.lproj/Localizable.stringsbin109032 -> 114122 bytes
-rw-r--r--iOSClient/Supporting Files/ka.lproj/Localizable.stringsbin106164 -> 111230 bytes
-rw-r--r--iOSClient/Supporting Files/kab.lproj/Localizable.stringsbin106224 -> 111298 bytes
-rw-r--r--iOSClient/Supporting Files/km.lproj/Localizable.stringsbin106402 -> 111482 bytes
-rw-r--r--iOSClient/Supporting Files/kn.lproj/Localizable.stringsbin106644 -> 111710 bytes
-rw-r--r--iOSClient/Supporting Files/ko.lproj/Localizable.stringsbin88148 -> 93640 bytes
-rw-r--r--iOSClient/Supporting Files/la.lproj/Localizable.stringsbin106150 -> 111216 bytes
-rw-r--r--iOSClient/Supporting Files/lb.lproj/Localizable.stringsbin106538 -> 111606 bytes
-rw-r--r--iOSClient/Supporting Files/lo.lproj/Localizable.stringsbin104580 -> 109722 bytes
-rw-r--r--iOSClient/Supporting Files/lt_LT.lproj/Localizable.stringsbin108934 -> 114036 bytes
-rw-r--r--iOSClient/Supporting Files/lv.lproj/Localizable.stringsbin107178 -> 112256 bytes
-rw-r--r--iOSClient/Supporting Files/mk.lproj/Localizable.stringsbin107492 -> 112556 bytes
-rw-r--r--iOSClient/Supporting Files/mn.lproj/Localizable.stringsbin106896 -> 111990 bytes
-rw-r--r--iOSClient/Supporting Files/mr.lproj/Localizable.stringsbin106134 -> 111206 bytes
-rw-r--r--iOSClient/Supporting Files/ms_MY.lproj/Localizable.stringsbin106264 -> 111346 bytes
-rw-r--r--iOSClient/Supporting Files/my.lproj/Localizable.stringsbin106340 -> 111406 bytes
-rw-r--r--iOSClient/Supporting Files/nb-NO.lproj/Localizable.stringsbin107262 -> 112272 bytes
-rw-r--r--iOSClient/Supporting Files/ne.lproj/Localizable.stringsbin106174 -> 111246 bytes
-rw-r--r--iOSClient/Supporting Files/nl.lproj/Localizable.stringsbin111474 -> 116584 bytes
-rw-r--r--iOSClient/Supporting Files/nn_NO.lproj/Localizable.stringsbin106306 -> 111374 bytes
-rw-r--r--iOSClient/Supporting Files/oc.lproj/Localizable.stringsbin107164 -> 112296 bytes
-rw-r--r--iOSClient/Supporting Files/pl.lproj/Localizable.stringsbin110928 -> 116106 bytes
-rw-r--r--iOSClient/Supporting Files/ps.lproj/Localizable.stringsbin106188 -> 111258 bytes
-rw-r--r--iOSClient/Supporting Files/pt-BR.lproj/Localizable.stringsbin111830 -> 117272 bytes
-rw-r--r--iOSClient/Supporting Files/pt-PT.lproj/InfoPlist.stringsbin1696 -> 1884 bytes
-rw-r--r--iOSClient/Supporting Files/pt-PT.lproj/Localizable.stringsbin110254 -> 115322 bytes
-rw-r--r--iOSClient/Supporting Files/ro.lproj/Localizable.stringsbin109270 -> 114342 bytes
-rw-r--r--iOSClient/Supporting Files/ru.lproj/InfoPlist.stringsbin1696 -> 1782 bytes
-rw-r--r--iOSClient/Supporting Files/ru.lproj/Localizable.stringsbin111444 -> 116626 bytes
-rw-r--r--iOSClient/Supporting Files/sc.lproj/Localizable.stringsbin115784 -> 120826 bytes
-rw-r--r--iOSClient/Supporting Files/si.lproj/Localizable.stringsbin107074 -> 112158 bytes
-rw-r--r--iOSClient/Supporting Files/sk-SK.lproj/InfoPlist.stringsbin1792 -> 1824 bytes
-rw-r--r--iOSClient/Supporting Files/sk-SK.lproj/Localizable.stringsbin110388 -> 115570 bytes
-rw-r--r--iOSClient/Supporting Files/sl.lproj/InfoPlist.stringsbin1696 -> 1776 bytes
-rw-r--r--iOSClient/Supporting Files/sl.lproj/Localizable.stringsbin111982 -> 117304 bytes
-rw-r--r--iOSClient/Supporting Files/sq.lproj/Localizable.stringsbin107894 -> 112986 bytes
-rw-r--r--iOSClient/Supporting Files/sr.lproj/Localizable.stringsbin107886 -> 112886 bytes
-rw-r--r--iOSClient/Supporting Files/sr@latin.lproj/Localizable.stringsbin106470 -> 111534 bytes
-rw-r--r--iOSClient/Supporting Files/sv.lproj/Localizable.stringsbin108108 -> 113022 bytes
-rw-r--r--iOSClient/Supporting Files/sw.lproj/Localizable.stringsbin106160 -> 111226 bytes
-rw-r--r--iOSClient/Supporting Files/ta.lproj/Localizable.stringsbin106476 -> 111542 bytes
-rw-r--r--iOSClient/Supporting Files/th_TH.lproj/Localizable.stringsbin106568 -> 111630 bytes
-rw-r--r--iOSClient/Supporting Files/tk.lproj/Localizable.stringsbin106840 -> 111912 bytes
-rw-r--r--iOSClient/Supporting Files/tr.lproj/Localizable.stringsbin110194 -> 115556 bytes
-rw-r--r--iOSClient/Supporting Files/ug.lproj/Localizable.stringsbin106334 -> 111392 bytes
-rw-r--r--iOSClient/Supporting Files/uk.lproj/Localizable.stringsbin107530 -> 112614 bytes
-rw-r--r--iOSClient/Supporting Files/ur_PK.lproj/Localizable.stringsbin106198 -> 111264 bytes
-rw-r--r--iOSClient/Supporting Files/uz.lproj/Localizable.stringsbin106642 -> 111708 bytes
-rw-r--r--iOSClient/Supporting Files/vi.lproj/Localizable.stringsbin107004 -> 112092 bytes
-rw-r--r--iOSClient/Supporting Files/zh-Hans.lproj/Localizable.stringsbin79466 -> 83920 bytes
-rw-r--r--iOSClient/Supporting Files/zh-Hant-TW.lproj/InfoPlist.stringsbin1696 -> 916 bytes
-rw-r--r--iOSClient/Supporting Files/zh-Hant-TW.lproj/Localizable.stringsbin83444 -> 89044 bytes
-rw-r--r--iOSClient/Supporting Files/zh_HK.lproj/Localizable.stringsbin79802 -> 83558 bytes
-rwxr-xr-xiOSClient/Transfers/NCTransferCell.swift55
-rw-r--r--iOSClient/Transfers/NCTransfers.swift107
-rw-r--r--iOSClient/Trash/Cell/NCTrashListCell+NCTrashCellProtocol.swift (renamed from iOSClient/Trash/Cell/NCTrashListCell.swift)28
-rw-r--r--iOSClient/Trash/NCTrash+CollectionView.swift123
-rw-r--r--iOSClient/Trash/NCTrash.swift170
-rw-r--r--iOSClient/Trash/Section/NCTrashSectionHeaderFooter.swift139
-rw-r--r--iOSClient/Trash/Section/NCTrashSectionHeaderMenu.xib91
-rw-r--r--iOSClient/UserStatus/NCUserStatus.storyboard23
-rw-r--r--iOSClient/UserStatus/NCUserStatus.swift23
-rw-r--r--iOSClient/Utility/CCUtility.h15
-rw-r--r--iOSClient/Utility/CCUtility.m248
-rw-r--r--iOSClient/Utility/NCActivityIndicator.swift148
-rw-r--r--iOSClient/Utility/NCContentPresenter.swift48
-rw-r--r--iOSClient/Utility/NCUserBaseUrl.swift6
-rw-r--r--iOSClient/Utility/NCUtility+Image.swift6
-rw-r--r--iOSClient/Utility/NCUtility.swift316
-rw-r--r--iOSClient/Utility/NCUtilityFileSystem.swift9
-rw-r--r--iOSClient/Utility/ParallelWorker.swift2
-rw-r--r--iOSClient/Utility/ThreadSafeDictionary.swift65
-rw-r--r--iOSClient/Viewer/NCViewer.swift36
-rw-r--r--iOSClient/Viewer/NCViewerMedia/NCPlayer/NCKTVHTTPCache.swift2
-rw-r--r--iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift2
-rw-r--r--iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift18
-rw-r--r--iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift150
-rw-r--r--iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift7
-rw-r--r--iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.storyboard4
-rw-r--r--iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.swift164
-rw-r--r--iOSClient/Viewer/NCViewerNextcloudText/NCViewerNextcloudText.swift15
-rw-r--r--iOSClient/Viewer/NCViewerPDF/NCViewerPDF.swift95
-rw-r--r--iOSClient/Viewer/NCViewerPDF/NCViewerPDFSearch.swift2
-rw-r--r--iOSClient/Viewer/NCViewerProviderContextMenu.swift62
-rw-r--r--iOSClient/Viewer/NCViewerQuickLook/NCViewerQuickLook.swift9
-rw-r--r--iOSClient/Viewer/NCViewerRichdocument/NCViewerRichdocument.swift19
276 files changed, 6512 insertions, 5278 deletions
diff --git a/.swiftlint.yml b/.swiftlint.yml
index ac6e392d4..296f31a28 100644
--- a/.swiftlint.yml
+++ b/.swiftlint.yml
@@ -24,7 +24,9 @@ type_body_length:
identifier_name:
min_length: 0
-
+
+disabled_rules:
+ - unused_setter_value
excluded:
- Carthage
@@ -58,9 +60,7 @@ excluded:
- iOSClient/EmptyView/NCEmptyDataSet.swift
- iOSClient/Extensions/UIColor+Extensions.swift
- iOSClient/Extensions/UIImage+Extensions.swift
- - iOSClient/Favorites/NCFavorite.swift
- iOSClient/FileViewInFolder/NCFileViewInFolder.swift
- - iOSClient/Files/NCFiles.swift
- iOSClient/Login/NCAppConfigView.swift
- iOSClient/Login/NCLogin.swift
- iOSClient/Login/NCLoginWeb.swift
@@ -99,7 +99,6 @@ excluded:
- iOSClient/Networking/NCOperationQueue.swift
- iOSClient/Networking/NCService.swift
- iOSClient/Notification/NCNotification.swift
- - iOSClient/Offline/NCOffline.swift
- iOSClient/Recent/NCRecent.swift
- iOSClient/Rename file/NCRenameFile.swift
- iOSClient/RichWorkspace/NCRichWorkspaceCommon.swift
diff --git a/Animation.gif b/Animation.gif
index a0c22d2e1..0b830a9d3 100644
--- a/Animation.gif
+++ b/Animation.gif
Binary files differ
diff --git a/Cartfile.resolved b/Cartfile.resolved
index ce55f69c1..5124bceca 100644
--- a/Cartfile.resolved
+++ b/Cartfile.resolved
@@ -1,3 +1,3 @@
-github "krzyzanowskim/OpenSSL" "1.1.1300"
+github "krzyzanowskim/OpenSSL" "1.1.1700"
github "marinofaggiana/KTVHTTPCache" "2.0.5"
github "marinofaggiana/TOPasscodeViewController" "a1b9d1058b2648e636525fc368e220a0cfddb42a"
diff --git a/File Provider Extension/FileProviderData.swift b/File Provider Extension/FileProviderData.swift
index 509c86d69..0bfc1d1d8 100644
--- a/File Provider Extension/FileProviderData.swift
+++ b/File Provider Extension/FileProviderData.swift
@@ -81,7 +81,7 @@ class fileProviderData: NSObject {
let levelLog = CCUtility.getLogLevel()
NCCommunicationCommon.shared.levelLog = levelLog
let version = NSString(format: NCBrandOptions.shared.textCopyrightNextcloudiOS as NSString, NCUtility.shared.getVersionApp()) as String
- NCCommunicationCommon.shared.writeLog("Start session with level \(levelLog) " + version + " (File Provider Extension)")
+ NCCommunicationCommon.shared.writeLog("Start File Provider session with level \(levelLog) " + version + " (File Provider Extension)")
}
// NO DOMAIN -> Set default account
diff --git a/File Provider Extension/FileProviderExtension.swift b/File Provider Extension/FileProviderExtension.swift
index 2e003945f..9643b4fdd 100644
--- a/File Provider Extension/FileProviderExtension.swift
+++ b/File Provider Extension/FileProviderExtension.swift
@@ -347,7 +347,7 @@ class FileProviderExtension: NSFileProviderExtension, NCNetworkingDelegate {
fileURL.stopAccessingSecurityScopedResource()
- let metadata = NCManageDatabase.shared.createMetadata(account: fileProviderData.shared.account, user: fileProviderData.shared.user, userId: fileProviderData.shared.userId, fileName: fileName, fileNameView: fileName, ocId: ocIdTemp, serverUrl: tableDirectory.serverUrl, urlBase: fileProviderData.shared.accountUrlBase, url: "", contentType: "", livePhoto: false)
+ let metadata = NCManageDatabase.shared.createMetadata(account: fileProviderData.shared.account, user: fileProviderData.shared.user, userId: fileProviderData.shared.userId, fileName: fileName, fileNameView: fileName, ocId: ocIdTemp, serverUrl: tableDirectory.serverUrl, urlBase: fileProviderData.shared.accountUrlBase, url: "", contentType: "")
metadata.session = NCNetworking.shared.sessionIdentifierBackgroundExtension
metadata.size = size
metadata.status = NCGlobal.shared.metadataStatusUploading
diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj
index 0bd1dd77b..82f2736b2 100644
--- a/Nextcloud.xcodeproj/project.pbxproj
+++ b/Nextcloud.xcodeproj/project.pbxproj
@@ -33,7 +33,7 @@
AF36077627BFB019001A243D /* ParallelWorkerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF36077527BFB019001A243D /* ParallelWorkerTest.swift */; };
AF3F909A28213BEA0048A93E /* UserAgentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF3F909928213BEA0048A93E /* UserAgentTests.swift */; };
AF3FDCC22796ECC300710F60 /* NCTrash+CollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF3FDCC12796ECC300710F60 /* NCTrash+CollectionView.swift */; };
- AF3FDCC32796F3FB00710F60 /* NCTrashListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD4821903F850088454D /* NCTrashListCell.swift */; };
+ AF3FDCC32796F3FB00710F60 /* NCTrashListCell+NCTrashCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD4821903F850088454D /* NCTrashListCell+NCTrashCellProtocol.swift */; };
AF4BF614275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */; };
AF4BF615275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */; };
AF4BF616275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */; };
@@ -107,8 +107,6 @@
F70968A424212C4E00ED60E5 /* NCLivePhoto.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70968A324212C4E00ED60E5 /* NCLivePhoto.swift */; };
F70A58BE24D0349500DED00D /* NCCapabilitiesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70A58BD24D0349500DED00D /* NCCapabilitiesViewController.swift */; };
F70A58C024D0545100DED00D /* NCCapabilitiesViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F70A58BF24D0545100DED00D /* NCCapabilitiesViewController.storyboard */; };
- F70B866D2642A21300ED5349 /* NCBackgroundImageColor.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F70B866B2642A21300ED5349 /* NCBackgroundImageColor.storyboard */; };
- F70B866E2642A21300ED5349 /* NCBackgroundImageColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70B866C2642A21300ED5349 /* NCBackgroundImageColor.swift */; };
F70B86752642CE3B00ED5349 /* FirebaseCrashlytics in Frameworks */ = {isa = PBXBuildFile; productRef = F70B86742642CE3B00ED5349 /* FirebaseCrashlytics */; };
F70BFC7420E0FA7D00C67599 /* NCUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70BFC7320E0FA7C00C67599 /* NCUtility.swift */; };
F70BFC7520E0FA7D00C67599 /* NCUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70BFC7320E0FA7C00C67599 /* NCUtility.swift */; };
@@ -132,7 +130,6 @@
F7134186259747BA00768D21 /* NCPushNotification.m in Sources */ = {isa = PBXBuildFile; fileRef = F7134185259747BA00768D21 /* NCPushNotification.m */; };
F713FF002472764100214AF6 /* UIImage+animatedGIF.m in Sources */ = {isa = PBXBuildFile; fileRef = F713FEFF2472764100214AF6 /* UIImage+animatedGIF.m */; };
F71459D21D12E3B700CAFEEC /* CCUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = F7053E3D1C639DF500741EA5 /* CCUtility.m */; };
- F7145A1A1D12E3B700CAFEEC /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F7F67BB81A24D27800EE80DA /* Images.xcassets */; };
F7145A231D12E3B700CAFEEC /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = F7E70DE91A24DE4100E1B66A /* Localizable.strings */; };
F714803B262EBE3900693E51 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F714803A262EBE3900693E51 /* MainInterface.storyboard */; };
F7148041262EBE4000693E51 /* NCShareExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7148040262EBE4000693E51 /* NCShareExtension.swift */; };
@@ -145,12 +142,17 @@
F717402D24F699A5000C87D5 /* NCFavorite.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F717402B24F699A5000C87D5 /* NCFavorite.storyboard */; };
F717402E24F699A5000C87D5 /* NCFavorite.swift in Sources */ = {isa = PBXBuildFile; fileRef = F717402C24F699A5000C87D5 /* NCFavorite.swift */; };
F718C24E254D507B00C5C256 /* NCViewerMediaDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F718C24D254D507B00C5C256 /* NCViewerMediaDetailView.swift */; };
+ F719D9E0288D37A300762E33 /* NCColorPicker.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F719D9DF288D37A300762E33 /* NCColorPicker.storyboard */; };
+ F719D9E2288D396100762E33 /* NCColorPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = F719D9E1288D396100762E33 /* NCColorPicker.swift */; };
F7226EDC1EE4089300EBECB1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7226EDB1EE4089300EBECB1 /* Main.storyboard */; };
- F7233B3A27835FA400F40A43 /* ChromaColorPicker in Frameworks */ = {isa = PBXBuildFile; productRef = F7233B3927835FA400F40A43 /* ChromaColorPicker */; };
F723985C253C95CE00257F49 /* NCViewerRichdocument.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F723985B253C95CE00257F49 /* NCViewerRichdocument.storyboard */; };
F7239871253D86B600257F49 /* NCEmptyDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7239870253D86B600257F49 /* NCEmptyDataSet.swift */; };
F7239877253D86D300257F49 /* NCEmptyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7239876253D86D300257F49 /* NCEmptyView.xib */; };
F723B3DD22FC6D1D00301EFE /* NCShareCommentsCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F723B3DC22FC6D1C00301EFE /* NCShareCommentsCell.xib */; };
+ F7245924289BB50C00474787 /* ThreadSafeDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7245923289BB50B00474787 /* ThreadSafeDictionary.swift */; };
+ F7245925289BB59100474787 /* ThreadSafeDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7245923289BB50B00474787 /* ThreadSafeDictionary.swift */; };
+ F7245926289BB59300474787 /* ThreadSafeDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7245923289BB50B00474787 /* ThreadSafeDictionary.swift */; };
+ F7245927289BB59300474787 /* ThreadSafeDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7245923289BB50B00474787 /* ThreadSafeDictionary.swift */; };
F72685E727C78E490019EF5E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F72685E927C78E490019EF5E /* InfoPlist.strings */; };
F726EEEC1FED1C820030B9C8 /* NCEndToEndInitialize.swift in Sources */ = {isa = PBXBuildFile; fileRef = F726EEEB1FED1C820030B9C8 /* NCEndToEndInitialize.swift */; };
F72928A0253B0937009CA4FD /* NCMainNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F729289F253B0937009CA4FD /* NCMainNavigationController.swift */; };
@@ -181,7 +183,6 @@
F73D5E49246DE09200DF6467 /* NCElementsJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73D5E46246DE09200DF6467 /* NCElementsJSON.swift */; };
F73D5E4A246DE09200DF6467 /* NCElementsJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73D5E46246DE09200DF6467 /* NCElementsJSON.swift */; };
F73F537F1E929C8500F8678D /* NCMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73F537E1E929C8500F8678D /* NCMore.swift */; };
- F7417DB3216CE925007D05F5 /* NCTrashSectionHeaderFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7417DB2216CE925007D05F5 /* NCTrashSectionHeaderFooter.swift */; };
F7434B3420E23FD700417916 /* NCDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB41ED5A87C00B7EAD4 /* NCDatabase.swift */; };
F7434B3620E23FE000417916 /* NCManageDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB51ED5A87C00B7EAD4 /* NCManageDatabase.swift */; };
F7434B3820E2400600417916 /* NCBrand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76B3CCD1EAE01BD00921AC9 /* NCBrand.swift */; };
@@ -229,8 +230,6 @@
F75EAED826D2552E00F4320E /* MarqueeLabel in Frameworks */ = {isa = PBXBuildFile; productRef = F75EAED726D2552E00F4320E /* MarqueeLabel */; };
F760329F252F0F8E0015A421 /* NCTransferCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F760329D252F0F8E0015A421 /* NCTransferCell.swift */; };
F76032A0252F0F8E0015A421 /* NCTransferCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F760329E252F0F8E0015A421 /* NCTransferCell.xib */; };
- F7632FBF21832F8700721B71 /* NCTrashSectionHeaderMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7632FBE21832F8700721B71 /* NCTrashSectionHeaderMenu.xib */; };
- F7632FC1218353AA00721B71 /* NCTrashSectionFooter.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7632FC0218353AA00721B71 /* NCTrashSectionFooter.xib */; };
F7651A8A23A2A3F2001403D2 /* NCCreateFormUploadDocuments.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7651A8823A2A3F2001403D2 /* NCCreateFormUploadDocuments.storyboard */; };
F7651A8B23A2A3F2001403D2 /* NCCreateFormUploadDocuments.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7651A8923A2A3F2001403D2 /* NCCreateFormUploadDocuments.swift */; };
F765608F23BF813600765969 /* NCContentPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F765608E23BF813500765969 /* NCContentPresenter.swift */; };
@@ -245,6 +244,11 @@
F769454822E9F20D000A798A /* NCShareNetworking.swift in Sources */ = {isa = PBXBuildFile; fileRef = F769454722E9F20D000A798A /* NCShareNetworking.swift */; };
F76B3CCE1EAE01BD00921AC9 /* NCBrand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76B3CCD1EAE01BD00921AC9 /* NCBrand.swift */; };
F76B3CCF1EAE01BD00921AC9 /* NCBrand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76B3CCD1EAE01BD00921AC9 /* NCBrand.swift */; };
+ F76C26A62850D3A500E42BDF /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F7F67BB81A24D27800EE80DA /* Images.xcassets */; };
+ F76D364628A4F8BF00214537 /* NCActivityIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76D364528A4F8BF00214537 /* NCActivityIndicator.swift */; };
+ F76D364728A4F8BF00214537 /* NCActivityIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76D364528A4F8BF00214537 /* NCActivityIndicator.swift */; };
+ F76D364828A4F8BF00214537 /* NCActivityIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76D364528A4F8BF00214537 /* NCActivityIndicator.swift */; };
+ F76D364928A4F8BF00214537 /* NCActivityIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76D364528A4F8BF00214537 /* NCActivityIndicator.swift */; };
F76D3CF12428B40E005DFA87 /* NCViewerPDFSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76D3CF02428B40E005DFA87 /* NCViewerPDFSearch.swift */; };
F76D3CF32428B94E005DFA87 /* NCViewerPDFSearchCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F76D3CF22428B94E005DFA87 /* NCViewerPDFSearchCell.xib */; };
F76D3CF52428D0C1005DFA87 /* NCViewerPDF.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F76D3CF42428D0C0005DFA87 /* NCViewerPDF.storyboard */; };
@@ -286,6 +290,9 @@
F77B0F611D118A16002130FE /* Acknowledgements.rtf in Resources */ = {isa = PBXBuildFile; fileRef = F7ACE42B1BAC0268006C0017 /* Acknowledgements.rtf */; };
F77B0F631D118A16002130FE /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = F7E70DE91A24DE4100E1B66A /* Localizable.strings */; };
F77B0F7D1D118A16002130FE /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F7F67BB81A24D27800EE80DA /* Images.xcassets */; };
+ F77BB746289984CA0090FC19 /* UIViewController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77BB745289984CA0090FC19 /* UIViewController+Extension.swift */; };
+ F77BB748289985270090FC19 /* UITabBarController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77BB747289985270090FC19 /* UITabBarController+Extension.swift */; };
+ F77BB74A2899857B0090FC19 /* UINavigationController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77BB7492899857B0090FC19 /* UINavigationController+Extension.swift */; };
F78071091EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m in Sources */ = {isa = PBXBuildFile; fileRef = F78071081EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m */; };
F780710A1EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m in Sources */ = {isa = PBXBuildFile; fileRef = F78071081EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m */; };
F78295311F962EFA00A572F5 /* NCEndToEndEncryption.m in Sources */ = {isa = PBXBuildFile; fileRef = F70CAE391F8CF31A008125FD /* NCEndToEndEncryption.m */; };
@@ -307,7 +314,7 @@
F78ACD4221903CE00088454D /* NCListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD4121903CE00088454D /* NCListCell.swift */; };
F78ACD4421903CF20088454D /* NCListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD4321903CF20088454D /* NCListCell.xib */; };
F78ACD4621903D010088454D /* NCGridCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD4521903D010088454D /* NCGridCell.xib */; };
- F78ACD4A21903F850088454D /* NCTrashListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD4821903F850088454D /* NCTrashListCell.swift */; };
+ F78ACD4A21903F850088454D /* NCTrashListCell+NCTrashCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD4821903F850088454D /* NCTrashListCell+NCTrashCellProtocol.swift */; };
F78ACD4B21903F850088454D /* NCTrashListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD4921903F850088454D /* NCTrashListCell.xib */; };
F78ACD52219046DC0088454D /* NCSectionHeaderFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD51219046DC0088454D /* NCSectionHeaderFooter.swift */; };
F78ACD54219047D40088454D /* NCSectionFooter.xib in Resources */ = {isa = PBXBuildFile; fileRef = F78ACD53219047D40088454D /* NCSectionFooter.xib */; };
@@ -336,8 +343,7 @@
F7A321AD1E9E6AD50069AD1B /* CCAdvanced.m in Sources */ = {isa = PBXBuildFile; fileRef = F7A321AC1E9E6AD50069AD1B /* CCAdvanced.m */; };
F7A76DC8256A71CD00119AB3 /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extensions.swift */; };
F7A76DCD256A71CE00119AB3 /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extensions.swift */; };
- F7A80BCA252624C100C7CD01 /* NCFileViewInFolder.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7A80BC8252624C100C7CD01 /* NCFileViewInFolder.storyboard */; };
- F7A80BCB252624C100C7CD01 /* NCFileViewInFolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A80BC9252624C100C7CD01 /* NCFileViewInFolder.swift */; };
+ F7AC1CB028AB94490032D99F /* Array+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7AC1CAF28AB94490032D99F /* Array+Extensions.swift */; };
F7AE00F5230D5F9E007ACF8A /* NCLoginWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7AE00F4230D5F9E007ACF8A /* NCLoginWeb.swift */; };
F7AE00F8230E81CB007ACF8A /* NCBrowserWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7AE00F7230E81CB007ACF8A /* NCBrowserWeb.swift */; };
F7AE00FA230E81EB007ACF8A /* NCBrowserWeb.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7AE00F9230E81EB007ACF8A /* NCBrowserWeb.storyboard */; };
@@ -416,6 +422,7 @@
F7F878AE1FB9E3B900599E4F /* NCEndToEndMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F878AD1FB9E3B900599E4F /* NCEndToEndMetadata.swift */; };
F7F878AF1FB9E3B900599E4F /* NCEndToEndMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F878AD1FB9E3B900599E4F /* NCEndToEndMetadata.swift */; };
F7F9D1BB25397CE000D9BFF5 /* NCViewer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F9D1BA25397CE000D9BFF5 /* NCViewer.swift */; };
+ F7FF2CB12842159500EBB7A1 /* NCSectionHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7FF2CB02842159500EBB7A1 /* NCSectionHeader.xib */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -582,8 +589,6 @@
F70A07C8205285FB00DC1231 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Localizable.strings"; sourceTree = "<group>"; };
F70A58BD24D0349500DED00D /* NCCapabilitiesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCapabilitiesViewController.swift; sourceTree = "<group>"; };
F70A58BF24D0545100DED00D /* NCCapabilitiesViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCCapabilitiesViewController.storyboard; sourceTree = "<group>"; };
- F70B866B2642A21300ED5349 /* NCBackgroundImageColor.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCBackgroundImageColor.storyboard; sourceTree = "<group>"; };
- F70B866C2642A21300ED5349 /* NCBackgroundImageColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCBackgroundImageColor.swift; sourceTree = "<group>"; };
F70B866F2642CA9500ED5349 /* ChromaColorPicker.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = ChromaColorPicker.xcframework; path = Carthage/Build/ChromaColorPicker.xcframework; sourceTree = "<group>"; };
F70B86792642CF5300ED5349 /* KTVHTTPCache.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = KTVHTTPCache.xcframework; path = Carthage/Build/KTVHTTPCache.xcframework; sourceTree = "<group>"; };
F70B867A2642CF5300ED5349 /* TLPhotoPicker.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = TLPhotoPicker.xcframework; path = Carthage/Build/TLPhotoPicker.xcframework; sourceTree = "<group>"; };
@@ -606,6 +611,7 @@
F70D87CE25EE6E58008CBBBD /* NCRenameFile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCRenameFile.swift; sourceTree = "<group>"; };
F70D8D8024A4A9BF000A5756 /* NCNetworkingProcessUpload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCNetworkingProcessUpload.swift; sourceTree = "<group>"; };
F70F2BA4225F2D8900EBB73E /* ZIPFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ZIPFoundation.framework; path = Carthage/Build/iOS/ZIPFoundation.framework; sourceTree = "<group>"; };
+ F70F96AF2874394B006C8379 /* Nextcloud-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Nextcloud-Bridging-Header.h"; sourceTree = "<group>"; };
F710C5EF2471A6D1009AD8B7 /* Sentry.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sentry.framework; path = Carthage/Build/iOS/Sentry.framework; sourceTree = "<group>"; };
F710D1F42405770F00A6033D /* NCViewerPDF.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCViewerPDF.swift; sourceTree = "<group>"; };
F710D2012405826100A6033D /* NCViewer+Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCViewer+Menu.swift"; sourceTree = "<group>"; };
@@ -638,11 +644,14 @@
F7176DB9256672640017E83C /* FIRAnalyticsConnector.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FIRAnalyticsConnector.framework; path = Carthage/Build/iOS/FIRAnalyticsConnector.framework; sourceTree = "<group>"; };
F7176DDA256672D90017E83C /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
F718C24D254D507B00C5C256 /* NCViewerMediaDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCViewerMediaDetailView.swift; sourceTree = "<group>"; };
+ F719D9DF288D37A300762E33 /* NCColorPicker.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCColorPicker.storyboard; sourceTree = "<group>"; };
+ F719D9E1288D396100762E33 /* NCColorPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCColorPicker.swift; sourceTree = "<group>"; };
F7226EDB1EE4089300EBECB1 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = "<group>"; };
F723985B253C95CE00257F49 /* NCViewerRichdocument.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCViewerRichdocument.storyboard; sourceTree = "<group>"; };
F7239870253D86B600257F49 /* NCEmptyDataSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCEmptyDataSet.swift; sourceTree = "<group>"; };
F7239876253D86D300257F49 /* NCEmptyView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCEmptyView.xib; sourceTree = "<group>"; };
F723B3DC22FC6D1C00301EFE /* NCShareCommentsCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCShareCommentsCell.xib; sourceTree = "<group>"; };
+ F7245923289BB50B00474787 /* ThreadSafeDictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreadSafeDictionary.swift; sourceTree = "<group>"; };
F7267A81225DFCE100D6DB7D /* AFNetworking.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AFNetworking.framework; path = Carthage/Build/iOS/AFNetworking.framework; sourceTree = "<group>"; };
F72685E827C78E490019EF5E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
F726EEEB1FED1C820030B9C8 /* NCEndToEndInitialize.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCEndToEndInitialize.swift; sourceTree = "<group>"; };
@@ -674,7 +683,6 @@
F73D11F9253C5F4800DF9BEC /* NCViewerNextcloudText.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCViewerNextcloudText.storyboard; sourceTree = "<group>"; };
F73D5E46246DE09200DF6467 /* NCElementsJSON.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCElementsJSON.swift; sourceTree = "<group>"; };
F73F537E1E929C8500F8678D /* NCMore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCMore.swift; sourceTree = "<group>"; };
- F7417DB2216CE925007D05F5 /* NCTrashSectionHeaderFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCTrashSectionHeaderFooter.swift; sourceTree = "<group>"; };
F7421EAE2294044B00C4B7C1 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
F7434B5F20E2440600417916 /* FileProviderExtension-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FileProviderExtension-Bridging-Header.h"; sourceTree = "<group>"; };
F745B250222D871800346520 /* QRCodeReader.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QRCodeReader.framework; path = Carthage/Build/iOS/QRCodeReader.framework; sourceTree = "<group>"; };
@@ -717,8 +725,6 @@
F75EDFBE1E8C116D00E6F369 /* libstdc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libstdc++.tbd"; path = "usr/lib/libstdc++.tbd"; sourceTree = SDKROOT; };
F760329D252F0F8E0015A421 /* NCTransferCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NCTransferCell.swift; path = iOSClient/Transfers/NCTransferCell.swift; sourceTree = SOURCE_ROOT; };
F760329E252F0F8E0015A421 /* NCTransferCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = NCTransferCell.xib; path = iOSClient/Transfers/NCTransferCell.xib; sourceTree = SOURCE_ROOT; };
- F7632FBE21832F8700721B71 /* NCTrashSectionHeaderMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCTrashSectionHeaderMenu.xib; sourceTree = "<group>"; };
- F7632FC0218353AA00721B71 /* NCTrashSectionFooter.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCTrashSectionFooter.xib; sourceTree = "<group>"; };
F7651A8823A2A3F2001403D2 /* NCCreateFormUploadDocuments.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCCreateFormUploadDocuments.storyboard; sourceTree = "<group>"; };
F7651A8923A2A3F2001403D2 /* NCCreateFormUploadDocuments.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCCreateFormUploadDocuments.swift; sourceTree = "<group>"; };
F765608623BF806C00765969 /* QuickLayout.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLayout.framework; path = Carthage/Build/iOS/QuickLayout.framework; sourceTree = "<group>"; };
@@ -734,6 +740,7 @@
F769454522E9F1B0000A798A /* NCShareCommon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareCommon.swift; sourceTree = "<group>"; };
F769454722E9F20D000A798A /* NCShareNetworking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareNetworking.swift; sourceTree = "<group>"; };
F76B3CCD1EAE01BD00921AC9 /* NCBrand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCBrand.swift; sourceTree = "<group>"; };
+ F76D364528A4F8BF00214537 /* NCActivityIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCActivityIndicator.swift; sourceTree = "<group>"; };
F76D3CF02428B40E005DFA87 /* NCViewerPDFSearch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCViewerPDFSearch.swift; sourceTree = "<group>"; };
F76D3CF22428B94E005DFA87 /* NCViewerPDFSearchCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCViewerPDFSearchCell.xib; sourceTree = "<group>"; };
F76D3CF42428D0C0005DFA87 /* NCViewerPDF.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCViewerPDF.storyboard; sourceTree = "<group>"; };
@@ -776,6 +783,9 @@
F77910A425DD517B00CEDB9E /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
F77910AA25DD53C700CEDB9E /* NCSettingsBundleHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSettingsBundleHelper.swift; sourceTree = "<group>"; };
F77A697C250A0FBC00FF1708 /* NCCollectionViewCommon+Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCCollectionViewCommon+Menu.swift"; sourceTree = "<group>"; };
+ F77BB745289984CA0090FC19 /* UIViewController+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extension.swift"; sourceTree = "<group>"; };
+ F77BB747289985270090FC19 /* UITabBarController+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UITabBarController+Extension.swift"; sourceTree = "<group>"; };
+ F77BB7492899857B0090FC19 /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = "<group>"; };
F78071071EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNotificationCenter+MainThread.h"; sourceTree = "<group>"; };
F78071081EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSNotificationCenter+MainThread.m"; sourceTree = "<group>"; };
F785EE9C246196DF00B3F945 /* NCNetworkingE2EE.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCNetworkingE2EE.swift; sourceTree = "<group>"; };
@@ -787,7 +797,7 @@
F78ACD4121903CE00088454D /* NCListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCListCell.swift; sourceTree = "<group>"; };
F78ACD4321903CF20088454D /* NCListCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCListCell.xib; sourceTree = "<group>"; };
F78ACD4521903D010088454D /* NCGridCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCGridCell.xib; sourceTree = "<group>"; };
- F78ACD4821903F850088454D /* NCTrashListCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCTrashListCell.swift; sourceTree = "<group>"; };
+ F78ACD4821903F850088454D /* NCTrashListCell+NCTrashCellProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCTrashListCell+NCTrashCellProtocol.swift"; sourceTree = "<group>"; };
F78ACD4921903F850088454D /* NCTrashListCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCTrashListCell.xib; sourceTree = "<group>"; };
F78ACD51219046DC0088454D /* NCSectionHeaderFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSectionHeaderFooter.swift; sourceTree = "<group>"; };
F78ACD53219047D40088454D /* NCSectionFooter.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCSectionFooter.xib; sourceTree = "<group>"; };
@@ -811,8 +821,6 @@
F7A0D1342591FBC5008F8A13 /* String+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = "<group>"; };
F7A321AB1E9E6AD50069AD1B /* CCAdvanced.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCAdvanced.h; sourceTree = "<group>"; };
F7A321AC1E9E6AD50069AD1B /* CCAdvanced.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCAdvanced.m; sourceTree = "<group>"; };
- F7A80BC8252624C100C7CD01 /* NCFileViewInFolder.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCFileViewInFolder.storyboard; sourceTree = "<group>"; };
- F7A80BC9252624C100C7CD01 /* NCFileViewInFolder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCFileViewInFolder.swift; sourceTree = "<group>"; };
F7AA41B827C7CF4600494705 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/InfoPlist.strings; sourceTree = "<group>"; };
F7AA41B927C7CF4B00494705 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
F7AA41BA27C7CF5000494705 /* zh-Hant-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant-TW"; path = "zh-Hant-TW.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
@@ -855,6 +863,7 @@
F7AA41DF27C7CF7E00494705 /* es-PY */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-PY"; path = "es-PY.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
F7AA41E027C7CF8000494705 /* es-NI */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-NI"; path = "es-NI.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
F7AA41E127C7CF8100494705 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
+ F7AC1CAF28AB94490032D99F /* Array+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Extensions.swift"; sourceTree = "<group>"; };
F7ACE4291BAC0268006C0017 /* Acknowledgements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Acknowledgements.h; sourceTree = "<group>"; };
F7ACE42A1BAC0268006C0017 /* Acknowledgements.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Acknowledgements.m; sourceTree = "<group>"; };
F7ACE42B1BAC0268006C0017 /* Acknowledgements.rtf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.rtf; path = Acknowledgements.rtf; sourceTree = "<group>"; };
@@ -905,7 +914,6 @@
F7CE8AFA1DC1F8D8009CAE48 /* Nextcloud.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Nextcloud.app; sourceTree = BUILT_PRODUCTS_DIR; };
F7CE8AFB1DC1F8D8009CAE48 /* Share.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Share.appex; sourceTree = BUILT_PRODUCTS_DIR; };
F7D0F33D264144FC0097D4A3 /* Background.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Background.xcassets; sourceTree = "<group>"; };
- F7D154271E2392A300202FD9 /* Nextcloud-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Nextcloud-Bridging-Header.h"; sourceTree = "<group>"; };
F7D1611F23CF19E30039EBBF /* NCViewerRichWorkspace.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCViewerRichWorkspace.storyboard; sourceTree = "<group>"; };
F7D2C772246470CA008513AE /* XLForm.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XLForm.framework; path = Carthage/Build/iOS/XLForm.framework; sourceTree = "<group>"; };
F7D532461F5D4123006568B1 /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -948,6 +956,7 @@
F7F878AD1FB9E3B900599E4F /* NCEndToEndMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCEndToEndMetadata.swift; sourceTree = "<group>"; };
F7F9D1BA25397CE000D9BFF5 /* NCViewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCViewer.swift; sourceTree = "<group>"; };
F7FC7D551DC1F93800BB2C6A /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
+ F7FF2CB02842159500EBB7A1 /* NCSectionHeader.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCSectionHeader.xib; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -1010,7 +1019,6 @@
F7ED547C25EEA65400956C55 /* QRCodeReader in Frameworks */,
F788ECC7263AAAFA00ADC67F /* MarkdownKit in Frameworks */,
F7BB7E4727A18C56009B9F29 /* Parchment in Frameworks */,
- F7233B3A27835FA400F40A43 /* ChromaColorPicker in Frameworks */,
F770768E263A8C3400A1BA94 /* FloatingPanel in Frameworks */,
F710FC7C277B7D0000AA9FBF /* RealmSwift in Frameworks */,
F7E572FD278F146C00F8C99E /* OpenSSL.xcframework in Frameworks */,
@@ -1098,7 +1106,6 @@
F7DFB7E9219C5A0500680748 /* Create cloud */,
F78ACD50219046AC0088454D /* Section Header Footer */,
F7603298252F0E550015A421 /* Collection Common */,
- F7CA213725F1372B00826ABB /* Account Request */,
370D26AE248A3D7A00121797 /* NCCellProtocol.swift */,
F7226EDB1EE4089300EBECB1 /* Main.storyboard */,
F7682FDF23C36B0500983A04 /* NCMainTabBar.swift */,
@@ -1136,13 +1143,13 @@
path = languages;
sourceTree = "<group>";
};
- F70B866A2642A21300ED5349 /* BackgroundImageColor */ = {
+ F70B866A2642A21300ED5349 /* Color */ = {
isa = PBXGroup;
children = (
- F70B866B2642A21300ED5349 /* NCBackgroundImageColor.storyboard */,
- F70B866C2642A21300ED5349 /* NCBackgroundImageColor.swift */,
+ F719D9DF288D37A300762E33 /* NCColorPicker.storyboard */,
+ F719D9E1288D396100762E33 /* NCColorPicker.swift */,
);
- path = BackgroundImageColor;
+ path = Color;
sourceTree = "<group>";
};
F70D87CC25EE6E58008CBBBD /* Rename file */ = {
@@ -1317,16 +1324,6 @@
path = "Collection Common";
sourceTree = "<group>";
};
- F7632FC32183667400721B71 /* Section */ = {
- isa = PBXGroup;
- children = (
- F7632FC0218353AA00721B71 /* NCTrashSectionFooter.xib */,
- F7632FBE21832F8700721B71 /* NCTrashSectionHeaderMenu.xib */,
- F7417DB2216CE925007D05F5 /* NCTrashSectionHeaderFooter.swift */,
- );
- path = Section;
- sourceTree = "<group>";
- };
F765F72E25237E3F00391DBE /* Recent */ = {
isa = PBXGroup;
children = (
@@ -1375,7 +1372,7 @@
F78ACD4721903F850088454D /* Cell */ = {
isa = PBXGroup;
children = (
- F78ACD4821903F850088454D /* NCTrashListCell.swift */,
+ F78ACD4821903F850088454D /* NCTrashListCell+NCTrashCellProtocol.swift */,
F78ACD4921903F850088454D /* NCTrashListCell.xib */,
);
path = Cell;
@@ -1385,8 +1382,9 @@
isa = PBXGroup;
children = (
F78ACD53219047D40088454D /* NCSectionFooter.xib */,
- F78ACD51219046DC0088454D /* NCSectionHeaderFooter.swift */,
+ F7FF2CB02842159500EBB7A1 /* NCSectionHeader.xib */,
F78ACD57219048040088454D /* NCSectionHeaderMenu.xib */,
+ F78ACD51219046DC0088454D /* NCSectionHeaderFooter.swift */,
);
path = "Section Header Footer";
sourceTree = "<group>";
@@ -1395,7 +1393,6 @@
isa = PBXGroup;
children = (
F78ACD4721903F850088454D /* Cell */,
- F7632FC32183667400721B71 /* Section */,
F78F74332163757000C2ADAD /* NCTrash.storyboard */,
F78F74352163781100C2ADAD /* NCTrash.swift */,
AF3FDCC12796ECC300710F60 /* NCTrash+CollectionView.swift */,
@@ -1468,7 +1465,11 @@
AF7E504D27A2D8FF00B5E4AF /* UIBarButton+Extension.swift */,
F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */,
F79B645F26CA661600838ACA /* UIControl+Extensions.swift */,
+ F7AC1CAF28AB94490032D99F /* Array+Extensions.swift */,
F7F4F10F27ECDC4A008676F9 /* UIDevice+Extensions.swift */,
+ F77BB747289985270090FC19 /* UITabBarController+Extension.swift */,
+ F77BB745289984CA0090FC19 /* UIViewController+Extension.swift */,
+ F77BB7492899857B0090FC19 /* UINavigationController+Extension.swift */,
F7F4F11127ECDC52008676F9 /* UIFont+Extension.swift */,
F713FEFE2472764000214AF6 /* UIImage+animatedGIF.h */,
F713FEFF2472764100214AF6 /* UIImage+animatedGIF.m */,
@@ -1498,15 +1499,6 @@
path = Activity;
sourceTree = "<group>";
};
- F7A80BC7252624C100C7CD01 /* FileViewInFolder */ = {
- isa = PBXGroup;
- children = (
- F7A80BC8252624C100C7CD01 /* NCFileViewInFolder.storyboard */,
- F7A80BC9252624C100C7CD01 /* NCFileViewInFolder.swift */,
- );
- path = FileViewInFolder;
- sourceTree = "<group>";
- };
F7ACE4281BAC0268006C0017 /* Settings */ = {
isa = PBXGroup;
children = (
@@ -1580,10 +1572,12 @@
F70968A324212C4E00ED60E5 /* NCLivePhoto.swift */,
F707C26421A2DC5200F6181E /* NCStoreReview.swift */,
F70BFC7320E0FA7C00C67599 /* NCUtility.swift */,
+ F76D364528A4F8BF00214537 /* NCActivityIndicator.swift */,
AF93474B27E34120002537EE /* NCUtility+Image.swift */,
AF817EF0274BC781009ED85B /* NCUserBaseUrl.swift */,
F74AF3A3247FB6AE00AC767B /* NCUtilityFileSystem.swift */,
AF36077027BFA4E8001A243D /* ParallelWorker.swift */,
+ F7245923289BB50B00474787 /* ThreadSafeDictionary.swift */,
F702F2FC25EE5D2C008F8E80 /* NYMnemonic */,
);
path = Utility;
@@ -1612,6 +1606,7 @@
F7D0F33D264144FC0097D4A3 /* Background.xcassets */,
F7B8B82F25681C3400967775 /* GoogleService-Info.plist */,
F7362A1E220C853A005101B5 /* LaunchScreen.storyboard */,
+ F70F96AF2874394B006C8379 /* Nextcloud-Bridging-Header.h */,
F73CB5771ED46807005F2A5A /* NCBridgeSwift.h */,
F76B3CCD1EAE01BD00921AC9 /* NCBrand.swift */,
);
@@ -1777,16 +1772,16 @@
F7F67BB81A24D27800EE80DA /* Images.xcassets */,
F7C1CDD91E6DFC6F005D92BE /* Brand */,
F70211F31BAC56E9003FC03E /* Main */,
+ F7CA213725F1372B00826ABB /* Account Request */,
F7A321621E9E37960069AD1B /* Activity */,
- F70B866A2642A21300ED5349 /* BackgroundImageColor */,
F7AE00F6230E8191007ACF8A /* BrowserWeb */,
+ F70B866A2642A21300ED5349 /* Color */,
F7BAAD951ED5A63D00B7EAD4 /* Data */,
F73FAEE224D2CA830090692E /* Diagnostics */,
F723986F253D867900257F49 /* EmptyView */,
F7A0D14E259229FA008F8A13 /* Extensions */,
F7A3214D1E9E2A070069AD1B /* Favorites */,
F7725A5D251F33BB00D125E0 /* Files */,
- F7A80BC7252624C100C7CD01 /* FileViewInFolder */,
F7BFFA621A24D7300044ED85 /* Login */,
F7EC9CB921185F2000F1C5CE /* Media */,
371B5A2F23D0B04B00FAFAE9 /* Menu */,
@@ -1818,7 +1813,6 @@
children = (
F7F4F0FB27ECDBDA008676F9 /* Font */,
F72B60941A24F04E004EF66F /* Localizations */,
- F7D154271E2392A300202FD9 /* Nextcloud-Bridging-Header.h */,
);
name = "Supporting Files";
path = iOSClient;
@@ -2084,7 +2078,6 @@
F76DA96E277B78AE0082465B /* TLPhotoPicker */,
F710FC79277B7D0000AA9FBF /* Realm */,
F710FC7B277B7D0000AA9FBF /* RealmSwift */,
- F7233B3927835FA400F40A43 /* ChromaColorPicker */,
F7BB7E4627A18C56009B9F29 /* Parchment */,
F758A01127A7F03E0069468B /* JGProgressHUD */,
F753BA92281FD8020015BFB6 /* EasyTipView */,
@@ -2105,7 +2098,6 @@
TargetAttributes = {
2C33C47E23E2C475005F963B = {
CreatedOnToolsVersion = 11.3.1;
- DevelopmentTeam = 6JLRKY9ZV7;
ProvisioningStyle = Automatic;
};
AF8ED1F82757821000B8DBC4 = {
@@ -2113,7 +2105,6 @@
TestTargetID = F77B0DEB1D118A16002130FE;
};
F71459B41D12E3B700CAFEEC = {
- DevelopmentTeam = 6JLRKY9ZV7;
LastSwiftMigration = 1020;
SystemCapabilities = {
com.apple.ApplicationGroups.iOS = {
@@ -2126,7 +2117,6 @@
};
F771E3CF20E2392D00AFB62D = {
CreatedOnToolsVersion = 9.4.1;
- DevelopmentTeam = 6JLRKY9ZV7;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
};
@@ -2211,7 +2201,6 @@
F76DA967277B77E90082465B /* XCRemoteSwiftPackageReference "DropDown" */,
F76DA96D277B78AE0082465B /* XCRemoteSwiftPackageReference "TLPhotoPicker" */,
F710FC78277B7CFF00AA9FBF /* XCRemoteSwiftPackageReference "realm-swift" */,
- F7233B3827835FA300F40A43 /* XCRemoteSwiftPackageReference "ChromaColorPicker" */,
F7BB7E4527A18C56009B9F29 /* XCRemoteSwiftPackageReference "Parchment" */,
F72CD01027A7E92400E59476 /* XCRemoteSwiftPackageReference "JGProgressHUD" */,
F753BA91281FD8010015BFB6 /* XCRemoteSwiftPackageReference "EasyTipView" */,
@@ -2253,12 +2242,12 @@
F714803B262EBE3900693E51 /* MainInterface.storyboard in Resources */,
F7148054262ED51000693E51 /* NCListCell.xib in Resources */,
F7D57C8626317BDA00DE301D /* NCAccountRequest.storyboard in Resources */,
- F7145A1A1D12E3B700CAFEEC /* Images.xcassets in Resources */,
AF22B209277B4E4C00DAB0CC /* NCCreateFormUploadConflictCell.xib in Resources */,
F7148063262ED66200693E51 /* NCEmptyView.xib in Resources */,
AF22B207277B4E4C00DAB0CC /* NCCreateFormUploadConflict.storyboard in Resources */,
F7145A231D12E3B700CAFEEC /* Localizable.strings in Resources */,
F746EC51273906C40052598D /* NCViewCertificateDetails.storyboard in Resources */,
+ F76C26A62850D3A500E42BDF /* Images.xcassets in Resources */,
F79EC784263161BA004E59D6 /* NCRenameFile.storyboard in Resources */,
F714804F262ED4F900693E51 /* NCGridCell.xib in Resources */,
F714805E262ED52900693E51 /* NCSectionFooter.xib in Resources */,
@@ -2287,7 +2276,6 @@
F72685E727C78E490019EF5E /* InfoPlist.strings in Resources */,
F769453C22E9CFFF000A798A /* NCShareUserCell.xib in Resources */,
F7F4F10927ECDBDB008676F9 /* Inconsolata-Bold.ttf in Resources */,
- F7A80BCA252624C100C7CD01 /* NCFileViewInFolder.storyboard in Resources */,
F76D3CF52428D0C1005DFA87 /* NCViewerPDF.storyboard in Resources */,
F700222C1EC479840080073F /* Custom.xcassets in Resources */,
F702F2F125EE5CDB008F8E80 /* NCLogin.storyboard in Resources */,
@@ -2302,7 +2290,6 @@
F7EFC0C6256BC77700461AAD /* NCMoreUserCell.xib in Resources */,
F702F2E725EE5C86008F8E80 /* NCAudioRecorderViewController.storyboard in Resources */,
AF56C1DC2784856200D8BAE2 /* NCActivityCommentView.xib in Resources */,
- F7632FBF21832F8700721B71 /* NCTrashSectionHeaderMenu.xib in Resources */,
F7F4F10B27ECDBDB008676F9 /* Inconsolata-Light.ttf in Resources */,
3704EB2A23D5A58400455C5B /* NCMenu.storyboard in Resources */,
AF93471C27E2361E002537EE /* NCShareAdvancePermissionHeader.xib in Resources */,
@@ -2332,6 +2319,7 @@
F749C10D23C4A5340027D966 /* NCIntro.storyboard in Resources */,
F7239877253D86D300257F49 /* NCEmptyView.xib in Resources */,
F747BA1F22354D2000971601 /* NCCreateFormUploadVoiceNote.storyboard in Resources */,
+ F719D9E0288D37A300762E33 /* NCColorPicker.storyboard in Resources */,
F7651A8A23A2A3F2001403D2 /* NCCreateFormUploadDocuments.storyboard in Resources */,
F7F4F10A27ECDBDB008676F9 /* Inconsolata-ExtraBold.ttf in Resources */,
F704B5E72430C06700632F5F /* NCCreateFormUploadConflictCell.xib in Resources */,
@@ -2345,12 +2333,11 @@
F73D11FA253C5F4800DF9BEC /* NCViewerNextcloudText.storyboard in Resources */,
F7EDE51B262DD0C400414FE6 /* NCSelectCommandViewCopyMove.xib in Resources */,
F73B422B2476764F00A30FD3 /* NCNotification.storyboard in Resources */,
+ F7FF2CB12842159500EBB7A1 /* NCSectionHeader.xib in Resources */,
F7D1612023CF19E30039EBBF /* NCViewerRichWorkspace.storyboard in Resources */,
F77B0F631D118A16002130FE /* Localizable.strings in Resources */,
- F7632FC1218353AA00721B71 /* NCTrashSectionFooter.xib in Resources */,
F774264A22EB4D0000B23912 /* NCSearchUserDropDownCell.xib in Resources */,
F7CB689A2541676B0050EC94 /* NCMore.storyboard in Resources */,
- F70B866D2642A21300ED5349 /* NCBackgroundImageColor.storyboard in Resources */,
F77B0F7D1D118A16002130FE /* Images.xcassets in Resources */,
F73CB3B222E072A000AD728E /* NCShareHeaderView.xib in Resources */,
F7AE00FA230E81EB007ACF8A /* NCBrowserWeb.storyboard in Resources */,
@@ -2411,6 +2398,7 @@
F785EEA52461A4CF00B3F945 /* CCUtility.m in Sources */,
2C1D5D7923E2DE9100334ABB /* NCBrand.swift in Sources */,
F770768A263A8A2500A1BA94 /* NCUtilityFileSystem.swift in Sources */,
+ F76D364928A4F8BF00214537 /* NCActivityIndicator.swift in Sources */,
F746EC50273906BA0052598D /* NCViewCertificateDetails.swift in Sources */,
AF4BF62127562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */,
F702F2D225EE5B5C008F8E80 /* NCGlobal.swift in Sources */,
@@ -2418,6 +2406,7 @@
2C1D5D7523E2DE3300334ABB /* NCDatabase.swift in Sources */,
F7E98C1927E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */,
2C1D5D7623E2DE3300334ABB /* NCManageDatabase.swift in Sources */,
+ F7245927289BB59300474787 /* ThreadSafeDictionary.swift in Sources */,
2C33C48223E2C475005F963B /* NotificationService.swift in Sources */,
AF4BF617275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */,
D575039F27146F93008DC9DC /* String+Extensions.swift in Sources */,
@@ -2448,6 +2437,7 @@
buildActionMask = 2147483647;
files = (
F746EC4E273906B80052598D /* NCViewCertificateDetails.swift in Sources */,
+ F7245925289BB59100474787 /* ThreadSafeDictionary.swift in Sources */,
F73D5E48246DE09200DF6467 /* NCElementsJSON.swift in Sources */,
F7EDE4E5262D7BBE00414FE6 /* NCSectionHeaderFooter.swift in Sources */,
F79EC78926316AC4004E59D6 /* NCPopupViewController.swift in Sources */,
@@ -2464,7 +2454,7 @@
AF4BF61A27562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */,
AF4BF615275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */,
F798F0E225880608000DAFFD /* UIColor+Extensions.swift in Sources */,
- AF3FDCC32796F3FB00710F60 /* NCTrashListCell.swift in Sources */,
+ AF3FDCC32796F3FB00710F60 /* NCTrashListCell+NCTrashCellProtocol.swift in Sources */,
AF817EF2274BC781009ED85B /* NCUserBaseUrl.swift in Sources */,
F78295311F962EFA00A572F5 /* NCEndToEndEncryption.m in Sources */,
F74AF3A5247FB6AE00AC767B /* NCUtilityFileSystem.swift in Sources */,
@@ -2485,6 +2475,7 @@
F7BAADC91ED5A87C00B7EAD4 /* NCDatabase.swift in Sources */,
F7D57C8B26317BDE00DE301D /* NCAccountRequest.swift in Sources */,
AF22B217277D196700DAB0CC /* NCShareExtension+DataSource.swift in Sources */,
+ F76D364728A4F8BF00214537 /* NCActivityIndicator.swift in Sources */,
F780710A1EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m in Sources */,
F79EC77F26316193004E59D6 /* NCRenameFile.swift in Sources */,
AF22B208277B4E4C00DAB0CC /* NCCreateFormUploadConflictCell.swift in Sources */,
@@ -2499,9 +2490,11 @@
buildActionMask = 2147483647;
files = (
F771E3F720E239B500AFB62D /* FileProviderExtension+Actions.swift in Sources */,
+ F7245926289BB59300474787 /* ThreadSafeDictionary.swift in Sources */,
F76673F022C90434007ED366 /* FileProviderUtility.swift in Sources */,
F7434B3420E23FD700417916 /* NCDatabase.swift in Sources */,
F702F2D125EE5B5C008F8E80 /* NCGlobal.swift in Sources */,
+ F76D364828A4F8BF00214537 /* NCActivityIndicator.swift in Sources */,
F7434B3820E2400600417916 /* NCBrand.swift in Sources */,
F785EE9E2461A09900B3F945 /* NCNetworking.swift in Sources */,
F746EC4F273906B90052598D /* NCViewCertificateDetails.swift in Sources */,
@@ -2544,7 +2537,6 @@
F70D87D025EE6E58008CBBBD /* NCRenameFile.swift in Sources */,
F7F4F0F727ECDBA4008676F9 /* NCSubtitles.swift in Sources */,
F790110E21415BF600D7B136 /* NCViewerRichdocument.swift in Sources */,
- F70B866E2642A21300ED5349 /* NCBackgroundImageColor.swift in Sources */,
F78ACD4021903CC20088454D /* NCGridCell.swift in Sources */,
F75B0ABD244C4DBB00E58DCA /* NCFunctionCenter.swift in Sources */,
AF935067276B84E700BD078F /* NCMenu+FloatingPanel.swift in Sources */,
@@ -2552,6 +2544,7 @@
F769454022E9F077000A798A /* NCSharePaging.swift in Sources */,
F78ACD4221903CE00088454D /* NCListCell.swift in Sources */,
F76D3CF12428B40E005DFA87 /* NCViewerPDFSearch.swift in Sources */,
+ F7245924289BB50C00474787 /* ThreadSafeDictionary.swift in Sources */,
F73F537F1E929C8500F8678D /* NCMore.swift in Sources */,
F702F2CF25EE5B5C008F8E80 /* NCGlobal.swift in Sources */,
F72CD63A25C19EBF00F46F9A /* NCAutoUpload.swift in Sources */,
@@ -2562,11 +2555,11 @@
371B5A2E23D0B04500FAFAE9 /* NCMenu.swift in Sources */,
F79EDAA326B004980007D134 /* NCPlayerToolBar.swift in Sources */,
F77444F8222816D5000D5EB0 /* NCPickerViewController.swift in Sources */,
+ F77BB74A2899857B0090FC19 /* UINavigationController+Extension.swift in Sources */,
F72A47EC2487B06B005AD489 /* NCOperationQueue.swift in Sources */,
F769454622E9F1B0000A798A /* NCShareCommon.swift in Sources */,
F738E8421F90FFD100F95C8E /* NCManageEndToEndEncryption.m in Sources */,
F70753F12542A9A200972D44 /* NCViewerMedia.swift in Sources */,
- F7A80BCB252624C100C7CD01 /* NCFileViewInFolder.swift in Sources */,
F78A18B823CDE2B300F681F3 /* NCViewerRichWorkspace.swift in Sources */,
F77910AB25DD53C700CEDB9E /* NCSettingsBundleHelper.swift in Sources */,
AF4BF61927562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */,
@@ -2586,6 +2579,7 @@
F704B5E92430C0B800632F5F /* NCCreateFormUploadConflictCell.swift in Sources */,
F72D404923D2082500A97FD0 /* NCViewerNextcloudText.swift in Sources */,
AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */,
+ F77BB746289984CA0090FC19 /* UIViewController+Extension.swift in Sources */,
F700510522DF6A89003A3356 /* NCShare.swift in Sources */,
F72D1007210B6882009C96B7 /* NCPushNotificationEncryption.m in Sources */,
F785EE9D246196DF00B3F945 /* NCNetworkingE2EE.swift in Sources */,
@@ -2594,7 +2588,7 @@
F77B0E4F1D118A16002130FE /* CCManageAutoUpload.m in Sources */,
F7BAADC81ED5A87C00B7EAD4 /* NCDatabase.swift in Sources */,
F75C0C4823D1FAE300163CC8 /* NCRichWorkspaceCommon.swift in Sources */,
- F78ACD4A21903F850088454D /* NCTrashListCell.swift in Sources */,
+ F78ACD4A21903F850088454D /* NCTrashListCell+NCTrashCellProtocol.swift in Sources */,
F7B8CD91261AF3F7007C1359 /* NCNetworkingChunkedUpload.swift in Sources */,
F760329F252F0F8E0015A421 /* NCTransferCell.swift in Sources */,
AF68326A27BE65A90010BF0B /* NCMenuAction.swift in Sources */,
@@ -2610,7 +2604,6 @@
F7F4F0F927ECDBA4008676F9 /* NCSubtitlePlayer.swift in Sources */,
F7651A8B23A2A3F2001403D2 /* NCCreateFormUploadDocuments.swift in Sources */,
F74AF3A4247FB6AE00AC767B /* NCUtilityFileSystem.swift in Sources */,
- F7417DB3216CE925007D05F5 /* NCTrashSectionHeaderFooter.swift in Sources */,
F7239871253D86B600257F49 /* NCEmptyDataSet.swift in Sources */,
AFCE353327E4ED1900FEA6C2 /* UIToolbar+Extension.swift in Sources */,
8491B1CD273BBA82001C8C5B /* UIViewController+Menu.swift in Sources */,
@@ -2633,6 +2626,7 @@
AFCE353527E4ED5900FEA6C2 /* DateFormatter+Extension.swift in Sources */,
F718C24E254D507B00C5C256 /* NCViewerMediaDetailView.swift in Sources */,
F7381EE1218218C9000B1560 /* NCOffline.swift in Sources */,
+ F719D9E2288D396100762E33 /* NCColorPicker.swift in Sources */,
F78071091EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m in Sources */,
F79B646026CA661600838ACA /* UIControl+Extensions.swift in Sources */,
F7CA212D25F1333300826ABB /* NCAccountRequest.swift in Sources */,
@@ -2654,6 +2648,7 @@
AF3FDCC22796ECC300710F60 /* NCTrash+CollectionView.swift in Sources */,
F7DFB7F4219C5CA800680748 /* NCCreateFormUploadScanDocument.swift in Sources */,
F70D7C3725FFBF82002B9E34 /* NCCollectionViewCommon.swift in Sources */,
+ F76D364628A4F8BF00214537 /* NCActivityIndicator.swift in Sources */,
F7020FCE2233D7F700B7297D /* NCCreateFormUploadVoiceNote.swift in Sources */,
F7134186259747BA00768D21 /* NCPushNotification.m in Sources */,
F726EEEC1FED1C820030B9C8 /* NCEndToEndInitialize.swift in Sources */,
@@ -2663,6 +2658,7 @@
AF93471B27E2361E002537EE /* NCShareAdvancePermission.swift in Sources */,
F70753EB2542A99800972D44 /* NCViewerMediaPage.swift in Sources */,
F74C0436253F1CDC009762AB /* NCShares.swift in Sources */,
+ F7AC1CB028AB94490032D99F /* Array+Extensions.swift in Sources */,
F7AE00F5230D5F9E007ACF8A /* NCLoginWeb.swift in Sources */,
F707C26521A2DC5200F6181E /* NCStoreReview.swift in Sources */,
F7BAADCB1ED5A87C00B7EAD4 /* NCManageDatabase.swift in Sources */,
@@ -2678,6 +2674,7 @@
F704B5E52430AA8000632F5F /* NCCreateFormUploadConflict.swift in Sources */,
F765608F23BF813600765969 /* NCContentPresenter.swift in Sources */,
F70CEF5623E9C7E50007035B /* UIColor+Extensions.swift in Sources */,
+ F77BB748289985270090FC19 /* UITabBarController+Extension.swift in Sources */,
F75AC2431F1F62450073EC19 /* NCManageAutoUploadFileName.swift in Sources */,
F7C7B489245EBA4100D93E60 /* NCViewerQuickLook.swift in Sources */,
F758B45E212C569D00515F55 /* NCScanCell.swift in Sources */,
@@ -2831,6 +2828,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/iOSClient/Brand/Notification_Service_Extension.entitlements";
+ DEVELOPMENT_TEAM = NKUJUXUJ3B;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
EXTENSION,
@@ -2840,7 +2838,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.Notification-Service-Extension";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_NOTIFICATION_SERVICE";
- SWIFT_OBJC_BRIDGING_HEADER = "Notification Service Extension/Notification_Service_Extension-Bridging-Header.h";
+ SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/Notification Service Extension/Notification_Service_Extension-Bridging-Header.h";
};
name = Debug;
};
@@ -2848,6 +2846,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/iOSClient/Brand/Notification_Service_Extension.entitlements";
+ DEVELOPMENT_TEAM = NKUJUXUJ3B;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
EXTENSION,
@@ -2857,7 +2856,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.Notification-Service-Extension";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_NOTIFICATION_SERVICE";
- SWIFT_OBJC_BRIDGING_HEADER = "Notification Service Extension/Notification_Service_Extension-Bridging-Header.h";
+ SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/Notification Service Extension/Notification_Service_Extension-Bridging-Header.h";
};
name = Release;
};
@@ -2866,6 +2865,7 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
+ DEVELOPMENT_TEAM = NKUJUXUJ3B;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudTests;
@@ -2879,6 +2879,7 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
+ DEVELOPMENT_TEAM = NKUJUXUJ3B;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudTests;
@@ -2891,6 +2892,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = iOSClient/Brand/Share.entitlements;
+ DEVELOPMENT_TEAM = NKUJUXUJ3B;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
EXTENSION,
@@ -2900,7 +2902,7 @@
PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.Share;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_SHARE";
- SWIFT_OBJC_BRIDGING_HEADER = "Share/Share-Bridging-Header.h";
+ SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/Share/Share-Bridging-Header.h";
};
name = Debug;
};
@@ -2908,6 +2910,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = iOSClient/Brand/Share.entitlements;
+ DEVELOPMENT_TEAM = NKUJUXUJ3B;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
EXTENSION,
@@ -2917,7 +2920,7 @@
PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.Share;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_SHARE";
- SWIFT_OBJC_BRIDGING_HEADER = "Share/Share-Bridging-Header.h";
+ SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/Share/Share-Bridging-Header.h";
};
name = Release;
};
@@ -2925,6 +2928,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/iOSClient/Brand/File_Provider_Extension.entitlements";
+ DEVELOPMENT_TEAM = NKUJUXUJ3B;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
EXTENSION,
@@ -2934,7 +2938,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.File-Provider-Extension";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_FILE_PROVIDER_EXTENSION";
- SWIFT_OBJC_BRIDGING_HEADER = "File Provider Extension/FileProviderExtension-Bridging-Header.h";
+ SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/File Provider Extension/FileProviderExtension-Bridging-Header.h";
};
name = Debug;
};
@@ -2942,6 +2946,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/iOSClient/Brand/File_Provider_Extension.entitlements";
+ DEVELOPMENT_TEAM = NKUJUXUJ3B;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
EXTENSION,
@@ -2951,7 +2956,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.File-Provider-Extension";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_FILE_PROVIDER_EXTENSION";
- SWIFT_OBJC_BRIDGING_HEADER = "File Provider Extension/FileProviderExtension-Bridging-Header.h";
+ SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/File Provider Extension/FileProviderExtension-Bridging-Header.h";
};
name = Release;
};
@@ -2960,10 +2965,10 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = iOSClient/Brand/iOSClient.entitlements;
+ DEVELOPMENT_TEAM = NKUJUXUJ3B;
INFOPLIST_FILE = "$(SRCROOT)/iOSClient/Brand/iOSClient.plist";
PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_OBJC_BRIDGING_HEADER = "iOSClient/Nextcloud-Bridging-Header.h";
};
name = Debug;
};
@@ -2972,10 +2977,10 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = iOSClient/Brand/iOSClient.entitlements;
+ DEVELOPMENT_TEAM = NKUJUXUJ3B;
INFOPLIST_FILE = "$(SRCROOT)/iOSClient/Brand/iOSClient.plist";
PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_OBJC_BRIDGING_HEADER = "iOSClient/Nextcloud-Bridging-Header.h";
};
name = Release;
};
@@ -3006,12 +3011,13 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 18;
+ CURRENT_PROJECT_VERSION = 19;
DEVELOPMENT_TEAM = 6JLRKY9ZV7;
ENABLE_BITCODE = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
DEBUG,
@@ -3029,11 +3035,12 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = 4.4.0;
+ MARKETING_VERSION = 4.4.1;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "";
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) NC";
+ SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/iOSClient/Brand/Nextcloud-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@@ -3067,10 +3074,11 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 18;
+ CURRENT_PROJECT_VERSION = 19;
DEVELOPMENT_TEAM = 6JLRKY9ZV7;
ENABLE_BITCODE = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
@@ -3088,12 +3096,13 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = 4.4.0;
+ MARKETING_VERSION = 4.4.1;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "";
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG NC";
SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/iOSClient/Brand/Nextcloud-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@@ -3176,14 +3185,6 @@
minimumVersion = 10.0.0;
};
};
- F7233B3827835FA300F40A43 /* XCRemoteSwiftPackageReference "ChromaColorPicker" */ = {
- isa = XCRemoteSwiftPackageReference;
- repositoryURL = "https://github.com/marinofaggiana/ChromaColorPicker";
- requirement = {
- branch = master;
- kind = branch;
- };
- };
F72CD01027A7E92400E59476 /* XCRemoteSwiftPackageReference "JGProgressHUD" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/JonasGessner/JGProgressHUD.git";
@@ -3285,7 +3286,7 @@
repositoryURL = "https://github.com/nextcloud/ios-communication-library/";
requirement = {
kind = exactVersion;
- version = 0.99.6;
+ version = 0.99.8;
};
};
F788ECC5263AAAF900ADC67F /* XCRemoteSwiftPackageReference "MarkdownKit" */ = {
@@ -3360,11 +3361,6 @@
package = F710FC78277B7CFF00AA9FBF /* XCRemoteSwiftPackageReference "realm-swift" */;
productName = RealmSwift;
};
- F7233B3927835FA400F40A43 /* ChromaColorPicker */ = {
- isa = XCSwiftPackageProductDependency;
- package = F7233B3827835FA300F40A43 /* XCRemoteSwiftPackageReference "ChromaColorPicker" */;
- productName = ChromaColorPicker;
- };
F72CD01127A7E92400E59476 /* JGProgressHUD */ = {
isa = XCSwiftPackageProductDependency;
package = F72CD01027A7E92400E59476 /* XCRemoteSwiftPackageReference "JGProgressHUD" */;
diff --git a/README.md b/README.md
index b34a1a128..38d8614a9 100644
--- a/README.md
+++ b/README.md
@@ -2,20 +2,17 @@
[![Releases](https://img.shields.io/github/release/nextcloud/ios.svg)](https://github.com/nextcloud/ios/releases/latest) [![Build](https://github.com/nextcloud/ios/actions/workflows/xcode.yml/badge.svg)](https://github.com/nextcloud/ios/actions/workflows/xcode.yml) [![SwiftLint](https://github.com/nextcloud/ios/actions/workflows/lint.yml/badge.svg)](https://github.com/nextcloud/ios/actions/workflows/lint.yml)
[![irc](https://img.shields.io/badge/IRC-%23nextcloud--mobile%20on%20freenode-blue.svg)](https://webchat.freenode.net/?channels=nextcloud-mobile)
-<img src="Animation.gif"
-alt="Demo of the Nextcloud iOS files app"
-height="400">
+<img src="Animation.gif" alt="Demo of the Nextcloud iOS files app" width="277" height="600">
[<img src="https://developer.apple.com/assets/elements/badges/download-on-the-app-store.svg"
alt="Demo of the Nextcloud iOS files app"
height="40">](https://itunes.apple.com/us/app/nextcloud/id1125420102)
-Check out https://nextcloud.com and follow us on [twitter.com/nextclouders](https://twitter.com/nextclouders) or [twitter.com/NextcloudiOS](https://twitter.com/NextcloudiOS)
+Check out https://nextcloud.com and follow us on [twitter.com/nextclouders](https://twitter.com/nextclouders)
## How to contribute
If you want to [contribute](https://nextcloud.com/contribute/) to Nextcloud, you are very welcome:
-- on our IRC channels [![irc](https://img.shields.io/badge/IRC-%23nextcloud%20on%20freenode-orange.svg)](https://webchat.freenode.net/?channels=nextcloud) and [![irc](https://img.shields.io/badge/IRC-%23nextcloud--mobile%20on%20freenode-blue.svg)](https://webchat.freenode.net/?channels=nextcloud-mobile) on freenode
- our forum at https://help.nextcloud.com/c/clients/ios
- for translations of the app on [Transifex](https://www.transifex.com/nextcloud/nextcloud/dashboard/)
- opening issues and PRs (including a corresponding issue)
@@ -41,15 +38,15 @@ branch. Maybe start working on [starter issues](https://github.com/nextcloud/ios
Easy starting points are also reviewing [pull requests](https://github.com/nextcloud/ios/pulls)
-### Xcode 13.1 Project Setup
+### Xcode 13.4 Project Setup
#### Dependencies
-After forking a repository you have to build the dependencies. Dependencies are managed with Carthage version 0.37.0 or later.
+After forking a repository you have to build the dependencies. Dependencies are managed with Carthage version 0.38.0 or later.
Run
```
-carthage update --use-xcframeworks --platform iOS --cache-builds
+carthage update --use-xcframeworks --platform iOS
```
to fetch and compile the dependencies.
@@ -75,10 +72,10 @@ Git even has a `-s | --signoff` command line option to append this to your commi
## Support
-If you need assistance or want to ask a question about the iOS app, you are welcome to [ask for support](https://help.nextcloud.com/c/clients/ios) in our forums or the [IRC-Channel](https://webchat.freenode.net/?channels=nextcloud-mobile). If you have found a bug, feel free to [open a new Issue on GitHub](https://github.com/nextcloud/ios/issues). Keep in mind, that this repository only manages the iOS app. If you find bugs or have problems with the server/backend, you should ask the [Nextcloud server team](https://github.com/nextcloud/server) for help!
+If you need assistance or want to ask a question about the iOS app, you are welcome to [ask for support](https://help.nextcloud.com/c/clients/ios) in our Forums. If you have found a bug, feel free to [open a new Issue on GitHub](https://github.com/nextcloud/ios/issues). Keep in mind, that this repository only manages the iOS app. If you find bugs or have problems with the server/backend, you should ask the [Nextcloud server team](https://github.com/nextcloud/server) for help!
## TestFlight
Do you want to try the latest version in development of Nextcloud iOS ? Simple, follow this simple step
-[Apple TestFlight](https://testflight.apple.com/join/GjNbfo2a)
+[Apple TestFlight](https://testflight.apple.com/join/RXEJbWj9)
diff --git a/Share/NCShareExtension+DataSource.swift b/Share/NCShareExtension+DataSource.swift
index ef2ec2a99..a3c07e69f 100644
--- a/Share/NCShareExtension+DataSource.swift
+++ b/Share/NCShareExtension+DataSource.swift
@@ -47,11 +47,11 @@ extension NCShareExtension: UICollectionViewDelegate {
extension NCShareExtension: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
- return 1
+ return dataSource.numberOfSections()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
- let numberOfItems = dataSource.numberOfItems()
+ let numberOfItems = dataSource.numberOfItemsInSection(section)
emptyDataSet?.numberOfItemsInSection(numberOfItems, section: section)
return numberOfItems
}
@@ -81,7 +81,7 @@ extension NCShareExtension: UICollectionViewDataSource {
cell.progressView.progress = 0.0
if metadata.directory {
- setupDirectoryCell(cell, with: metadata)
+ setupDirectoryCell(cell, indexPath: indexPath, with: metadata)
}
// image Favorite
@@ -106,7 +106,7 @@ extension NCShareExtension: UICollectionViewDataSource {
return cell
}
- func setupDirectoryCell(_ cell: NCListCell, with metadata: tableMetadata) {
+ func setupDirectoryCell(_ cell: NCListCell, indexPath: IndexPath, with metadata: tableMetadata) {
var isShare = false
var isMounted = false
if let metadataFolder = metadataFolder {
@@ -114,10 +114,7 @@ extension NCShareExtension: UICollectionViewDataSource {
isMounted = metadata.permissions.contains(NCGlobal.shared.permissionMounted) && !metadataFolder.permissions.contains(NCGlobal.shared.permissionMounted)
}
- var tableShare: tableShare?
- if dataSource.metadataShare[metadata.ocId] != nil {
- tableShare = dataSource.metadataShare[metadata.ocId]
- }
+ let tableShare = dataSource.metadatasForSection[indexPath.section].metadataShare[metadata.ocId]
if metadata.e2eEncrypted {
cell.imageItem.image = NCBrandColor.cacheImages.folderEncrypted
diff --git a/Share/NCShareExtension+Files.swift b/Share/NCShareExtension+Files.swift
index 8a1ccf6bf..495dff95a 100644
--- a/Share/NCShareExtension+Files.swift
+++ b/Share/NCShareExtension+Files.swift
@@ -27,16 +27,25 @@ extension NCShareExtension {
@objc func reloadDatasource(withLoadFolder: Bool) {
+ var groupByField = "name"
+
layoutForView = NCUtility.shared.getLayoutForView(key: keyLayout, serverUrl: serverUrl)
- let metadatasSource = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND directory == true", activeAccount.account, serverUrl))
+ // set GroupField for Grid
+ if layoutForView?.layout == NCGlobal.shared.layoutGrid {
+ groupByField = "classFile"
+ }
+
+ let metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND directory == true", activeAccount.account, serverUrl))
self.dataSource = NCDataSource(
- metadatasSource: metadatasSource,
+ metadatas: metadatas,
+ account: activeAccount.account,
sort: layoutForView?.sort,
ascending: layoutForView?.ascending,
directoryOnTop: layoutForView?.directoryOnTop,
favoriteOnTop: true,
- filterLivePhoto: true)
+ filterLivePhoto: true,
+ groupByField: groupByField)
if withLoadFolder {
loadFolder()
@@ -48,6 +57,7 @@ extension NCShareExtension {
}
@objc func didCreateFolder(_ notification: NSNotification) {
+
guard let userInfo = notification.userInfo as NSDictionary?,
let ocId = userInfo["ocId"] as? String,
let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId)
diff --git a/Share/NCShareExtension+NCDelegate.swift b/Share/NCShareExtension+NCDelegate.swift
index 17f6e379a..50929180b 100644
--- a/Share/NCShareExtension+NCDelegate.swift
+++ b/Share/NCShareExtension+NCDelegate.swift
@@ -76,6 +76,10 @@ extension NCShareExtension: NCEmptyDataSetDelegate, NCAccountRequestDelegate {
}
self.activeAccount = activeAccount
+ // COLORS
+ NCBrandColor.shared.settingThemingColor(account: activeAccount.account)
+ NCBrandColor.shared.createUserColors()
+
// NETWORKING
NCCommunicationCommon.shared.setup(
account: activeAccount.account,
diff --git a/Share/NCShareExtension.swift b/Share/NCShareExtension.swift
index 831dc455c..d22714e40 100644
--- a/Share/NCShareExtension.swift
+++ b/Share/NCShareExtension.swift
@@ -121,11 +121,19 @@ class NCShareExtension: UIViewController {
NCCommunicationCommon.shared.pathLog = pathDirectoryGroup
}
if isSimulatorOrTestFlight {
- NCCommunicationCommon.shared.writeLog("Start session with level \(levelLog) " + versionNextcloudiOS + " (Simulator / TestFlight)")
+ NCCommunicationCommon.shared.writeLog("Start Share session with level \(levelLog) " + versionNextcloudiOS + " (Simulator / TestFlight)")
} else {
- NCCommunicationCommon.shared.writeLog("Start session with level \(levelLog) " + versionNextcloudiOS)
+ NCCommunicationCommon.shared.writeLog("Start Share session with level \(levelLog) " + versionNextcloudiOS)
}
+ // Colors
+ if let activeAccount = NCManageDatabase.shared.getActiveAccount() {
+ NCBrandColor.shared.settingThemingColor(account: activeAccount.account)
+ } else {
+ NCBrandColor.shared.createImagesThemingColor()
+ }
+ NCBrandColor.shared.createUserColors()
+
hud.indicatorView = JGProgressHUDRingIndicatorView()
if let indicatorView = hud.indicatorView as? JGProgressHUDRingIndicatorView {
indicatorView.ringWidth = 1.5
@@ -303,8 +311,7 @@ extension NCShareExtension {
fileName: fileName, fileNameView: fileName,
ocId: ocId,
serverUrl: serverUrl, urlBase: activeAccount.urlBase, url: "",
- contentType: "",
- livePhoto: false)
+ contentType: "")
metadata.session = NCCommunicationCommon.shared.sessionIdentifierUpload
metadata.sessionSelector = NCGlobal.shared.selectorUploadFileShareExtension
metadata.size = NCUtilityFileSystem.shared.getFileSize(filePath: toPath)
@@ -332,7 +339,10 @@ extension NCShareExtension {
guard uploadStarted else { return }
guard uploadMetadata.count > counterUploaded else { return finishedUploading() }
let metadata = uploadMetadata[counterUploaded]
-
+ let results = NCCommunicationCommon.shared.getInternalType(fileName: metadata.fileNameView, mimeType: metadata.contentType, directory: false)
+ metadata.contentType = results.mimeType
+ metadata.iconName = results.iconName
+ metadata.classFile = results.classFile
// E2EE
metadata.e2eEncrypted = CCUtility.isFolderEncrypted(metadata.serverUrl, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase)
// CHUNCK
diff --git a/iOSClient/Main/Account Request/NCAccountRequest.storyboard b/iOSClient/Account Request/NCAccountRequest.storyboard
index 5f563280e..5f563280e 100644
--- a/iOSClient/Main/Account Request/NCAccountRequest.storyboard
+++ b/iOSClient/Account Request/NCAccountRequest.storyboard
diff --git a/iOSClient/Main/Account Request/NCAccountRequest.swift b/iOSClient/Account Request/NCAccountRequest.swift
index 5036dca16..c5d8bfd0f 100644
--- a/iOSClient/Main/Account Request/NCAccountRequest.swift
+++ b/iOSClient/Account Request/NCAccountRequest.swift
@@ -66,6 +66,9 @@ class NCAccountRequest: UIViewController {
tableView.tableFooterView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 1))
tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
+ view.backgroundColor = NCBrandColor.shared.secondarySystemBackground
+ tableView.backgroundColor = NCBrandColor.shared.secondarySystemBackground
+
progressView.trackTintColor = .clear
progressView.progress = 1
if enableTimerProgress {
@@ -76,8 +79,6 @@ class NCAccountRequest: UIViewController {
NotificationCenter.default.addObserver(self, selector: #selector(startTimer), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidBecomeActive), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(applicationDidEnterBackground), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidEnterBackground), object: nil)
-
- changeTheming()
}
override func viewWillAppear(_ animated: Bool) {
@@ -102,22 +103,6 @@ class NCAccountRequest: UIViewController {
timer?.invalidate()
}
- override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
- super.traitCollectionDidChange(previousTraitCollection)
-
- changeTheming()
- }
-
- // MARK: - Theming
-
- @objc func changeTheming() {
-
- view.backgroundColor = NCBrandColor.shared.secondarySystemBackground
- tableView.backgroundColor = NCBrandColor.shared.secondarySystemBackground
-
- tableView.reloadData()
- }
-
// MARK: - Action
@IBAction func actionClose(_ sender: UIButton) {
@@ -241,11 +226,11 @@ extension NCAccountRequest: UITableViewDataSource {
displayName: account.displayName,
userBaseUrl: account)
- if account.alias != "" {
- userLabel?.text = account.alias.uppercased()
- } else {
+ if account.alias.isEmpty {
userLabel?.text = account.user.uppercased()
urlLabel?.text = (URL(string: account.urlBase)?.host ?? "")
+ } else {
+ userLabel?.text = account.alias.uppercased()
}
if account.active {
diff --git a/iOSClient/Activity/NCActivity.swift b/iOSClient/Activity/NCActivity.swift
index 39edd3544..30ad4e552 100644
--- a/iOSClient/Activity/NCActivity.swift
+++ b/iOSClient/Activity/NCActivity.swift
@@ -68,10 +68,6 @@ class NCActivity: UIViewController, NCSharePagingContent {
tableView.contentInset = insets
tableView.backgroundColor = NCBrandColor.shared.systemBackground
- NotificationCenter.default.addObserver(self, selector: #selector(self.changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil)
-
- changeTheming()
-
if showComments {
setupComments()
}
@@ -124,10 +120,7 @@ class NCActivity: UIViewController, NCSharePagingContent {
@objc func initialize() {
loadDataSource()
fetchAll(isInitial: true)
- }
-
- @objc func changeTheming() {
- tableView.reloadData()
+ view.setNeedsLayout()
}
func makeTableFooterView() -> UIView {
@@ -222,7 +215,7 @@ extension NCActivity: UITableViewDataSource {
// Image
let fileName = appDelegate.userBaseUrl + "-" + comment.actorId + ".png"
- NCOperationQueue.shared.downloadAvatar(user: comment.actorId, dispalyName: comment.actorDisplayName, fileName: fileName, cell: cell, view: tableView)
+ NCOperationQueue.shared.downloadAvatar(user: comment.actorId, dispalyName: comment.actorDisplayName, fileName: fileName, cell: cell, view: tableView, cellImageView: cell.fileAvatarImageView)
// Username
cell.labelUser.text = comment.actorDisplayName
cell.labelUser.textColor = NCBrandColor.shared.label
@@ -265,8 +258,9 @@ extension NCActivity: UITableViewDataSource {
let fileNameLocalPath = CCUtility.getDirectoryUserData() + "/" + fileNameIcon
if FileManager.default.fileExists(atPath: fileNameLocalPath) {
- let image = NCUtility.shared.loadImage(named: fileNameIcon, color: NCBrandColor.shared.gray)
- cell.icon.image = image
+ if let image = UIImage(contentsOfFile: fileNameLocalPath) {
+ cell.icon.image = image
+ }
} else {
NCCommunication.shared.downloadContent(serverUrl: activity.icon) { _, data, errorCode, _ in
if errorCode == 0 {
@@ -288,10 +282,11 @@ extension NCActivity: UITableViewDataSource {
let fileName = appDelegate.userBaseUrl + "-" + activity.user + ".png"
- NCOperationQueue.shared.downloadAvatar(user: activity.user, dispalyName: nil, fileName: fileName, cell: cell, view: tableView)
+ NCOperationQueue.shared.downloadAvatar(user: activity.user, dispalyName: nil, fileName: fileName, cell: cell, view: tableView, cellImageView: cell.fileAvatarImageView)
}
// subject
+ cell.subject.text = activity.subject
if activity.subjectRich.count > 0 {
var subject = activity.subjectRich
@@ -357,8 +352,11 @@ extension NCActivity {
guard !isFetchingActivity else { return }
self.isFetchingActivity = true
- let height = self.tabBarController?.tabBar.frame.size.height ?? 0
- NCUtility.shared.startActivityIndicator(backgroundView: self.view, blurEffect: false, bottom: height + 50, style: .gray)
+ var bottom: CGFloat = 0
+ if let mainTabBar = self.tabBarController?.tabBar as? NCMainTabBar {
+ bottom = -mainTabBar.getHight()
+ }
+ NCActivityIndicator.shared.start(backgroundView: self.view, bottom: bottom-5, style: .gray)
let dispatchGroup = DispatchGroup()
loadComments(disptachGroup: dispatchGroup)
@@ -371,7 +369,7 @@ extension NCActivity {
dispatchGroup.notify(queue: .main) {
self.loadDataSource()
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
// otherwise is triggered again
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
@@ -422,11 +420,10 @@ extension NCActivity {
/// Check if most recent activivities are loaded, if not trigger reload
func checkRecentActivity(disptachGroup: DispatchGroup) {
- let recentActivityId = NCManageDatabase.shared.getLatestActivityId(account: appDelegate.account)
-
- guard recentActivityId > 0, metadata == nil, hasActivityToLoad else {
+ guard let result = NCManageDatabase.shared.getLatestActivityId(account: appDelegate.account), metadata == nil, hasActivityToLoad else {
return self.loadActivity(idActivity: 0, disptachGroup: disptachGroup)
}
+ let resultActivityId = max(result.activityFirstKnown, result.activityLastGiven)
disptachGroup.enter()
@@ -435,25 +432,26 @@ extension NCActivity {
limit: 1,
objectId: nil,
objectType: objectType,
- previews: true) { account, activities, errorCode, _ in
+ previews: true) { account, _, activityFirstKnown, activityLastGiven, errorCode, _ in
defer { disptachGroup.leave() }
+ let largestActivityId = max(activityFirstKnown, activityLastGiven)
guard errorCode == 0,
account == self.appDelegate.account,
- let activity = activities.first,
- activity.idActivity > recentActivityId
+ largestActivityId > resultActivityId
else {
self.hasActivityToLoad = errorCode == 304 ? false : self.hasActivityToLoad
return
}
- self.loadActivity(idActivity: 0, limit: activity.idActivity - recentActivityId, disptachGroup: disptachGroup)
+ self.loadActivity(idActivity: 0, limit: largestActivityId - resultActivityId, disptachGroup: disptachGroup)
}
}
func loadActivity(idActivity: Int, limit: Int = 200, disptachGroup: DispatchGroup) {
guard hasActivityToLoad else { return }
+ var resultActivityId = 0
disptachGroup.enter()
NCCommunication.shared.getActivity(
@@ -461,7 +459,7 @@ extension NCActivity {
limit: min(limit, 200),
objectId: metadata?.fileId,
objectType: objectType,
- previews: true) { account, activities, errorCode, _ in
+ previews: true) { account, activities, activityFirstKnown, activityLastGiven, errorCode, _ in
defer { disptachGroup.leave() }
guard errorCode == 0,
account == self.appDelegate.account,
@@ -473,8 +471,12 @@ extension NCActivity {
NCManageDatabase.shared.addActivity(activities, account: account)
// update most recently loaded activity only when all activities are loaded (not filtered)
- if self.metadata == nil {
- NCManageDatabase.shared.updateLatestActivityId(activities, account: account)
+ let largestActivityId = max(activityFirstKnown, activityLastGiven)
+ if let result = NCManageDatabase.shared.getLatestActivityId(account: self.appDelegate.account) {
+ resultActivityId = max(result.activityFirstKnown, result.activityLastGiven)
+ }
+ if self.metadata == nil, largestActivityId > resultActivityId {
+ NCManageDatabase.shared.updateLatestActivityId(activityFirstKnown: activityFirstKnown, activityLastGiven: activityLastGiven, account: account)
}
}
}
diff --git a/iOSClient/Activity/NCActivityTableViewCell.swift b/iOSClient/Activity/NCActivityTableViewCell.swift
index f75c88d62..40b3307a5 100644
--- a/iOSClient/Activity/NCActivityTableViewCell.swift
+++ b/iOSClient/Activity/NCActivityTableViewCell.swift
@@ -23,11 +23,14 @@
import Foundation
import NCCommunication
+import FloatingPanel
class NCActivityCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var imageView: UIImageView!
+ var fileId = ""
+
override func awakeFromNib() {
super.awakeFromNib()
}
@@ -47,38 +50,16 @@ class NCActivityTableViewCell: UITableViewCell, NCCellProtocol {
private var user: String = ""
var idActivity: Int = 0
- var account: String = ""
var activityPreviews: [tableActivityPreview] = []
var didSelectItemEnable: Bool = true
var viewController: UIViewController?
var fileAvatarImageView: UIImageView? {
- get {
- return avatar
- }
- }
- var fileObjectId: String? {
- get {
- return nil
- }
- }
- var filePreviewImageView: UIImageView? {
- get {
- return nil
- }
+ get { return avatar }
}
var fileUser: String? {
- get {
- return user
- }
- set {
- user = newValue ?? ""
- }
- }
-
- @objc func tapAvatarImage() {
- guard let fileUser = fileUser else { return }
- viewController?.showProfileMenu(userId: fileUser)
+ get { return user }
+ set { user = newValue ?? "" }
}
override func awakeFromNib() {
@@ -89,6 +70,11 @@ class NCActivityTableViewCell: UITableViewCell, NCCellProtocol {
let avatarRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapAvatarImage))
avatar.addGestureRecognizer(avatarRecognizer)
}
+
+ @objc func tapAvatarImage() {
+ guard let fileUser = fileUser else { return }
+ viewController?.showProfileMenu(userId: fileUser)
+ }
}
// MARK: - Collection View
@@ -130,7 +116,7 @@ extension NCActivityTableViewCell: UICollectionViewDelegate {
return
}
- if activityPreview.view == "files" && activityPreview.mimeType != "dir" {
+ if activityPreview.view == NCGlobal.shared.appName && activityPreview.mimeType != "dir" {
guard let activitySubjectRich = NCManageDatabase.shared.getActivitySubjectRich(account: activityPreview.account, idActivity: activityPreview.idActivity, id: String(activityPreview.fileId)) else {
return
@@ -156,11 +142,12 @@ extension NCActivityTableViewCell: UICollectionViewDelegate {
var pathComponents = activityPreview.link.components(separatedBy: "?")
pathComponents = pathComponents[1].components(separatedBy: "&")
var serverUrlFileName = pathComponents[0].replacingOccurrences(of: "dir=", with: "").removingPercentEncoding!
- serverUrlFileName = appDelegate.urlBase + "/" + NCUtilityFileSystem.shared.getWebDAV(account: activityPreview.account) + serverUrlFileName + "/" + activitySubjectRich.name
-
+ serverUrlFileName = NCUtilityFileSystem.shared.getHomeServer(account: activityPreview.account) + serverUrlFileName + "/" + activitySubjectRich.name
let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(activitySubjectRich.id, fileNameView: activitySubjectRich.name)!
- NCUtility.shared.startActivityIndicator(backgroundView: (appDelegate.window?.rootViewController?.view)!, blurEffect: true)
+ if let backgroundView = appDelegate.window?.rootViewController?.view {
+ NCActivityIndicator.shared.start(backgroundView: backgroundView)
+ }
NCCommunication.shared.download(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, requestHandler: { _ in
@@ -176,28 +163,30 @@ extension NCActivityTableViewCell: UICollectionViewDelegate {
let fileName = (serverUrlFileName as NSString).lastPathComponent
let serverUrlFileName = serverUrl + "/" + fileName
- NCNetworking.shared.readFile(serverUrlFileName: serverUrlFileName, account: activityPreview.account) { account, metadata, errorCode, _ in
+ NCNetworking.shared.readFile(serverUrlFileName: serverUrlFileName) { account, metadata, errorCode, _ in
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
- if account == self.appDelegate.account && errorCode == 0 {
+ DispatchQueue.main.async {
+ if account == self.appDelegate.account, errorCode == 0, let metadata = metadata {
- // move from id to oc:id + instanceid (ocId)
- let atPath = CCUtility.getDirectoryProviderStorage()! + "/" + activitySubjectRich.id
- let toPath = CCUtility.getDirectoryProviderStorage()! + "/" + metadata!.ocId
+ // move from id to oc:id + instanceid (ocId)
+ let atPath = CCUtility.getDirectoryProviderStorage()! + "/" + activitySubjectRich.id
+ let toPath = CCUtility.getDirectoryProviderStorage()! + "/" + metadata.ocId
- CCUtility.moveFile(atPath: atPath, toPath: toPath)
+ CCUtility.moveFile(atPath: atPath, toPath: toPath)
- NCManageDatabase.shared.addMetadata(metadata!)
- if let viewController = self.viewController {
- NCViewer.shared.view(viewController: viewController, metadata: metadata!, metadatas: [metadata!], imageIcon: cell?.imageView.image)
+ NCManageDatabase.shared.addMetadata(metadata)
+ if let viewController = self.viewController {
+ NCViewer.shared.view(viewController: viewController, metadata: metadata, metadatas: [metadata], imageIcon: cell?.imageView.image)
+ }
}
}
}
} else {
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
}
}
}
@@ -211,7 +200,8 @@ extension NCActivityTableViewCell: UICollectionViewDataSource {
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
- return activityPreviews.count
+ let results = activityPreviews.unique { $0.fileId }
+ return results.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
@@ -234,7 +224,7 @@ extension NCActivityTableViewCell: UICollectionViewDataSource {
cell.imageView.image = image
}
} else {
- cell.imageView.image = UIImage(named: "file")
+ cell.imageView.image = UIImage(named: "file_photo")
}
}
@@ -250,13 +240,13 @@ extension NCActivityTableViewCell: UICollectionViewDataSource {
cell.imageView.image = image
}
} else {
- cell.imageView.image = UIImage(named: "file")
+ cell.imageView.image = UIImage(named: "file_photo")
}
}
} else {
- if let activitySubjectRich = NCManageDatabase.shared.getActivitySubjectRich(account: account, idActivity: idActivity, id: fileId) {
+ if let activitySubjectRich = NCManageDatabase.shared.getActivitySubjectRich(account: activityPreview.account, idActivity: idActivity, id: fileId) {
let fileNamePath = CCUtility.getDirectoryUserData() + "/" + activitySubjectRich.name
@@ -268,11 +258,7 @@ extension NCActivityTableViewCell: UICollectionViewDataSource {
} else {
- NCCommunication.shared.downloadPreview(fileNamePathOrFileId: activityPreview.source, fileNamePreviewLocalPath: fileNamePath, widthPreview: 0, heightPreview: 0, etag: nil, useInternalEndpoint: false) { _, imagePreview, _, _, _, errorCode, _ in
- if errorCode == 0 && imagePreview != nil {
- self.collectionView.reloadData()
- }
- }
+ NCOperationQueue.shared.downloadThumbnailActivity(fileNamePathOrFileId: activityPreview.source, fileNamePreviewLocalPath: fileNamePath, fileId: fileId, cell: cell, collectionView: collectionView)
}
}
}
diff --git a/iOSClient/AppDelegate.swift b/iOSClient/AppDelegate.swift
index ccaeb5659..344dbd835 100644
--- a/iOSClient/AppDelegate.swift
+++ b/iOSClient/AppDelegate.swift
@@ -40,28 +40,27 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
@objc var userId: String = ""
@objc var password: String = ""
+ var deletePasswordSession: Bool = false
var activeAppConfigView: NCAppConfigView?
- var activeFiles: NCFiles?
- var activeFileViewInFolder: NCFileViewInFolder?
var activeLogin: NCLogin?
var activeLoginWeb: NCLoginWeb?
- @objc var activeMedia: NCMedia?
var activeServerUrl: String = ""
@objc var activeViewController: UIViewController?
var mainTabBar: NCMainTabBar?
var activeMetadata: tableMetadata?
- var listFilesVC: [String: NCFiles] = [:]
- var listFavoriteVC: [String: NCFavorite] = [:]
- var listOfflineVC: [String: NCOffline] = [:]
- var listProgress: [String: NCGlobal.progressType] = [:]
+ let listFilesVC = ThreadSafeDictionary<String,NCFiles>()
+ let listFavoriteVC = ThreadSafeDictionary<String,NCFavorite>()
+ let listOfflineVC = ThreadSafeDictionary<String,NCOffline>()
var disableSharesView: Bool = false
var documentPickerViewController: NCDocumentPickerViewController?
var networkingProcessUpload: NCNetworkingProcessUpload?
var shares: [tableShare] = []
var timerErrorNetworking: Timer?
-
+
+ var errorITMS90076: Bool = false
+
private var privacyProtectionWindow: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
@@ -106,6 +105,19 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
}
}
+ // LOG Account
+ if let account = NCManageDatabase.shared.getActiveAccount() {
+ NCCommunicationCommon.shared.writeLog("Account active \(account.account)")
+ if CCUtility.getPassword(account.account).isEmpty {
+ NCCommunicationCommon.shared.writeLog("PASSWORD NOT FOUND for \(account.account)")
+ }
+ }
+
+ // ITMS-90076: Potential Loss of Keychain Access
+ if let account = NCManageDatabase.shared.getActiveAccount(), CCUtility.getPassword(account.account).isEmpty, NCUtility.shared.getVersionApp(withBuild: false).starts(with: "4.4") {
+ errorITMS90076 = true
+ }
+
// Activate user account
if let activeAccount = NCManageDatabase.shared.getActiveAccount() {
@@ -119,17 +131,24 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
settingAccount(activeAccount.account, urlBase: activeAccount.urlBase, user: activeAccount.user, userId: activeAccount.userId, password: CCUtility.getPassword(activeAccount.account))
+ NCBrandColor.shared.settingThemingColor(account: activeAccount.account)
+
} else {
CCUtility.deleteAllChainStore()
if let bundleID = Bundle.main.bundleIdentifier {
UserDefaults.standard.removePersistentDomain(forName: bundleID)
}
+
+ NCBrandColor.shared.createImagesThemingColor()
}
+ // Create user color
+ NCBrandColor.shared.createUserColors()
+
// initialize
NotificationCenter.default.addObserver(self, selector: #selector(initialize), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterInitialize), object: nil)
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterInitialize)
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterInitialize, userInfo:["atStart":1])
// Process upload
networkingProcessUpload = NCNetworkingProcessUpload()
@@ -189,6 +208,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
// L' applicazione entrerà in primo piano (attivo sempre)
func applicationDidBecomeActive(_ application: UIApplication) {
+ self.deletePasswordSession = false
+
if !NCAskAuthorization.shared.isRequesting {
// Privacy
hidePrivacyProtectionWindow()
@@ -237,7 +258,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterApplicationWillEnterForeground)
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterRichdocumentGrabFocus)
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSourceNetworkForced)
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSourceNetwork)
}
// L' applicazione si dimetterà dallo stato di attivo
@@ -295,17 +316,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
// MARK: -
@objc private func initialize() {
-
- if account == "" { return }
+ guard !account.isEmpty else { return }
NCCommunicationCommon.shared.writeLog("initialize Main")
// Registeration push notification
NCPushNotification.shared().pushNotification()
- // Setting Theming
- NCBrandColor.shared.settingThemingColor(account: account)
-
// Start Auto Upload
NCAutoUpload.shared.initAutoUpload(viewController: nil) { _ in }
@@ -363,7 +380,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
NCAutoUpload.shared.initAutoUpload(viewController: nil) { _ in
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUpdateBadgeNumber)
NCCommunicationCommon.shared.writeLog("Completition handler refresh task with [Auto upload]")
task.setTaskCompleted(success: true)
}
@@ -387,7 +403,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
NCService.shared.synchronizeOffline(account: account)
DispatchQueue.main.asyncAfter(deadline: .now() + 25) {
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUpdateBadgeNumber)
NCCommunicationCommon.shared.writeLog("Completition handler processing task [Synchronize Favorite & Offline]")
task.setTaskCompleted(success: true)
}
@@ -405,7 +420,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
NCCommunicationCommon.shared.writeLog("Start perform Fetch [Auto upload]")
NCAutoUpload.shared.initAutoUpload(viewController: nil) { items in
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUpdateBadgeNumber)
NCCommunicationCommon.shared.writeLog("Completition perform Fetch with \(items) uploads [Auto upload]")
if items == 0 {
completionHandler(UIBackgroundFetchResult.noData)
@@ -848,7 +862,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
- NCFunctionCenter.shared.openFileViewInFolder(serverUrl: serverUrl, fileName: fileName)
+ NCFunctionCenter.shared.openFileViewInFolder(serverUrl: serverUrl, fileNameBlink: fileName)
}
} else {
diff --git a/iOSClient/BackgroundImageColor/NCBackgroundImageColor.storyboard b/iOSClient/BackgroundImageColor/NCBackgroundImageColor.storyboard
deleted file mode 100644
index 850b3fb83..000000000
--- a/iOSClient/BackgroundImageColor/NCBackgroundImageColor.storyboard
+++ /dev/null
@@ -1,257 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="V0q-CP-xMJ">
- <device id="retina3_5" orientation="portrait" appearance="light"/>
- <dependencies>
- <deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
- <capability name="Safe area layout guides" minToolsVersion="9.0"/>
- <capability name="System colors in document resources" minToolsVersion="11.0"/>
- <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
- </dependencies>
- <scenes>
- <!--Background Image Color-->
- <scene sceneID="L90-uG-f4z">
- <objects>
- <viewController id="V0q-CP-xMJ" customClass="NCBackgroundImageColor" customModule="Nextcloud" customModuleProvider="target" sceneMemberID="viewController">
- <view key="view" contentMode="scaleToFill" id="gzh-6E-hc4">
- <rect key="frame" x="0.0" y="0.0" width="300" height="450"/>
- <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
- <subviews>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Background" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="nZr-nE-ths">
- <rect key="frame" x="20" y="15" width="260" height="18"/>
- <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="iU2-DL-ICv">
- <rect key="frame" x="0.0" y="53" width="300" height="250"/>
- <subviews>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="3E4-fA-LuC">
- <rect key="frame" x="260" y="0.0" width="30" height="30"/>
- <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- <constraints>
- <constraint firstAttribute="width" constant="30" id="7gh-HI-7F4"/>
- <constraint firstAttribute="height" constant="30" id="tN7-80-0OA"/>
- </constraints>
- <connections>
- <action selector="whiteButtonAction:" destination="V0q-CP-xMJ" eventType="touchUpInside" id="qan-1S-lXZ"/>
- </connections>
- </button>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="wje-qo-0av">
- <rect key="frame" x="260" y="50" width="30" height="30"/>
- <color key="backgroundColor" systemColor="systemOrangeColor"/>
- <constraints>
- <constraint firstAttribute="height" constant="30" id="eEj-s3-RlJ"/>
- <constraint firstAttribute="width" constant="30" id="wll-2m-eab"/>
- </constraints>
- <connections>
- <action selector="orangeButtonAction:" destination="V0q-CP-xMJ" eventType="touchUpInside" id="rze-5I-h4O"/>
- </connections>
- </button>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aan-mm-3h8">
- <rect key="frame" x="260" y="100" width="30" height="30"/>
- <color key="backgroundColor" systemColor="systemRedColor"/>
- <constraints>
- <constraint firstAttribute="width" constant="30" id="KEh-Br-hec"/>
- <constraint firstAttribute="height" constant="30" id="KF6-bC-uqI"/>
- </constraints>
- <connections>
- <action selector="redButtonAction:" destination="V0q-CP-xMJ" eventType="touchUpInside" id="DQh-Gp-afZ"/>
- </connections>
- </button>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ele-7I-DxL">
- <rect key="frame" x="260" y="150" width="30" height="30"/>
- <color key="backgroundColor" systemColor="systemGreenColor"/>
- <constraints>
- <constraint firstAttribute="height" constant="30" id="DgY-z7-3HB"/>
- <constraint firstAttribute="width" constant="30" id="NZK-QF-30V"/>
- </constraints>
- <state key="normal">
- <preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="default"/>
- </state>
- <connections>
- <action selector="greenButtonAction:" destination="V0q-CP-xMJ" eventType="touchUpInside" id="vz7-sI-OZN"/>
- </connections>
- </button>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="STo-4B-X2d">
- <rect key="frame" x="260" y="200" width="30" height="30"/>
- <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- <constraints>
- <constraint firstAttribute="width" constant="30" id="Qez-ew-4Ft"/>
- <constraint firstAttribute="height" constant="30" id="bNc-qJ-yHL"/>
- </constraints>
- <state key="normal">
- <preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="default"/>
- </state>
- <connections>
- <action selector="blackButtonAction:" destination="V0q-CP-xMJ" eventType="touchUpInside" id="FjW-KU-IXB"/>
- </connections>
- </button>
- </subviews>
- <constraints>
- <constraint firstItem="STo-4B-X2d" firstAttribute="top" secondItem="ele-7I-DxL" secondAttribute="bottom" constant="20" id="BKq-hv-vnm"/>
- <constraint firstAttribute="trailing" secondItem="ele-7I-DxL" secondAttribute="trailing" constant="10" id="FvE-ra-6MO"/>
- <constraint firstAttribute="trailing" secondItem="STo-4B-X2d" secondAttribute="trailing" constant="10" id="H9y-WI-TXI"/>
- <constraint firstAttribute="trailing" secondItem="3E4-fA-LuC" secondAttribute="trailing" constant="10" id="UoS-lh-xRi"/>
- <constraint firstAttribute="trailing" secondItem="aan-mm-3h8" secondAttribute="trailing" constant="10" id="VKC-iZ-oKg"/>
- <constraint firstItem="aan-mm-3h8" firstAttribute="top" secondItem="wje-qo-0av" secondAttribute="bottom" constant="20" id="Vtc-IV-iRF"/>
- <constraint firstItem="3E4-fA-LuC" firstAttribute="top" secondItem="iU2-DL-ICv" secondAttribute="top" id="XPi-Om-9AW"/>
- <constraint firstItem="ele-7I-DxL" firstAttribute="top" secondItem="aan-mm-3h8" secondAttribute="bottom" constant="20" id="ZFk-RV-bm7"/>
- <constraint firstAttribute="trailing" secondItem="wje-qo-0av" secondAttribute="trailing" constant="10" id="au5-4T-kJG"/>
- <constraint firstItem="wje-qo-0av" firstAttribute="top" secondItem="3E4-fA-LuC" secondAttribute="bottom" constant="20" id="p2S-Vf-mU1"/>
- <constraint firstAttribute="height" constant="250" id="v0B-oB-eD3"/>
- </constraints>
- </view>
- <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7CJ-Q0-ABH" userLabel="SeparatorV">
- <rect key="frame" x="150" y="400" width="0.5" height="50"/>
- <color key="backgroundColor" systemColor="systemGray4Color"/>
- <constraints>
- <constraint firstAttribute="width" constant="0.5" id="wU1-tA-NZk"/>
- </constraints>
- </view>
- <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ouH-gK-Guv" userLabel="SeparatorH">
- <rect key="frame" x="0.0" y="399.5" width="300" height="0.5"/>
- <color key="backgroundColor" systemColor="systemGray4Color"/>
- <constraints>
- <constraint firstAttribute="height" constant="0.5" id="2OQ-Mt-Gnh"/>
- </constraints>
- </view>
- <button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="249" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="W5y-aT-UlI">
- <rect key="frame" x="0.0" y="400" width="150" height="50"/>
- <constraints>
- <constraint firstAttribute="height" constant="50" id="xnX-6W-gp9"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="16"/>
- <state key="normal" title="Cancel">
- <color key="titleColor" systemColor="systemBlueColor"/>
- </state>
- <connections>
- <action selector="cancelAction:" destination="V0q-CP-xMJ" eventType="touchUpInside" id="z5n-6l-qtR"/>
- </connections>
- </button>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hcV-V0-eZB">
- <rect key="frame" x="150" y="400" width="150" height="50"/>
- <fontDescription key="fontDescription" type="system" pointSize="16"/>
- <state key="normal" title="Ok">
- <color key="titleColor" systemColor="systemBlueColor"/>
- </state>
- <connections>
- <action selector="okAction:" destination="V0q-CP-xMJ" eventType="touchUpInside" id="DO8-xB-WXf"/>
- </connections>
- </button>
- <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Dsj-Of-TI5">
- <rect key="frame" x="0.0" y="308" width="300" height="80"/>
- <subviews>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qCH-0e-MgJ">
- <rect key="frame" x="241" y="3.5" width="51" height="31"/>
- <connections>
- <action selector="darkmodeAction:" destination="V0q-CP-xMJ" eventType="valueChanged" id="jpD-6b-nRS"/>
- </connections>
- </switch>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="dark mode" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="AH4-ei-W3C">
- <rect key="frame" x="10" y="10" width="221" height="18"/>
- <fontDescription key="fontDescription" type="system" pointSize="15"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6Dy-77-TIC">
- <rect key="frame" x="10" y="48" width="280" height="30"/>
- <color key="backgroundColor" systemColor="systemGray4Color"/>
- <constraints>
- <constraint firstAttribute="height" constant="30" id="ZKT-Su-3nU"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="15"/>
- <state key="normal" title="default color">
- <color key="titleColor" systemColor="labelColor"/>
- </state>
- <connections>
- <action selector="defaultAction:" destination="V0q-CP-xMJ" eventType="touchUpInside" id="iTy-8K-wVB"/>
- </connections>
- </button>
- </subviews>
- <constraints>
- <constraint firstItem="6Dy-77-TIC" firstAttribute="top" secondItem="AH4-ei-W3C" secondAttribute="bottom" constant="20" id="0J5-Y3-Z2f"/>
- <constraint firstItem="qCH-0e-MgJ" firstAttribute="centerY" secondItem="AH4-ei-W3C" secondAttribute="centerY" id="7pt-EI-Zgu"/>
- <constraint firstItem="AH4-ei-W3C" firstAttribute="top" secondItem="Dsj-Of-TI5" secondAttribute="top" constant="10" id="9E5-Em-VG8"/>
- <constraint firstItem="qCH-0e-MgJ" firstAttribute="leading" secondItem="AH4-ei-W3C" secondAttribute="trailing" constant="10" id="9qm-mi-Gwb"/>
- <constraint firstItem="AH4-ei-W3C" firstAttribute="leading" secondItem="Dsj-Of-TI5" secondAttribute="leading" constant="10" id="Afp-ca-hx0"/>
- <constraint firstItem="6Dy-77-TIC" firstAttribute="leading" secondItem="Dsj-Of-TI5" secondAttribute="leading" constant="10" id="Bn8-Bi-qOg"/>
- <constraint firstAttribute="trailing" secondItem="qCH-0e-MgJ" secondAttribute="trailing" constant="10" id="QVc-0U-Mg8"/>
- <constraint firstAttribute="trailing" secondItem="6Dy-77-TIC" secondAttribute="trailing" constant="10" id="jId-wH-r5I"/>
- <constraint firstAttribute="height" constant="80" id="uSG-oG-ooi"/>
- </constraints>
- </view>
- </subviews>
- <viewLayoutGuide key="safeArea" id="1c1-7Q-WMG"/>
- <color key="backgroundColor" systemColor="systemGray6Color"/>
- <constraints>
- <constraint firstItem="hcV-V0-eZB" firstAttribute="top" secondItem="ouH-gK-Guv" secondAttribute="bottom" id="1MZ-1P-Ej1"/>
- <constraint firstItem="1c1-7Q-WMG" firstAttribute="bottom" secondItem="hcV-V0-eZB" secondAttribute="bottom" id="2Wh-Y6-n8F"/>
- <constraint firstItem="1c1-7Q-WMG" firstAttribute="trailing" secondItem="iU2-DL-ICv" secondAttribute="trailing" id="3Mn-1r-AGf"/>
- <constraint firstItem="Dsj-Of-TI5" firstAttribute="top" secondItem="iU2-DL-ICv" secondAttribute="bottom" constant="5" id="7kJ-dL-S5M"/>
- <constraint firstItem="1c1-7Q-WMG" firstAttribute="bottom" secondItem="7CJ-Q0-ABH" secondAttribute="bottom" id="8HO-F9-tfD"/>
- <constraint firstItem="ouH-gK-Guv" firstAttribute="leading" secondItem="1c1-7Q-WMG" secondAttribute="leading" id="A6T-ed-97T"/>
- <constraint firstItem="hcV-V0-eZB" firstAttribute="leading" secondItem="W5y-aT-UlI" secondAttribute="trailing" id="Aa4-Pg-Ioh"/>
- <constraint firstItem="1c1-7Q-WMG" firstAttribute="trailing" secondItem="nZr-nE-ths" secondAttribute="trailing" constant="20" id="DPW-MV-oKc"/>
- <constraint firstItem="7CJ-Q0-ABH" firstAttribute="centerX" secondItem="1c1-7Q-WMG" secondAttribute="centerX" id="EVx-ob-2bn"/>
- <constraint firstItem="nZr-nE-ths" firstAttribute="leading" secondItem="1c1-7Q-WMG" secondAttribute="leading" constant="20" id="SI9-xL-6s8"/>
- <constraint firstItem="iU2-DL-ICv" firstAttribute="top" secondItem="nZr-nE-ths" secondAttribute="bottom" constant="20" id="ZrF-wP-mwm"/>
- <constraint firstItem="iU2-DL-ICv" firstAttribute="leading" secondItem="1c1-7Q-WMG" secondAttribute="leading" id="aNT-a0-r8t"/>
- <constraint firstItem="1c1-7Q-WMG" firstAttribute="bottom" secondItem="W5y-aT-UlI" secondAttribute="bottom" id="ai8-AR-XYe"/>
- <constraint firstItem="7CJ-Q0-ABH" firstAttribute="top" secondItem="ouH-gK-Guv" secondAttribute="bottom" id="an1-EN-YiB"/>
- <constraint firstItem="1c1-7Q-WMG" firstAttribute="trailing" secondItem="W5y-aT-UlI" secondAttribute="trailing" multiplier="2" id="g0h-1g-A3R"/>
- <constraint firstItem="Dsj-Of-TI5" firstAttribute="leading" secondItem="1c1-7Q-WMG" secondAttribute="leading" id="gYm-lv-oVe"/>
- <constraint firstItem="1c1-7Q-WMG" firstAttribute="trailing" secondItem="hcV-V0-eZB" secondAttribute="trailing" id="heW-2p-hLJ"/>
- <constraint firstItem="W5y-aT-UlI" firstAttribute="leading" secondItem="1c1-7Q-WMG" secondAttribute="leading" id="kw6-l5-CAR"/>
- <constraint firstItem="nZr-nE-ths" firstAttribute="top" secondItem="1c1-7Q-WMG" secondAttribute="top" constant="15" id="oyJ-sj-j5N"/>
- <constraint firstItem="1c1-7Q-WMG" firstAttribute="trailing" secondItem="ouH-gK-Guv" secondAttribute="trailing" id="r1N-R6-iZg"/>
- <constraint firstItem="1c1-7Q-WMG" firstAttribute="trailing" secondItem="Dsj-Of-TI5" secondAttribute="trailing" id="tA5-3w-2U2"/>
- <constraint firstItem="W5y-aT-UlI" firstAttribute="top" secondItem="ouH-gK-Guv" secondAttribute="bottom" id="ywb-oW-pJe"/>
- </constraints>
- </view>
- <navigationItem key="navigationItem" id="Zon-2j-rsc"/>
- <size key="freeformSize" width="300" height="450"/>
- <connections>
- <outlet property="blackButton" destination="STo-4B-X2d" id="XwW-Q1-u9Y"/>
- <outlet property="cancelButton" destination="W5y-aT-UlI" id="P9l-o1-miU"/>
- <outlet property="chromaColorPickerView" destination="iU2-DL-ICv" id="iX8-Pq-EFB"/>
- <outlet property="darkmodeLabel" destination="AH4-ei-W3C" id="JvO-LN-BUu"/>
- <outlet property="darkmodeSwitch" destination="qCH-0e-MgJ" id="rjG-X5-eqA"/>
- <outlet property="defaultButton" destination="6Dy-77-TIC" id="PxM-tG-Ve7"/>
- <outlet property="greenButton" destination="ele-7I-DxL" id="vYB-cv-c6D"/>
- <outlet property="okButton" destination="hcV-V0-eZB" id="1VQ-qp-4Fs"/>
- <outlet property="orangeButton" destination="wje-qo-0av" id="LN8-3w-Wtx"/>
- <outlet property="redButton" destination="aan-mm-3h8" id="X89-dx-fGV"/>
- <outlet property="titleLabel" destination="nZr-nE-ths" id="UbA-Dl-0Ad"/>
- <outlet property="whiteButton" destination="3E4-fA-LuC" id="mNg-2f-rvs"/>
- </connections>
- </viewController>
- <placeholder placeholderIdentifier="IBFirstResponder" id="qdm-Cl-C5l" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
- </objects>
- <point key="canvasLocation" x="1453.125" y="133.75"/>
- </scene>
- </scenes>
- <resources>
- <systemColor name="labelColor">
- <color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- </systemColor>
- <systemColor name="systemBlueColor">
- <color red="0.0" green="0.47843137254901963" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
- </systemColor>
- <systemColor name="systemGray4Color">
- <color red="0.81960784313725488" green="0.81960784313725488" blue="0.83921568627450982" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
- </systemColor>
- <systemColor name="systemGray6Color">
- <color red="0.94901960784313721" green="0.94901960784313721" blue="0.96862745098039216" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
- </systemColor>
- <systemColor name="systemGreenColor">
- <color red="0.20392156862745098" green="0.7803921568627451" blue="0.34901960784313724" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
- </systemColor>
- <systemColor name="systemOrangeColor">
- <color red="1" green="0.58431372549019611" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
- </systemColor>
- <systemColor name="systemRedColor">
- <color red="1" green="0.23137254901960785" blue="0.18823529411764706" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
- </systemColor>
- </resources>
-</document>
diff --git a/iOSClient/BackgroundImageColor/NCBackgroundImageColor.swift b/iOSClient/BackgroundImageColor/NCBackgroundImageColor.swift
deleted file mode 100644
index e41e5a218..000000000
--- a/iOSClient/BackgroundImageColor/NCBackgroundImageColor.swift
+++ /dev/null
@@ -1,298 +0,0 @@
-//
-// NCBackgroundImageColor.swift
-// Nextcloud
-//
-// Created by Marino Faggiana on 05/05/21.
-// Copyright © 2021 Marino Faggiana. All rights reserved.
-//
-// Author Marino Faggiana <marino.faggiana@nextcloud.com>
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-import UIKit
-import ChromaColorPicker
-
-public protocol NCBackgroundImageColorDelegate: AnyObject {
- func colorPickerCancel()
- func colorPickerWillChange(color: UIColor)
- func colorPickerDidChange(lightColor: String, darkColor: String)
-}
-
-// optional func
-public extension NCBackgroundImageColorDelegate {
- func colorPickerCancel() {}
- func colorPickerWillChange(color: UIColor) { }
- func colorPickerDidChange(lightColor: String, darkColor: String) { }
-}
-
-class NCBackgroundImageColor: UIViewController {
-
- @IBOutlet weak var titleLabel: UILabel!
- @IBOutlet weak var chromaColorPickerView: UIView!
-
- @IBOutlet weak var whiteButton: UIButton!
- @IBOutlet weak var orangeButton: UIButton!
- @IBOutlet weak var redButton: UIButton!
- @IBOutlet weak var greenButton: UIButton!
- @IBOutlet weak var blackButton: UIButton!
-
- @IBOutlet weak var darkmodeLabel: UILabel!
- @IBOutlet weak var darkmodeSwitch: UISwitch!
-
- @IBOutlet weak var defaultButton: UIButton!
- @IBOutlet weak var cancelButton: UIButton!
- @IBOutlet weak var okButton: UIButton!
-
- private let colorPicker = ChromaColorPicker()
- private let brightnessSlider = ChromaBrightnessSlider()
- private var colorHandle: ChromaColorHandle?
- private let defaultColorPickerSize = CGSize(width: 200, height: 200)
- private let brightnessSliderWidthHeightRatio: CGFloat = 0.1
-
- weak var delegate: NCBackgroundImageColorDelegate?
- var setupColor: UIColor?
- var darkColor = "#000000"
- var lightColor = "#FFFFFF"
-
- let width: CGFloat = 300
- let height: CGFloat = 450
-
- // MARK: - View Life Cycle
-
- override func viewDidLoad() {
- super.viewDidLoad()
-
- setupColorPicker()
- setupBrightnessSlider()
- setupColorPickerHandles()
-
- titleLabel.text = NSLocalizedString("_background_", comment: "")
- darkmodeLabel.text = NSLocalizedString("_dark_mode_", comment: "")
-
- defaultButton.setTitle(NSLocalizedString("_default_color_", comment: ""), for: .normal)
-
- cancelButton.setTitle(NSLocalizedString("_cancel_", comment: ""), for: .normal)
- okButton.setTitle(NSLocalizedString("_ok_", comment: ""), for: .normal)
-
- whiteButton.backgroundColor = .white
- whiteButton.layer.cornerRadius = 5
- whiteButton.layer.borderWidth = 0.5
- whiteButton.layer.borderColor = NCBrandColor.shared.label.cgColor
- whiteButton.layer.masksToBounds = true
-
- orangeButton.backgroundColor = .orange
- orangeButton.layer.cornerRadius = 5
- orangeButton.layer.borderWidth = 0.5
- orangeButton.layer.borderColor = NCBrandColor.shared.label.cgColor
- orangeButton.layer.masksToBounds = true
-
- redButton.backgroundColor = .red
- redButton.layer.cornerRadius = 5
- redButton.layer.borderWidth = 0.5
- redButton.layer.borderColor = NCBrandColor.shared.label.cgColor
- redButton.layer.masksToBounds = true
-
- greenButton.backgroundColor = .green
- greenButton.layer.cornerRadius = 5
- greenButton.layer.borderWidth = 0.5
- greenButton.layer.borderColor = NCBrandColor.shared.label.cgColor
- greenButton.layer.masksToBounds = true
-
- blackButton.backgroundColor = .black
- blackButton.layer.cornerRadius = 5
- blackButton.layer.borderWidth = 0.5
- blackButton.layer.borderColor = NCBrandColor.shared.label.cgColor
- blackButton.layer.masksToBounds = true
-
- defaultButton.layer.cornerRadius = 15
- defaultButton.layer.borderWidth = 0.5
- defaultButton.layer.borderColor = UIColor.gray.cgColor
- defaultButton.layer.masksToBounds = true
- }
-
- override func viewWillAppear(_ animated: Bool) {
- super.viewWillAppear(animated)
-
- if traitCollection.userInterfaceStyle == .dark {
- darkmodeSwitch.isOn = true
- } else {
- darkmodeSwitch.isOn = false
- }
-
- // Color for all folders
- if let activeAccount = NCManageDatabase.shared.getActiveAccount() {
- if darkColor == "" {
- darkColor = activeAccount.darkColorBackground
- }
- if lightColor == "" {
- lightColor = activeAccount.lightColorBackground
- }
- }
-
- // set color
- if darkmodeSwitch.isOn {
- if let color = UIColor(hex: darkColor) {
- changeColor(color)
- } else {
- changeColor(.black)
- }
- } else {
- if let color = UIColor(hex: lightColor) {
- changeColor(color)
- } else {
- changeColor(.white)
- }
- }
- }
-
- // MARK: - Action
-
- @IBAction func whiteButtonAction(_ sender: UIButton) {
- changeColor(.white)
- }
-
- @IBAction func orangeButtonAction(_ sender: UIButton) {
- changeColor(.orange)
- }
-
- @IBAction func redButtonAction(_ sender: UIButton) {
- changeColor(.red)
- }
-
- @IBAction func greenButtonAction(_ sender: UIButton) {
- changeColor(.green)
- }
-
- @IBAction func blackButtonAction(_ sender: UIButton) {
- changeColor(.black)
- }
-
- @IBAction func darkmodeAction(_ sender: UISwitch) {
-
- if sender.isOn {
- if darkColor == "" {
- changeColor(.black)
- } else {
- if let color = UIColor(hex: darkColor) {
- changeColor(color)
- }
- }
- } else {
- if lightColor == "" {
- changeColor(.white)
- } else {
- if let color = UIColor(hex: lightColor) {
- changeColor(color)
- }
- }
- }
- }
-
- @IBAction func defaultAction(_ sender: Any) {
-
- if darkmodeSwitch.isOn {
- darkColor = "#000000"
- changeColor(.black)
- } else {
- lightColor = "#FFFFFF"
- changeColor(.white)
- }
- }
-
- @IBAction func cancelAction(_ sender: Any) {
-
- self.delegate?.colorPickerCancel()
- dismiss(animated: true)
- }
-
- @IBAction func okAction(_ sender: Any) {
-
- var lightColor = self.lightColor
- var darkColor = self.darkColor
-
- if lightColor == "#FFFFFF" { lightColor = "" }
- if darkColor == "#000000" { darkColor = "" }
-
- self.delegate?.colorPickerDidChange(lightColor: lightColor, darkColor: darkColor)
-
- dismiss(animated: true)
- }
-
- // MARK: - ChromaColorPicker
-
- private func setupColorPicker() {
- colorPicker.delegate = self
- colorPicker.translatesAutoresizingMaskIntoConstraints = false
- view.addSubview(colorPicker)
-
- NSLayoutConstraint.activate([
- colorPicker.leadingAnchor.constraint(equalTo: chromaColorPickerView.leadingAnchor, constant: 20),
- colorPicker.topAnchor.constraint(equalTo: chromaColorPickerView.topAnchor),
- colorPicker.widthAnchor.constraint(equalToConstant: defaultColorPickerSize.width),
- colorPicker.heightAnchor.constraint(equalToConstant: defaultColorPickerSize.height)
- ])
- }
-
- private func setupBrightnessSlider() {
- brightnessSlider.connect(to: colorPicker)
-
- // Style
- brightnessSlider.trackColor = UIColor.blue
- brightnessSlider.handle.borderWidth = 3.0 // Example of customizing the handle's properties.
-
- // Layout
- brightnessSlider.translatesAutoresizingMaskIntoConstraints = false
- view.addSubview(brightnessSlider)
-
- NSLayoutConstraint.activate([
- brightnessSlider.centerXAnchor.constraint(equalTo: colorPicker.centerXAnchor),
- brightnessSlider.topAnchor.constraint(equalTo: colorPicker.bottomAnchor, constant: 20),
- brightnessSlider.widthAnchor.constraint(equalTo: colorPicker.widthAnchor, multiplier: 1),
- brightnessSlider.heightAnchor.constraint(equalTo: brightnessSlider.widthAnchor, multiplier: brightnessSliderWidthHeightRatio)
- ])
- }
-
- private func setupColorPickerHandles() {
- colorHandle = colorPicker.addHandle(at: setupColor)
- }
-
- private func changeColor(_ color: UIColor) {
-
- colorHandle?.color = color
- colorPicker.setNeedsLayout()
- brightnessSlider.trackColor = color
-
- if darkmodeSwitch.isOn {
- darkColor = color.hexString
- } else {
- lightColor = color.hexString
- }
-
- self.delegate?.colorPickerWillChange(color: color)
- }
-}
-
-extension NCBackgroundImageColor: ChromaColorPickerDelegate {
- func colorPickerHandleDidChange(_ colorPicker: ChromaColorPicker, handle: ChromaColorHandle, to color: UIColor) {
-
- if darkmodeSwitch.isOn {
- darkColor = color.hexString
- } else {
- lightColor = color.hexString
- }
-
- self.delegate?.colorPickerWillChange(color: color)
- }
-}
diff --git a/iOSClient/Brand/NCBrand.swift b/iOSClient/Brand/NCBrand.swift
index b8148e5af..eb44e85f6 100755
--- a/iOSClient/Brand/NCBrand.swift
+++ b/iOSClient/Brand/NCBrand.swift
@@ -90,9 +90,6 @@ import UIKit
@objc public var disable_request_account: Bool = false
@objc public var disable_log: Bool = false
- @objc public var disable_background_color: Bool = true
- @objc public var disable_background_image: Bool = true
-
override init() {
if folderBrandAutoUpload != "" {
@@ -106,8 +103,6 @@ import UIKit
class NCBrandColor: NSObject {
@objc static let shared: NCBrandColor = {
let instance = NCBrandColor()
- instance.createImagesThemingColor()
- instance.createUserColors()
return instance
}()
@@ -139,6 +134,15 @@ class NCBrandColor: NSObject {
static var buttonStop = UIImage()
static var buttonMoreLock = UIImage()
static var buttonRestore = UIImage()
+ static var buttonTrash = UIImage()
+
+ static var iconContacts = UIImage()
+ static var iconTalk = UIImage()
+ static var iconCalendar = UIImage()
+ static var iconDeck = UIImage()
+ static var iconMail = UIImage()
+ static var iconConfirm = UIImage()
+ static var iconPages = UIImage()
}
// Color
@@ -155,6 +159,61 @@ class NCBrandColor: NSObject {
@objc public let yellowFavorite: UIColor = UIColor(red: 248.0/255.0, green: 205.0/255.0, blue: 70.0/255.0, alpha: 1.0)
public var userColors: [CGColor] = []
+ public var themingColor: String = ""
+ public var themingColorElement: String = ""
+ public var themingColorText: String = ""
+
+ @objc public var annotationColor: UIColor {
+ get {
+ return .systemBlue
+ }
+ }
+
+ @objc public var systemBlue: UIColor {
+ get {
+ if #available(iOS 13, *) {
+ return .systemBlue
+ } else {
+ return UIColor(red: 0.0, green: 122.0 / 255.0, blue: 1.0, alpha: 1.0)
+ }
+ }
+ }
+
+ @objc public var systemIndigo: UIColor {
+ get {
+ if #available(iOS 13, *) {
+ return .systemIndigo
+ } else {
+ return UIColor(red: 88.0 / 255.0, green: 86.0 / 255.0, blue: 214.0 / 255.0, alpha: 1.0)
+ }
+ }
+ }
+
+ @objc public var systemPink: UIColor {
+ get {
+ if #available(iOS 13, *) {
+ return .systemPink
+ } else {
+ return UIColor(red: 1.0, green: 45.0 / 255.0, blue: 85.0 / 255.0, alpha: 1.0)
+ }
+ }
+ }
+
+ @objc public var systemTeal: UIColor {
+ get {
+ if #available(iOS 13, *) {
+ return .systemTeal
+ } else {
+ return UIColor(red: 90.0 / 255.0, green: 200.0 / 255.0, blue: 250.0 / 255.0, alpha: 1.0)
+ }
+ }
+ }
+
+ @objc public var systemMint: UIColor {
+ get {
+ return UIColor(red: 0.0 / 255.0, green: 199.0 / 255.0, blue: 190.0 / 255.0, alpha: 1.0)
+ }
+ }
@objc public var systemBackground: UIColor {
get {
@@ -256,6 +315,16 @@ class NCBrandColor: NSObject {
}
}
+ @objc public var systemGray1: UIColor {
+ get {
+ if #available(iOS 13, *) {
+ return UIColor(red: 0.60, green: 0.60, blue: 0.60, alpha: 1.0)
+ } else {
+ return UIColor(red: 0.60, green: 0.60, blue: 0.60, alpha: 1.0)
+ }
+ }
+ }
+
@objc public var systemGray2: UIColor {
get {
if #available(iOS 13, *) {
@@ -317,16 +386,16 @@ class NCBrandColor: NSObject {
}
override init() {
- self.brand = self.customer
- self.brandElement = self.customer
- self.brandText = self.customerText
+ brand = customer
+ brandElement = customer
+ brandText = customerText
}
- private func createUserColors() {
- self.userColors = generateColors()
+ func createUserColors() {
+ userColors = generateColors()
}
- public func createImagesThemingColor() {
+ func createImagesThemingColor() {
let gray: UIColor = UIColor(red: 162.0/255.0, green: 162.0/255.0, blue: 162.0/255.0, alpha: 0.5)
@@ -358,93 +427,98 @@ class NCBrandColor: NSObject {
cacheImages.buttonStop = UIImage(named: "stop")!.image(color: gray, size: 50)
cacheImages.buttonMoreLock = UIImage(named: "moreLock")!.image(color: gray, size: 50)
cacheImages.buttonRestore = UIImage(named: "restore")!.image(color: gray, size: 50)
+ cacheImages.buttonTrash = UIImage(named: "trash")!.image(color: gray, size: 50)
+
+ cacheImages.iconContacts = UIImage(named: "icon-contacts")!.image(color: brandElement, size: folderWidth)
+ cacheImages.iconTalk = UIImage(named: "icon-talk")!.image(color: brandElement, size: folderWidth)
+ cacheImages.iconCalendar = UIImage(named: "icon-calendar")!.image(color: brandElement, size: folderWidth)
+ cacheImages.iconDeck = UIImage(named: "icon-deck")!.image(color: brandElement, size: folderWidth)
+ cacheImages.iconMail = UIImage(named: "icon-mail")!.image(color: brandElement, size: folderWidth)
+ cacheImages.iconConfirm = UIImage(named: "icon-confirm")!.image(color: brandElement, size: folderWidth)
+ cacheImages.iconPages = UIImage(named: "icon-pages")!.image(color: brandElement, size: folderWidth)
}
- #if !EXTENSION
- public func settingThemingColor(account: String) {
+ func settingThemingColor(account: String) {
let darker: CGFloat = 30 // %
let lighter: CGFloat = 30 // %
if NCBrandOptions.shared.use_themingColor {
- let themingColor = NCManageDatabase.shared.getCapabilitiesServerString(account: account, elements: NCElementsJSON.shared.capabilitiesThemingColor)
-
- let themingColorElement = NCManageDatabase.shared.getCapabilitiesServerString(account: account, elements: NCElementsJSON.shared.capabilitiesThemingColorElement)
-
- let themingColorText = NCManageDatabase.shared.getCapabilitiesServerString(account: account, elements: NCElementsJSON.shared.capabilitiesThemingColorText)
-
- settingBrandColor(themingColor, themingColorElement: themingColorElement, themingColorText: themingColorText)
+ if let themingColor = NCManageDatabase.shared.getCapabilitiesServerString(account: account, elements: NCElementsJSON.shared.capabilitiesThemingColor),
+ let themingColorElement = NCManageDatabase.shared.getCapabilitiesServerString(account: account, elements: NCElementsJSON.shared.capabilitiesThemingColorElement),
+ let themingColorText = NCManageDatabase.shared.getCapabilitiesServerString(account: account, elements: NCElementsJSON.shared.capabilitiesThemingColorText) {
+
+ self.themingColor = themingColor
+ self.themingColorElement = themingColorElement
+ self.themingColorText = themingColorText
+
+ // COLOR
+ if themingColor.first == "#" {
+ if let color = UIColor(hex: themingColor) {
+ brand = color
+ } else {
+ brand = customer
+ }
+ } else {
+ brand = customer
+ }
- if NCBrandColor.shared.brandElement.isTooLight() {
- if let color = NCBrandColor.shared.brandElement.darker(by: darker) {
- NCBrandColor.shared.brandElement = color
+ // COLOR TEXT
+ if themingColorText.first == "#" {
+ if let color = UIColor(hex: themingColorText) {
+ brandText = color
+ } else {
+ brandText = customerText
+ }
+ } else {
+ brandText = customerText
}
- } else if NCBrandColor.shared.brandElement.isTooDark() {
- if let color = NCBrandColor.shared.brandElement.lighter(by: lighter) {
- NCBrandColor.shared.brandElement = color
+
+ // COLOR ELEMENT
+ if themingColorElement.first == "#" {
+ if let color = UIColor(hex: themingColorElement) {
+ brandElement = color
+ } else {
+ brandElement = brand
+ }
+ } else {
+ brandElement = brand
}
}
- } else {
-
- if NCBrandColor.shared.customer.isTooLight() {
- if let color = NCBrandColor.shared.customer.darker(by: darker) {
- NCBrandColor.shared.brandElement = color
+ if brandElement.isTooLight() {
+ if let color = brandElement.darker(by: darker) {
+ brandElement = color
}
- } else if NCBrandColor.shared.customer.isTooDark() {
- if let color = NCBrandColor.shared.customer.lighter(by: lighter) {
- NCBrandColor.shared.brandElement = color
+ } else if brandElement.isTooDark() {
+ if let color = brandElement.lighter(by: lighter) {
+ brandElement = color
}
- } else {
- NCBrandColor.shared.brandElement = NCBrandColor.shared.customer
}
- NCBrandColor.shared.brand = NCBrandColor.shared.customer
- NCBrandColor.shared.brandText = NCBrandColor.shared.customerText
- }
-
- DispatchQueue.main.async {
- self.createImagesThemingColor()
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterChangeTheming)
- }
- }
- #endif
-
- @objc func settingBrandColor(_ themingColor: String?, themingColorElement: String?, themingColorText: String?) {
-
- // COLOR
- if themingColor?.first == "#" {
- if let color = UIColor(hex: themingColor!) {
- NCBrandColor.shared.brand = color
- } else {
- NCBrandColor.shared.brand = NCBrandColor.shared.customer
- }
} else {
- NCBrandColor.shared.brand = NCBrandColor.shared.customer
- }
- // COLOR TEXT
- if themingColorText?.first == "#" {
- if let color = UIColor(hex: themingColorText!) {
- NCBrandColor.shared.brandText = color
+ if self.customer.isTooLight() {
+ if let color = customer.darker(by: darker) {
+ brandElement = color
+ }
+ } else if customer.isTooDark() {
+ if let color = customer.lighter(by: lighter) {
+ brandElement = color
+ }
} else {
- NCBrandColor.shared.brandText = NCBrandColor.shared.customerText
+ brandElement = customer
}
- } else {
- NCBrandColor.shared.brandText = NCBrandColor.shared.customerText
- }
- // COLOR ELEMENT
- if themingColorElement?.first == "#" {
- if let color = UIColor(hex: themingColorElement!) {
- NCBrandColor.shared.brandElement = color
- } else {
- NCBrandColor.shared.brandElement = NCBrandColor.shared.brand
- }
- } else {
- NCBrandColor.shared.brandElement = NCBrandColor.shared.brand
+ brand = customer
+ brandText = customerText
}
+
+ createImagesThemingColor()
+ #if !EXTENSION
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterChangeTheming)
+ #endif
}
private func stepCalc(steps: Int, color1: CGColor, color2: CGColor) -> [CGFloat] {
diff --git a/iOSClient/Nextcloud-Bridging-Header.h b/iOSClient/Brand/Nextcloud-Bridging-Header.h
index b758fed19..b758fed19 100644
--- a/iOSClient/Nextcloud-Bridging-Header.h
+++ b/iOSClient/Brand/Nextcloud-Bridging-Header.h
diff --git a/iOSClient/Brand/iOSClient.plist b/iOSClient/Brand/iOSClient.plist
index 9f096d6cb..a1a376ecf 100755
--- a/iOSClient/Brand/iOSClient.plist
+++ b/iOSClient/Brand/iOSClient.plist
@@ -45,7 +45,7 @@
<key>ITSAppUsesNonExemptEncryption</key>
<true/>
<key>ITSEncryptionExportComplianceCode</key>
- <string>3b2bb0b1-fa12-43cb-a78f-0f7e1afd33df</string>
+ <string>8e9f9874-938e-460b-a9be-f82cb3393971</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>nextcloudtalk</string>
@@ -75,6 +75,8 @@
<string>Photo library access is required to upload your photos and videos to your cloud.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Photo library access is required to upload your photos and videos to your cloud.</string>
+ <key>PHPhotoLibraryPreventAutomaticLimitedAccessAlert</key>
+ <true/>
<key>UIAppFonts</key>
<array>
<string>Inconsolata-Light.ttf</string>
@@ -85,8 +87,6 @@
<string>Inconsolata-ExtraBold.ttf</string>
<string>Inconsolata-Black.ttf</string>
</array>
- <key>PHPhotoLibraryPreventAutomaticLimitedAccessAlert</key>
- <true/>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
diff --git a/iOSClient/Color/NCColorPicker.storyboard b/iOSClient/Color/NCColorPicker.storyboard
new file mode 100644
index 000000000..28d2ca8a6
--- /dev/null
+++ b/iOSClient/Color/NCColorPicker.storyboard
@@ -0,0 +1,293 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Y6W-OH-hqX">
+ <device id="retina4_0" orientation="portrait" appearance="light"/>
+ <dependencies>
+ <deployment identifier="iOS"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
+ <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+ <capability name="System colors in document resources" minToolsVersion="11.0"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <scenes>
+ <!--Color Picker-->
+ <scene sceneID="s0d-6b-0kx">
+ <objects>
+ <viewController id="Y6W-OH-hqX" customClass="NCColorPicker" customModule="Nextcloud" customModuleProvider="target" sceneMemberID="viewController">
+ <view key="view" contentMode="scaleToFill" id="5EZ-qb-Rvc">
+ <rect key="frame" x="0.0" y="0.0" width="200" height="320"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kwJ-4R-6nM">
+ <rect key="frame" x="10" y="10" width="15" height="15"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="15" id="AE2-yu-3y4"/>
+ <constraint firstAttribute="width" constant="15" id="Foq-O9-Wep"/>
+ </constraints>
+ <state key="normal" image="xmark"/>
+ <connections>
+ <action selector="closeAction:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="nq5-sT-FEb"/>
+ </connections>
+ </button>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8DH-gC-coa">
+ <rect key="frame" x="0.0" y="8.5" width="200" height="18"/>
+ <fontDescription key="fontDescription" type="system" pointSize="15"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="JUR-Vj-yBU">
+ <rect key="frame" x="15" y="45" width="40" height="40"/>
+ <color key="backgroundColor" systemColor="labelColor"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="40" id="LDf-aO-ruY"/>
+ <constraint firstAttribute="height" constant="40" id="U5p-9E-WGx"/>
+ </constraints>
+ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <connections>
+ <action selector="orangeButtonAction:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="qjx-Me-0xU"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Zr2-rF-YUt">
+ <rect key="frame" x="15" y="100" width="40" height="40"/>
+ <color key="backgroundColor" systemColor="labelColor"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="40" id="krX-Ql-hLX"/>
+ <constraint firstAttribute="width" constant="40" id="pBq-i1-K9T"/>
+ </constraints>
+ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <connections>
+ <action selector="redButtonAction:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="b2r-oG-GvU"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dOn-SY-wnl">
+ <rect key="frame" x="15" y="155" width="40" height="40"/>
+ <color key="backgroundColor" systemColor="labelColor"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="40" id="BI1-aU-56D"/>
+ <constraint firstAttribute="width" constant="40" id="v3I-Na-zQ5"/>
+ </constraints>
+ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <connections>
+ <action selector="purpleButtonAction:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="Ep7-vV-zH8"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="C2a-jB-FVB">
+ <rect key="frame" x="15" y="210" width="40" height="40"/>
+ <color key="backgroundColor" systemColor="labelColor"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="40" id="Sfk-IP-7JV"/>
+ <constraint firstAttribute="width" constant="40" id="n8f-nK-weh"/>
+ </constraints>
+ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <connections>
+ <action selector="blueButtonAction:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="M04-54-NPB"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8xv-8Y-A50">
+ <rect key="frame" x="15" y="265" width="40" height="40"/>
+ <color key="backgroundColor" systemColor="labelColor"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="40" id="Jgq-IJ-7jj"/>
+ <constraint firstAttribute="width" constant="40" id="h5m-EQ-2Go"/>
+ </constraints>
+ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <connections>
+ <action selector="greenButtonAction:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="VVw-Ra-U8N"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="OlH-Ak-sRA">
+ <rect key="frame" x="80" y="45" width="40" height="40"/>
+ <color key="backgroundColor" systemColor="labelColor"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="40" id="3kj-5z-0de"/>
+ <constraint firstAttribute="width" constant="40" id="vjr-4J-pHk"/>
+ </constraints>
+ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <connections>
+ <action selector="cyanButtonAction:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="Qxa-md-cPa"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FU6-q8-9Iw">
+ <rect key="frame" x="80" y="100" width="40" height="40"/>
+ <color key="backgroundColor" systemColor="labelColor"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="40" id="NGk-p2-vQ4"/>
+ <constraint firstAttribute="height" constant="40" id="Rni-gX-9zj"/>
+ </constraints>
+ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <connections>
+ <action selector="yellowButtonAction:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="DuE-By-m9k"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LwF-26-oss">
+ <rect key="frame" x="80" y="155" width="40" height="40"/>
+ <color key="backgroundColor" systemColor="labelColor"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="40" id="Pqo-uv-KrN"/>
+ <constraint firstAttribute="width" constant="40" id="y5l-31-c4D"/>
+ </constraints>
+ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <connections>
+ <action selector="grayButtonAction:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="wP2-wX-3Hl"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="I9w-cx-QlY">
+ <rect key="frame" x="80" y="210" width="40" height="40"/>
+ <color key="backgroundColor" systemColor="labelColor"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="40" id="Vgv-il-6Vw"/>
+ <constraint firstAttribute="width" constant="40" id="dHD-fs-7m0"/>
+ </constraints>
+ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <connections>
+ <action selector="brownButtonAction:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="AH7-Kr-g9S"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="12u-cu-XGu">
+ <rect key="frame" x="80" y="265" width="40" height="40"/>
+ <color key="backgroundColor" systemColor="labelColor"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="40" id="8vW-vR-kNP"/>
+ <constraint firstAttribute="height" constant="40" id="F3v-dP-jmB"/>
+ </constraints>
+ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <connections>
+ <action selector="systemBlueButtonAction:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="V6v-x6-0xf"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tt7-sI-TfL">
+ <rect key="frame" x="145" y="45" width="40" height="40"/>
+ <color key="backgroundColor" systemColor="labelColor"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="40" id="b6h-GE-ftL"/>
+ <constraint firstAttribute="height" constant="40" id="mfL-IL-0ZL"/>
+ </constraints>
+ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <connections>
+ <action selector="systemIndigoButtonAction:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="rNl-zX-67r"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Arw-up-GyD">
+ <rect key="frame" x="145" y="100" width="40" height="40"/>
+ <color key="backgroundColor" systemColor="labelColor"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="40" id="A9m-mr-Ec3"/>
+ <constraint firstAttribute="height" constant="40" id="s6X-2m-m44"/>
+ </constraints>
+ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <connections>
+ <action selector="systemMintButtonAction:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="aDb-dN-ifP"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="I7I-Ed-32n">
+ <rect key="frame" x="145" y="155" width="40" height="40"/>
+ <color key="backgroundColor" systemColor="labelColor"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="40" id="Gd6-bt-nR7"/>
+ <constraint firstAttribute="width" constant="40" id="eRN-Vo-lal"/>
+ </constraints>
+ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <connections>
+ <action selector="systemPinkButtonAction:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="emC-0N-gqJ"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Uaq-hC-U4a">
+ <rect key="frame" x="145" y="210" width="40" height="40"/>
+ <color key="backgroundColor" systemColor="labelColor"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="40" id="DqE-d1-FMQ"/>
+ <constraint firstAttribute="width" constant="40" id="L0n-3P-wA1"/>
+ </constraints>
+ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <connections>
+ <action selector="defaultButtonAction:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="VhY-1n-fwQ"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="iB2-gu-3IO">
+ <rect key="frame" x="145" y="265" width="40" height="40"/>
+ <color key="backgroundColor" systemColor="labelColor"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="40" id="62A-PY-UZr"/>
+ <constraint firstAttribute="height" constant="40" id="P8F-Uh-nef"/>
+ </constraints>
+ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <connections>
+ <action selector="customButtonAction:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="sST-c5-Zap"/>
+ </connections>
+ </button>
+ </subviews>
+ <viewLayoutGuide key="safeArea" id="vDu-zF-Fre"/>
+ <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+ <constraints>
+ <constraint firstItem="vDu-zF-Fre" firstAttribute="trailing" secondItem="I7I-Ed-32n" secondAttribute="trailing" constant="15" id="3ke-4j-aut"/>
+ <constraint firstItem="12u-cu-XGu" firstAttribute="centerY" secondItem="8xv-8Y-A50" secondAttribute="centerY" id="3ns-C4-1Xk"/>
+ <constraint firstItem="FU6-q8-9Iw" firstAttribute="centerY" secondItem="Zr2-rF-YUt" secondAttribute="centerY" id="4Ul-fS-EGZ"/>
+ <constraint firstItem="I9w-cx-QlY" firstAttribute="centerY" secondItem="C2a-jB-FVB" secondAttribute="centerY" id="Adb-Hg-6jK"/>
+ <constraint firstItem="vDu-zF-Fre" firstAttribute="trailing" secondItem="8DH-gC-coa" secondAttribute="trailing" id="EXV-D4-maX"/>
+ <constraint firstItem="I7I-Ed-32n" firstAttribute="centerY" secondItem="LwF-26-oss" secondAttribute="centerY" id="HyJ-T6-sBi"/>
+ <constraint firstItem="vDu-zF-Fre" firstAttribute="trailing" secondItem="iB2-gu-3IO" secondAttribute="trailing" constant="15" id="Ig3-DV-ieD"/>
+ <constraint firstItem="Arw-up-GyD" firstAttribute="centerY" secondItem="FU6-q8-9Iw" secondAttribute="centerY" id="K5S-f9-g07"/>
+ <constraint firstItem="C2a-jB-FVB" firstAttribute="leading" secondItem="vDu-zF-Fre" secondAttribute="leading" constant="15" id="Lpi-y7-FCx"/>
+ <constraint firstItem="OlH-Ak-sRA" firstAttribute="centerX" secondItem="vDu-zF-Fre" secondAttribute="centerX" id="T5p-2s-e2t"/>
+ <constraint firstItem="I9w-cx-QlY" firstAttribute="centerX" secondItem="vDu-zF-Fre" secondAttribute="centerX" id="Vzf-ZI-4Y7"/>
+ <constraint firstItem="JUR-Vj-yBU" firstAttribute="leading" secondItem="vDu-zF-Fre" secondAttribute="leading" constant="15" id="ZH3-0g-M1x"/>
+ <constraint firstItem="8DH-gC-coa" firstAttribute="leading" secondItem="vDu-zF-Fre" secondAttribute="leading" id="bAT-qS-Fr3"/>
+ <constraint firstItem="C2a-jB-FVB" firstAttribute="top" secondItem="dOn-SY-wnl" secondAttribute="bottom" constant="15" id="byc-af-adU"/>
+ <constraint firstItem="vDu-zF-Fre" firstAttribute="trailing" secondItem="Arw-up-GyD" secondAttribute="trailing" constant="15" id="cyP-IZ-1wa"/>
+ <constraint firstItem="vDu-zF-Fre" firstAttribute="trailing" secondItem="tt7-sI-TfL" secondAttribute="trailing" constant="15" id="dOh-Zh-y8X"/>
+ <constraint firstItem="8DH-gC-coa" firstAttribute="centerY" secondItem="kwJ-4R-6nM" secondAttribute="centerY" id="dkq-zI-tcR"/>
+ <constraint firstItem="LwF-26-oss" firstAttribute="centerX" secondItem="vDu-zF-Fre" secondAttribute="centerX" id="eli-R1-TLW"/>
+ <constraint firstItem="dOn-SY-wnl" firstAttribute="leading" secondItem="vDu-zF-Fre" secondAttribute="leading" constant="15" id="gfe-aq-7nk"/>
+ <constraint firstItem="kwJ-4R-6nM" firstAttribute="top" secondItem="vDu-zF-Fre" secondAttribute="top" constant="10" id="hAt-TC-6LC"/>
+ <constraint firstItem="Zr2-rF-YUt" firstAttribute="top" secondItem="JUR-Vj-yBU" secondAttribute="bottom" constant="15" id="kLH-Zl-k0m"/>
+ <constraint firstItem="tt7-sI-TfL" firstAttribute="centerY" secondItem="OlH-Ak-sRA" secondAttribute="centerY" id="ksI-o1-K8w"/>
+ <constraint firstItem="LwF-26-oss" firstAttribute="centerY" secondItem="dOn-SY-wnl" secondAttribute="centerY" id="l31-GR-n7H"/>
+ <constraint firstItem="iB2-gu-3IO" firstAttribute="centerY" secondItem="12u-cu-XGu" secondAttribute="centerY" id="les-by-5nK"/>
+ <constraint firstItem="12u-cu-XGu" firstAttribute="centerX" secondItem="vDu-zF-Fre" secondAttribute="centerX" id="qE7-PC-xCD"/>
+ <constraint firstItem="Uaq-hC-U4a" firstAttribute="centerY" secondItem="I9w-cx-QlY" secondAttribute="centerY" id="qqP-HH-Ver"/>
+ <constraint firstItem="kwJ-4R-6nM" firstAttribute="leading" secondItem="vDu-zF-Fre" secondAttribute="leading" constant="10" id="rHM-tU-erV"/>
+ <constraint firstItem="OlH-Ak-sRA" firstAttribute="centerY" secondItem="JUR-Vj-yBU" secondAttribute="centerY" id="rwN-7j-Caf"/>
+ <constraint firstItem="8xv-8Y-A50" firstAttribute="top" secondItem="I9w-cx-QlY" secondAttribute="bottom" constant="15" id="tNf-9p-HHV"/>
+ <constraint firstItem="vDu-zF-Fre" firstAttribute="trailing" secondItem="Uaq-hC-U4a" secondAttribute="trailing" constant="15" id="tzG-Kx-can"/>
+ <constraint firstItem="dOn-SY-wnl" firstAttribute="top" secondItem="Zr2-rF-YUt" secondAttribute="bottom" constant="15" id="uIJ-Xj-Oe3"/>
+ <constraint firstItem="FU6-q8-9Iw" firstAttribute="centerX" secondItem="vDu-zF-Fre" secondAttribute="centerX" id="vzc-ef-AhZ"/>
+ <constraint firstItem="Zr2-rF-YUt" firstAttribute="leading" secondItem="vDu-zF-Fre" secondAttribute="leading" constant="15" id="zBA-2T-5J8"/>
+ <constraint firstItem="8xv-8Y-A50" firstAttribute="leading" secondItem="vDu-zF-Fre" secondAttribute="leading" constant="15" id="zJA-Gg-OZr"/>
+ <constraint firstItem="JUR-Vj-yBU" firstAttribute="top" secondItem="vDu-zF-Fre" secondAttribute="top" constant="45" id="zbI-KC-mx0"/>
+ </constraints>
+ </view>
+ <size key="freeformSize" width="200" height="320"/>
+ <connections>
+ <outlet property="blueButton" destination="C2a-jB-FVB" id="lIY-Ag-Nkv"/>
+ <outlet property="brownButton" destination="I9w-cx-QlY" id="b8T-np-0mw"/>
+ <outlet property="closeButton" destination="kwJ-4R-6nM" id="woU-Kz-IXU"/>
+ <outlet property="customButton" destination="iB2-gu-3IO" id="Vtm-VH-D0l"/>
+ <outlet property="cyanButton" destination="OlH-Ak-sRA" id="26d-bc-OiU"/>
+ <outlet property="defaultButton" destination="Uaq-hC-U4a" id="t6X-aV-hPF"/>
+ <outlet property="grayButton" destination="LwF-26-oss" id="lzV-jY-LNd"/>
+ <outlet property="greenButton" destination="8xv-8Y-A50" id="teG-ST-UCN"/>
+ <outlet property="orangeButton" destination="JUR-Vj-yBU" id="aGO-8f-0Em"/>
+ <outlet property="purpleButton" destination="dOn-SY-wnl" id="hes-XJ-gMJ"/>
+ <outlet property="redButton" destination="Zr2-rF-YUt" id="jib-wX-2Of"/>
+ <outlet property="systemBlueButton" destination="12u-cu-XGu" id="aOV-BK-urz"/>
+ <outlet property="systemIndigoButton" destination="tt7-sI-TfL" id="tUi-Th-IDf"/>
+ <outlet property="systemMintButton" destination="Arw-up-GyD" id="gqG-tN-WiJ"/>
+ <outlet property="systemPinkButton" destination="I7I-Ed-32n" id="YzP-1f-nkJ"/>
+ <outlet property="titleLabel" destination="8DH-gC-coa" id="k2U-jx-f6R"/>
+ <outlet property="yellowButton" destination="FU6-q8-9Iw" id="oAa-NT-Qhd"/>
+ </connections>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="Ief-a0-LHa" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="-233.4375" y="50.70422535211268"/>
+ </scene>
+ </scenes>
+ <resources>
+ <image name="xmark" width="24" height="24"/>
+ <systemColor name="labelColor">
+ <color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </systemColor>
+ <systemColor name="systemBackgroundColor">
+ <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </systemColor>
+ </resources>
+</document>
diff --git a/iOSClient/Color/NCColorPicker.swift b/iOSClient/Color/NCColorPicker.swift
new file mode 100644
index 000000000..2bfba58b5
--- /dev/null
+++ b/iOSClient/Color/NCColorPicker.swift
@@ -0,0 +1,224 @@
+//
+// NCColorPicker.swift
+// Nextcloud
+//
+// Created by Marino Faggiana on 24/07/22.
+// Copyright © 2022 Marino Faggiana. All rights reserved.
+//
+
+import Foundation
+import UIKit
+
+class NCColorPicker: UIViewController {
+
+ @IBOutlet weak var closeButton: UIButton!
+ @IBOutlet weak var titleLabel: UILabel!
+
+ @IBOutlet weak var orangeButton: UIButton!
+ @IBOutlet weak var redButton: UIButton!
+ @IBOutlet weak var purpleButton: UIButton!
+ @IBOutlet weak var blueButton: UIButton!
+ @IBOutlet weak var greenButton: UIButton!
+ @IBOutlet weak var cyanButton: UIButton!
+ @IBOutlet weak var yellowButton: UIButton!
+ @IBOutlet weak var grayButton: UIButton!
+ @IBOutlet weak var brownButton: UIButton!
+
+ @IBOutlet weak var systemBlueButton: UIButton!
+ @IBOutlet weak var systemIndigoButton: UIButton!
+ @IBOutlet weak var systemMintButton: UIButton!
+ @IBOutlet weak var systemPinkButton: UIButton!
+
+ @IBOutlet weak var defaultButton: UIButton!
+ @IBOutlet weak var customButton: UIButton!
+
+ var metadata: tableMetadata?
+ var tapAction: UITapGestureRecognizer?
+ var selectedColor: UIColor?
+
+ // MARK: - View Life Cycle
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ view.backgroundColor = NCBrandColor.shared.secondarySystemBackground
+
+ if let metadata = metadata {
+ let serverUrl = metadata.serverUrl + "/" + metadata.fileName
+ if let tableDirectory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, serverUrl)), let hex = tableDirectory.colorFolder, let color = UIColor(hex: hex) {
+ selectedColor = color
+ }
+ }
+
+ closeButton.setImage(NCUtility.shared.loadImage(named: "xmark", color: NCBrandColor.shared.label), for: .normal)
+ titleLabel.text = NSLocalizedString("_select_color_", comment: "")
+
+ orangeButton.backgroundColor = .orange
+ orangeButton.layer.cornerRadius = 5
+ orangeButton.layer.masksToBounds = true
+
+ redButton.backgroundColor = .red
+ redButton.layer.cornerRadius = 5
+ redButton.layer.masksToBounds = true
+
+ purpleButton.backgroundColor = .purple
+ purpleButton.layer.cornerRadius = 5
+ purpleButton.layer.masksToBounds = true
+
+ blueButton.backgroundColor = .blue
+ blueButton.layer.cornerRadius = 5
+ blueButton.layer.masksToBounds = true
+
+ brownButton.backgroundColor = .brown
+ brownButton.layer.cornerRadius = 5
+ brownButton.layer.masksToBounds = true
+
+ greenButton.backgroundColor = .green
+ greenButton.layer.cornerRadius = 5
+ greenButton.layer.masksToBounds = true
+
+ grayButton.backgroundColor = .gray
+ grayButton.layer.cornerRadius = 5
+ grayButton.layer.masksToBounds = true
+
+ cyanButton.backgroundColor = .cyan
+ cyanButton.layer.cornerRadius = 5
+ cyanButton.layer.masksToBounds = true
+
+ yellowButton.backgroundColor = .yellow
+ yellowButton.layer.cornerRadius = 5
+ yellowButton.layer.masksToBounds = true
+
+ systemBlueButton.backgroundColor = NCBrandColor.shared.systemBlue
+ systemBlueButton.layer.cornerRadius = 5
+ systemBlueButton.layer.masksToBounds = true
+
+ systemMintButton.backgroundColor = NCBrandColor.shared.systemMint
+ systemMintButton.layer.cornerRadius = 5
+ systemMintButton.layer.masksToBounds = true
+
+ systemPinkButton.backgroundColor = NCBrandColor.shared.systemPink
+ systemPinkButton.layer.cornerRadius = 5
+ systemPinkButton.layer.masksToBounds = true
+
+ if #available(iOS 14.0, *) {
+ customButton.setImage(UIImage(named: "rgb"), for: .normal)
+ if let selectedColor = selectedColor {
+ customButton.backgroundColor = selectedColor
+ } else {
+ customButton.backgroundColor = NCBrandColor.shared.secondarySystemBackground
+ }
+ } else {
+ customButton.backgroundColor = NCBrandColor.shared.systemTeal
+ }
+ customButton.layer.cornerRadius = 5
+ customButton.layer.masksToBounds = true
+
+ systemIndigoButton.backgroundColor = NCBrandColor.shared.systemIndigo
+ systemIndigoButton.layer.cornerRadius = 5
+ systemIndigoButton.layer.masksToBounds = true
+
+ defaultButton.backgroundColor = NCBrandColor.shared.brandElement
+ defaultButton.layer.cornerRadius = 5
+ defaultButton.layer.masksToBounds = true
+ }
+
+ // MARK: - Action
+
+ @IBAction func closeAction(_ sender: UIButton) {
+ dismiss(animated: true)
+ }
+
+ @IBAction func orangeButtonAction(_ sender: AnyObject) {
+ updateColor(hexColor: UIColor.orange.hexString)
+ }
+
+ @IBAction func redButtonAction(_ sender: AnyObject) {
+ updateColor(hexColor: UIColor.red.hexString)
+ }
+
+ @IBAction func purpleButtonAction(_ sender: AnyObject) {
+ updateColor(hexColor: UIColor.purple.hexString)
+ }
+
+ @IBAction func blueButtonAction(_ sender: AnyObject) {
+ updateColor(hexColor: UIColor.blue.hexString)
+ }
+
+ @IBAction func greenButtonAction(_ sender: AnyObject) {
+ updateColor(hexColor: UIColor.green.hexString)
+ }
+
+ @IBAction func cyanButtonAction(_ sender: AnyObject) {
+ updateColor(hexColor: UIColor.cyan.hexString)
+ }
+
+ @IBAction func yellowButtonAction(_ sender: AnyObject) {
+ updateColor(hexColor: UIColor.yellow.hexString)
+ }
+
+ @IBAction func grayButtonAction(_ sender: AnyObject) {
+ updateColor(hexColor: UIColor.gray.hexString)
+ }
+
+ @IBAction func brownButtonAction(_ sender: AnyObject) {
+ updateColor(hexColor: UIColor.brown.hexString)
+ }
+
+ @IBAction func systemBlueButtonAction(_ sender: AnyObject) {
+ updateColor(hexColor: NCBrandColor.shared.systemBlue.hexString)
+ }
+
+ @IBAction func systemIndigoButtonAction(_ sender: AnyObject) {
+ updateColor(hexColor: NCBrandColor.shared.systemIndigo.hexString)
+ }
+
+ @IBAction func systemMintButtonAction(_ sender: AnyObject) {
+ updateColor(hexColor: NCBrandColor.shared.systemMint.hexString)
+ }
+
+ @IBAction func systemPinkButtonAction(_ sender: AnyObject) {
+ updateColor(hexColor: NCBrandColor.shared.systemPink.hexString)
+ }
+
+ @IBAction func defaultButtonAction(_ sender: AnyObject) {
+ updateColor(hexColor: nil)
+ }
+
+ @IBAction func customButtonAction(_ sender: AnyObject) {
+
+ if #available(iOS 14.0, *) {
+ let picker = UIColorPickerViewController()
+ picker.delegate = self
+ picker.supportsAlpha = false
+ if let selectedColor = selectedColor {
+ picker.selectedColor = selectedColor
+ }
+ self.present(picker, animated: true, completion: nil)
+ } else {
+ updateColor(hexColor: NCBrandColor.shared.systemTeal.hexString)
+ }
+ }
+
+ // MARK: -
+
+ func updateColor(hexColor: String?) {
+ if let metadata = metadata {
+ let serverUrl = metadata.serverUrl + "/" + metadata.fileName
+ if NCManageDatabase.shared.setDirectory(serverUrl: serverUrl, colorFolder: hexColor, account: metadata.account) != nil {
+ self.dismiss(animated: true)
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": metadata.serverUrl])
+ }
+ }
+ self.dismiss(animated: true)
+ }
+}
+
+@available(iOS 14.0, *)
+extension NCColorPicker: UIColorPickerViewControllerDelegate {
+
+ func colorPickerViewControllerDidFinish(_ viewController: UIColorPickerViewController) {
+ let hexColor = viewController.selectedColor.hexString
+ updateColor(hexColor: hexColor)
+ }
+}
diff --git a/iOSClient/Data/NCDataSource.swift b/iOSClient/Data/NCDataSource.swift
index 09c423492..6922093a3 100644
--- a/iOSClient/Data/NCDataSource.swift
+++ b/iOSClient/Data/NCDataSource.swift
@@ -22,12 +22,21 @@
//
import UIKit
+import NCCommunication
class NCDataSource: NSObject {
- public var metadatas: [tableMetadata] = []
- public var metadataShare: [String: tableShare] = [:]
- public var metadataOffLine: [String] = []
+ var metadatas: [tableMetadata] = []
+ var metadatasForSection: [NCMetadataForSection] = []
+
+ var directory: tableDirectory?
+ var groupByField: String = ""
+
+ private var sectionsValue: [String] = []
+ private var providers: [NCCSearchProvider]?
+ private var searchResults: [NCCSearchResult]?
+ private var shares: [tableShare] = []
+ private var localFiles: [tableLocalFile] = []
private var ascending: Bool = true
private var sort: String = ""
@@ -39,214 +48,512 @@ class NCDataSource: NSObject {
super.init()
}
- init(metadatasSource: [tableMetadata], sort: String? = "none", ascending: Bool? = false, directoryOnTop: Bool? = true, favoriteOnTop: Bool? = true, filterLivePhoto: Bool? = true) {
+ init(metadatas: [tableMetadata], account: String, directory: tableDirectory? = nil, sort: String? = "none", ascending: Bool? = false, directoryOnTop: Bool? = true, favoriteOnTop: Bool? = true, filterLivePhoto: Bool? = true, groupByField: String = "name", providers: [NCCSearchProvider]? = nil, searchResults: [NCCSearchResult]? = nil) {
super.init()
+ self.metadatas = metadatas
+ self.directory = directory
+ self.shares = NCManageDatabase.shared.getTableShares(account: account)
+ self.localFiles = NCManageDatabase.shared.getTableLocalFile(account: account)
self.sort = sort ?? "none"
self.ascending = ascending ?? false
self.directoryOnTop = directoryOnTop ?? true
self.favoriteOnTop = favoriteOnTop ?? true
self.filterLivePhoto = filterLivePhoto ?? true
+ self.groupByField = groupByField
+ // unified search
+ self.providers = providers
+ self.searchResults = searchResults
- createMetadatas(metadatasSource: metadatasSource)
+ createSections()
}
// MARK: -
- private func createMetadatas(metadatasSource: [tableMetadata]) {
+ func clearDataSource() {
- var metadatasSourceSorted: [tableMetadata] = []
- var metadataFavoriteDirectory: [tableMetadata] = []
- var metadataFavoriteFile: [tableMetadata] = []
- var metadataDirectory: [tableMetadata] = []
- var metadataFile: [tableMetadata] = []
+ self.metadatas.removeAll()
+ self.metadatasForSection.removeAll()
+ self.directory = nil
+ self.sectionsValue.removeAll()
+ self.providers = nil
+ self.searchResults = nil
+ self.shares.removeAll()
+ self.localFiles.removeAll()
+ }
- /*
- Metadata order
- */
+ func clearDirectory() {
- if sort != "none" && sort != "" {
- metadatasSourceSorted = metadatasSource.sorted { (obj1: tableMetadata, obj2: tableMetadata) -> Bool in
- if sort == "date" {
- if ascending {
- return obj1.date.compare(obj2.date as Date) == ComparisonResult.orderedAscending
- } else {
- return obj1.date.compare(obj2.date as Date) == ComparisonResult.orderedDescending
- }
- } else if sort == "size" {
- if ascending {
- return obj1.size < obj2.size
- } else {
- return obj1.size > obj2.size
- }
- } else {
- if ascending {
- return obj1.fileNameView.localizedStandardCompare(obj2.fileNameView) == ComparisonResult.orderedAscending
- } else {
- return obj1.fileNameView.localizedStandardCompare(obj2.fileNameView) == ComparisonResult.orderedDescending
- }
- }
- }
- } else {
- metadatasSourceSorted = metadatasSource
- }
+ self.directory = nil
+ }
- /*
- Initialize datasource
- */
+ func changeGroupByField(_ groupByField: String) {
- for metadata in metadatasSourceSorted {
+ self.groupByField = groupByField
+ print("DATASOURCE: set group by filed " + groupByField)
+ self.metadatasForSection.removeAll()
+ self.sectionsValue.removeAll()
+ print("DATASOURCE: remove all sections")
- // skipped the root file
- if metadata.fileName == "." || metadata.serverUrl == ".." {
- continue
- }
+ createSections()
+ }
+ func addSection(metadatas: [tableMetadata], searchResult: NCCSearchResult?) {
+
+ self.metadatas.append(contentsOf: metadatas)
+
+ if let searchResult = searchResult {
+ self.searchResults?.append(searchResult)
+ }
+
+ createSections()
+ }
+
+ internal func createSections() {
+
+ // get all Section
+ for metadata in self.metadatas {
// skipped livePhoto
- if metadata.ext == "mov" && metadata.livePhoto && filterLivePhoto {
+ if filterLivePhoto && metadata.livePhoto && metadata.ext == "mov" {
continue
}
-
- // share
- let shares = NCManageDatabase.shared.getTableShares(account: metadata.account, serverUrl: metadata.serverUrl, fileName: metadata.fileName)
- if shares.count > 0 {
- metadataShare[metadata.ocId] = shares.first
+ let section = NSLocalizedString(self.getSectionValue(metadata: metadata), comment: "").lowercased().firstUppercased
+ if !self.sectionsValue.contains(section) {
+ self.sectionsValue.append(section)
}
+ }
- // is Local / offline
- if !metadata.directory, CCUtility.fileProviderStorageExists(metadata) {
- let tableLocalFile = NCManageDatabase.shared.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
- if tableLocalFile == nil {
- NCManageDatabase.shared.addLocalFile(metadata: metadata)
+ // Unified search
+ if let providers = self.providers, !providers.isEmpty {
+ let sectionsDictionary = ThreadSafeDictionary<String,Int>()
+ for section in self.sectionsValue {
+ if let provider = providers.filter({ $0.name.lowercased() == section.lowercased()}).first {
+ sectionsDictionary[section] = provider.order
}
- if tableLocalFile?.offline ?? false {
- metadataOffLine.append(metadata.ocId)
+ }
+ self.sectionsValue.removeAll()
+ let sectionsDictionarySorted = sectionsDictionary.sorted(by: { $0.value < $1.value } )
+ let appName = NSLocalizedString(NCGlobal.shared.appName, comment: "").lowercased().firstUppercased
+ for section in sectionsDictionarySorted {
+ if section.key == appName {
+ self.sectionsValue.insert(section.key, at: 0)
+ } else {
+ self.sectionsValue.append(section.key)
}
}
- // Organized the metadata
- if metadata.favorite && favoriteOnTop {
- if metadata.directory {
- metadataFavoriteDirectory.append(metadata)
+ } else {
+
+ // normal
+ let directory = NSLocalizedString("directory", comment: "").lowercased().firstUppercased
+ self.sectionsValue = self.sectionsValue.sorted {
+ if directoryOnTop && $0 == directory {
+ return true
+ } else if directoryOnTop && $1 == directory {
+ return false
+ }
+ if self.ascending {
+ return $0 < $1
} else {
- metadataFavoriteFile.append(metadata)
+ return $0 > $1
}
- } else if metadata.directory && directoryOnTop {
- metadataDirectory.append(metadata)
- } else {
- metadataFile.append(metadata)
}
}
- metadatas.removeAll()
- metadatas += metadataFavoriteDirectory
- metadatas += metadataFavoriteFile
- metadatas += metadataDirectory
- metadatas += metadataFile
+ for sectionValue in self.sectionsValue {
+ if !existsMetadataForSection(sectionValue: sectionValue) {
+ print("DATASOURCE: create metadata for section: " + sectionValue)
+ createMetadataForSection(sectionValue: sectionValue)
+ }
+ }
+ }
+
+ internal func createMetadataForSection(sectionValue: String) {
+
+ var searchResult: NCCSearchResult?
+ if let providers = self.providers, !providers.isEmpty, let searchResults = self.searchResults {
+ searchResult = searchResults.filter({ $0.name == sectionValue}).first
+ }
+ let metadatas = self.metadatas.filter({ getSectionValue(metadata: $0) == sectionValue})
+ let metadataForSection = NCMetadataForSection.init(sectionValue: sectionValue,
+ metadatas: metadatas,
+ shares: self.shares,
+ localFiles: self.localFiles,
+ lastSearchResult: searchResult,
+ sort: self.sort,
+ ascending: self.ascending,
+ directoryOnTop: self.directoryOnTop,
+ favoriteOnTop: self.favoriteOnTop,
+ filterLivePhoto: self.filterLivePhoto)
+ metadatasForSection.append(metadataForSection)
+ }
+
+ func getMetadataSourceForAllSections() -> [tableMetadata] {
+
+ var metadatas: [tableMetadata] = []
+
+ for section in metadatasForSection {
+ metadatas.append(contentsOf: section.metadatas)
+ }
+
+ return metadatas
}
// MARK: -
- func getFilesInformation() -> (directories: Int, files: Int, size: Int64) {
+ @discardableResult
+ func appendMetadatasToSection(_ metadatas: [tableMetadata], metadataForSection: NCMetadataForSection, lastSearchResult: NCCSearchResult) -> [IndexPath] {
+
+ guard let sectionIndex = getSectionIndex(metadataForSection.sectionValue) else { return [] }
+ var indexPaths: [IndexPath] = []
- var directories: Int = 0
- var files: Int = 0
- var size: Int64 = 0
+ self.metadatas.append(contentsOf: metadatas)
+ metadataForSection.metadatas.append(contentsOf: metadatas)
+ metadataForSection.lastSearchResult = lastSearchResult
+ metadataForSection.createMetadatas()
for metadata in metadatas {
- if metadata.directory {
- directories += 1
+ if let rowIndex = metadataForSection.metadatas.firstIndex(where: {$0.ocId == metadata.ocId}) {
+ indexPaths.append(IndexPath(row: rowIndex, section: sectionIndex))
+ }
+ }
+
+ return indexPaths
+ }
+
+ @discardableResult
+ func addMetadata(_ metadata: tableMetadata) -> (indexPath: IndexPath?, sameSections: Bool) {
+
+ let numberOfSections = self.numberOfSections()
+ let sectionValue = getSectionValue(metadata: metadata)
+
+ // ADD metadatasSource
+ if let rowIndex = self.metadatas.firstIndex(where: {$0.fileNameView == metadata.fileNameView || $0.ocId == metadata.ocId}) {
+ self.metadatas[rowIndex] = metadata
+ } else {
+ self.metadatas.append(metadata)
+ }
+
+ // ADD metadataForSection
+ if let sectionIndex = getSectionIndex(sectionValue), let metadataForSection = getMetadataForSection(sectionIndex) {
+ if let rowIndex = metadataForSection.metadatas.firstIndex(where: {$0.fileNameView == metadata.fileNameView || $0.ocId == metadata.ocId}) {
+ metadataForSection.metadatas[rowIndex] = metadata
+ return (IndexPath(row: rowIndex, section: sectionIndex), self.isSameNumbersOfSections(numberOfSections: numberOfSections))
} else {
- files += 1
+ metadataForSection.metadatas.append(metadata)
+ metadataForSection.createMetadatas()
+ if let rowIndex = metadataForSection.metadatas.firstIndex(where: {$0.ocId == metadata.ocId}) {
+ return (IndexPath(row: rowIndex, section: sectionIndex), self.isSameNumbersOfSections(numberOfSections: numberOfSections))
+ }
+ return (nil, self.isSameNumbersOfSections(numberOfSections: numberOfSections))
+ }
+ } else {
+ // NEW section
+ createSections()
+ // get IndexPath of new section
+ if let sectionIndex = getSectionIndex(sectionValue), let metadataForSection = getMetadataForSection(sectionIndex) {
+ if let rowIndex = metadataForSection.metadatas.firstIndex(where: {$0.fileNameView == metadata.fileNameView || $0.ocId == metadata.ocId}) {
+ return (IndexPath(row: rowIndex, section: sectionIndex), self.isSameNumbersOfSections(numberOfSections: numberOfSections))
+ }
}
- size += metadata.size
}
- return (directories, files, size)
+ return (nil, self.isSameNumbersOfSections(numberOfSections: numberOfSections))
}
- func deleteMetadata(ocId: String) -> Int? {
+ func deleteMetadata(ocId: String) -> (indexPath: IndexPath?, sameSections: Bool) {
+
+ let numberOfSections = self.numberOfSections()
+ var indexPathReturn: IndexPath?
+ var sectionValue = ""
+
+ // DELETE metadataForSection (IMPORTANT FIRST)
+ let (indexPath, metadataForSection) = self.getIndexPathMetadata(ocId: ocId)
+ if let indexPath = indexPath, let metadataForSection = metadataForSection, indexPath.row < metadataForSection.metadatas.count {
+ metadataForSection.metadatas.remove(at: indexPath.row)
+ if metadataForSection.metadatas.count == 0 {
+ // REMOVE sectionsValue / metadatasForSection
+ sectionValue = metadataForSection.sectionValue
+ if let sectionIndex = getSectionIndex(sectionValue) {
+ self.sectionsValue.remove(at: sectionIndex)
+ }
+ if let index = getIndexMetadatasForSection(sectionValue) {
+ self.metadatasForSection.remove(at: index)
+ }
+ } else {
+ metadataForSection.createMetadatas()
+ }
+ indexPathReturn = indexPath
+ } else { return (nil, false) }
- if let index = self.getIndexMetadata(ocId: ocId) {
- metadatas.remove(at: index)
- return index
+ // DELETE metadatasSource (IMPORTANT LAST)
+ if let rowIndex = self.metadatas.firstIndex(where: {$0.ocId == ocId}) {
+ self.metadatas.remove(at: rowIndex)
}
- return nil
+ return (indexPathReturn, self.isSameNumbersOfSections(numberOfSections: numberOfSections))
}
@discardableResult
- func reloadMetadata(ocId: String, ocIdTemp: String? = nil) -> Int? {
+ func reloadMetadata(ocId: String, ocIdTemp: String? = nil) -> (indexPath: IndexPath?, sameSections: Bool) {
+
+ let numberOfSections = self.numberOfSections()
+ var ocIdSearch = ocId
- var index: Int?
+ guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return (nil, self.isSameNumbersOfSections(numberOfSections: numberOfSections)) }
if let ocIdTemp = ocIdTemp {
- index = self.getIndexMetadata(ocId: ocIdTemp)
- } else {
- index = self.getIndexMetadata(ocId: ocId)
+ ocIdSearch = ocIdTemp
}
- guard let index = index, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return nil }
- metadatas[index] = metadata
+ // UPDATE metadataForSection (IMPORTANT FIRST)
+ let (indexPath, metadataForSection) = self.getIndexPathMetadata(ocId: ocIdSearch)
+ if let indexPath = indexPath, let metadataForSection = metadataForSection {
+ metadataForSection.metadatas[indexPath.row] = metadata
+ metadataForSection.createMetadatas()
+ }
- if CCUtility.fileProviderStorageExists(metadata) {
- let tableLocalFile = NCManageDatabase.shared.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
- if tableLocalFile?.offline ?? false {
- metadataOffLine.append(metadata.ocId)
- }
+ // UPDATE metadatasSource (IMPORTANT LAST)
+ if let rowIndex = self.metadatas.firstIndex(where: {$0.ocId == ocIdSearch}) {
+ self.metadatas[rowIndex] = metadata
}
- return index
+ let result = self.getIndexPathMetadata(ocId: ocId)
+ return (result.indexPath, self.isSameNumbersOfSections(numberOfSections: numberOfSections))
}
- @discardableResult
- func addMetadata(_ metadata: tableMetadata) -> Int? {
+ // MARK: -
- var index: Int = 0
+ func getIndexPathMetadata(ocId: String) -> (indexPath: IndexPath?, metadataForSection: NCMetadataForSection?) {
+ guard let metadata = self.metadatas.filter({ $0.ocId == ocId}).first else { return (nil, nil) }
+ let sectionValue = getSectionValue(metadata: metadata)
+ guard let sectionIndex = getSectionIndex(sectionValue), let metadataForSection = getMetadataForSection(sectionValue), let rowIndex = metadataForSection.metadatas.firstIndex(where: {$0.ocId == ocId}) else { return (nil, nil) }
+ return (IndexPath(row: rowIndex, section: sectionIndex), metadataForSection)
+ }
- // Already exists
- for metadataCount in metadatas {
- if metadataCount.fileNameView == metadata.fileNameView || metadataCount.ocId == metadata.ocId {
- metadatas[index] = metadata
- return index
- }
- index += 1
- }
+ func isSameNumbersOfSections(numberOfSections: Int) -> Bool {
+ guard self.metadatasForSection.count > 0 else { return false }
+ return numberOfSections == self.numberOfSections()
+ }
- // Append & rebuild
- metadatas.append(metadata)
- createMetadatas(metadatasSource: metadatas)
+ func numberOfSections() -> Int {
+ guard self.sectionsValue.count > 0 else { return 1 }
+ return self.sectionsValue.count
+ }
+
+ func numberOfItemsInSection(_ section: Int) -> Int {
+ guard self.sectionsValue.count > 0 && self.metadatas.count > 0, let metadataForSection = getMetadataForSection(section) else { return 0}
+ return metadataForSection.metadatas.count
+ }
+
+ func cellForItemAt(indexPath: IndexPath) -> tableMetadata? {
+ guard metadatasForSection.count > 0 && indexPath.section < metadatasForSection.count, let metadataForSection = getMetadataForSection(indexPath.section), indexPath.row < metadataForSection.metadatas.count else { return nil }
+ return metadataForSection.metadatas[indexPath.row]
+ }
- return getIndexMetadata(ocId: metadata.ocId)
+ func getSectionValue(indexPath: IndexPath) -> String {
+ guard metadatasForSection.count > 0 , let metadataForSection = self.getMetadataForSection(indexPath.section) else { return ""}
+ return metadataForSection.sectionValue
}
- func getIndexMetadata(ocId: String) -> Int? {
+ func getFooterInformationAllMetadatas() -> (directories: Int, files: Int, size: Int64) {
- var index: Int = 0
+ var directories: Int = 0
+ var files: Int = 0
+ var size: Int64 = 0
- for metadataCount in metadatas {
- if metadataCount.ocId == ocId {
- return index
- }
- index += 1
+ for metadataForSection in metadatasForSection {
+ directories += metadataForSection.numDirectory
+ files += metadataForSection.numFile
+ size += metadataForSection.totalSize
}
- return nil
+ return (directories, files, size)
}
- func numberOfItems() -> Int {
+ // MARK: -
+
+ internal func getSectionValue(metadata: tableMetadata) -> String {
- return metadatas.count
+ switch self.groupByField {
+ case "name":
+ return NSLocalizedString(metadata.name, comment: "").lowercased().firstUppercased
+ case "classFile":
+ return NSLocalizedString(metadata.classFile, comment: "").lowercased().firstUppercased
+ default:
+ return NSLocalizedString(metadata.name, comment: "").lowercased().firstUppercased
+ }
}
- func cellForItemAt(indexPath: IndexPath) -> tableMetadata? {
+ internal func getIndexMetadatasForSection(_ sectionValue: String) -> Int? {
+ return self.metadatasForSection.firstIndex(where: {$0.sectionValue == sectionValue })
+ }
+
+ internal func getSectionIndex(_ sectionValue: String) -> Int? {
+ return self.sectionsValue.firstIndex(where: {$0 == sectionValue })
+ }
+
+ internal func existsMetadataForSection(sectionValue: String) -> Bool {
+ return !self.metadatasForSection.filter({ $0.sectionValue == sectionValue }).isEmpty
+ }
+
+ internal func getMetadataForSection(_ section: Int) -> NCMetadataForSection? {
+ guard section < sectionsValue.count, let metadataForSection = self.metadatasForSection.filter({ $0.sectionValue == sectionsValue[section]}).first else { return nil }
+ return metadataForSection
+ }
+
+ internal func getMetadataForSection(_ sectionValue: String) -> NCMetadataForSection? {
+ guard let metadataForSection = self.metadatasForSection.filter({ $0.sectionValue == sectionValue }).first else { return nil }
+ return metadataForSection
+ }
+}
+
+// MARK: -
+
+class NCMetadataForSection: NSObject {
+
+ var sectionValue: String
+ var metadatas: [tableMetadata]
+ var shares: [tableShare]
+ var localFiles: [tableLocalFile]
+ var lastSearchResult: NCCSearchResult?
+ var unifiedSearchInProgress: Bool = false
+
+ private var sort : String
+ private var ascending: Bool
+ private var directoryOnTop: Bool
+ private var favoriteOnTop: Bool
+ private var filterLivePhoto: Bool
+
+ private var metadatasSorted: [tableMetadata] = []
+ private var metadatasFavoriteDirectory: [tableMetadata] = []
+ private var metadatasFavoriteFile: [tableMetadata] = []
+ private var metadatasDirectory: [tableMetadata] = []
+ private var metadatasFile: [tableMetadata] = []
+
+ public var numDirectory: Int = 0
+ public var numFile: Int = 0
+ public var totalSize: Int64 = 0
+ public let metadataShare = ThreadSafeDictionary<String,tableShare>()
+ public var metadataOffLine: [String] = []
+ public var directories: [tableDirectory]?
+
+ init(sectionValue: String, metadatas: [tableMetadata], shares: [tableShare], localFiles: [tableLocalFile], lastSearchResult: NCCSearchResult?, sort: String, ascending: Bool, directoryOnTop: Bool, favoriteOnTop: Bool, filterLivePhoto: Bool) {
+
+ self.sectionValue = sectionValue
+ self.metadatas = metadatas
+ self.shares = shares
+ self.localFiles = localFiles
+ self.lastSearchResult = lastSearchResult
+ self.sort = sort
+ self.ascending = ascending
+ self.directoryOnTop = directoryOnTop
+ self.favoriteOnTop = favoriteOnTop
+ self.filterLivePhoto = filterLivePhoto
+
+ super.init()
+
+ createMetadatas()
+ }
+
+ func createMetadatas() {
+
+ // Clear
+ //
+ metadatasSorted.removeAll()
+ metadatasFavoriteDirectory.removeAll()
+ metadatasFavoriteFile.removeAll()
+ metadatasDirectory.removeAll()
+ metadatasFile.removeAll()
+ metadataShare.removeAll()
+ metadataOffLine.removeAll()
+
+ numDirectory = 0
+ numFile = 0
+ totalSize = 0
+
+ var ocIds: [String] = []
- let row = indexPath.row
+ // Metadata order
+ //
+ if sort != "none" && sort != "" {
+ metadatasSorted = metadatas.sorted {
- if row > metadatas.count - 1 {
- return nil
+ switch sort {
+ case "date":
+ if ascending {
+ return ($0.date as Date) < ($1.date as Date)
+ } else {
+ return ($0.date as Date) > ($1.date as Date)
+ }
+ case "size":
+ if ascending {
+ return $0.size < $1.size
+ } else {
+ return $0.size > $1.size
+ }
+ default:
+ if ascending {
+ return $0.fileNameView.lowercased() < $1.fileNameView.lowercased()
+ } else {
+ return $0.fileNameView.lowercased() > $1.fileNameView.lowercased()
+ }
+ }
+ }
} else {
- return metadatas[row]
+ metadatasSorted = metadatas
}
+
+ // Initialize datasource
+ //
+ for metadata in metadatasSorted {
+
+ // skipped the root file
+ if metadata.fileName == "." || metadata.serverUrl == ".." {
+ continue
+ }
+
+ // skipped livePhoto
+ if filterLivePhoto && metadata.livePhoto && metadata.ext == "mov" {
+ continue
+ }
+
+ // share
+ if let share = self.shares.filter({ $0.serverUrl == metadata.serverUrl && $0.fileName == metadata.fileName }).first {
+ metadataShare[metadata.ocId] = share
+ }
+
+ // Organized the metadata
+ if metadata.favorite && favoriteOnTop {
+ if metadata.directory {
+ metadatasFavoriteDirectory.append(metadata)
+ } else {
+ metadatasFavoriteFile.append(metadata)
+ }
+ } else if metadata.directory && directoryOnTop {
+ metadatasDirectory.append(metadata)
+ } else {
+ metadatasFile.append(metadata)
+ }
+
+ //Info
+ if metadata.directory {
+ ocIds.append(metadata.ocId)
+ numDirectory += 1
+ } else {
+ numFile += 1
+ totalSize += metadata.size
+ }
+ }
+
+ directories = NCManageDatabase.shared.getTablesDirectory(predicate: NSPredicate(format: "ocId IN %@", ocIds), sorted: "serverUrl", ascending: true)
+
+ metadatas.removeAll()
+
+ // Struct view : favorite dir -> favorite file -> directory -> files
+ metadatas += metadatasFavoriteDirectory
+ metadatas += metadatasFavoriteFile
+ metadatas += metadatasDirectory
+ metadatas += metadatasFile
}
}
diff --git a/iOSClient/Data/NCDatabase.swift b/iOSClient/Data/NCDatabase.swift
index 0bd307150..4545a0723 100644
--- a/iOSClient/Data/NCDatabase.swift
+++ b/iOSClient/Data/NCDatabase.swift
@@ -85,10 +85,6 @@ class tableAccount: Object, NCUserBaseUrl {
@objc dynamic var website = ""
@objc dynamic var zip = ""
- // COLOR Files
- @objc dynamic var darkColorBackground = ""
- @objc dynamic var lightColorBackground = ""
-
// HC
@objc dynamic var hcIsTrial: Bool = false
@objc dynamic var hcTrialExpired: Bool = false
@@ -138,7 +134,8 @@ class tableActivity: Object, DateCompareable {
class tableActivityLatestId: Object {
@objc dynamic var account = ""
- @objc dynamic var mostRecentlyLoadedActivityId: Int = 0
+ @objc dynamic var activityFirstKnown: Int = 0
+ @objc dynamic var activityLastGiven: Int = 0
override static func primaryKey() -> String {
return "account"
}
@@ -260,6 +257,7 @@ class tableDirectEditingEditors: Object {
class tableDirectory: Object {
@objc dynamic var account = ""
+ @objc dynamic var colorFolder: String?
@objc dynamic var e2eEncrypted: Bool = false
@objc dynamic var etag = ""
@objc dynamic var favorite: Bool = false
@@ -350,6 +348,14 @@ class tableLocalFile: Object {
}
class tableMetadata: Object, NCUserBaseUrl {
+ override func isEqual(_ object: Any?) -> Bool {
+ if let object = object as? tableMetadata {
+ return self.fileId == object.fileId && self.account == object.account
+ && self.path == object.path && self.fileName == object.fileName
+ } else {
+ return false
+ }
+ }
@objc dynamic var account = ""
@objc dynamic var assetLocalIdentifier = ""
@@ -376,8 +382,11 @@ class tableMetadata: Object, NCUserBaseUrl {
@objc dynamic var fileNameWithoutExt = ""
@objc dynamic var hasPreview: Bool = false
@objc dynamic var iconName = ""
+ @objc dynamic var iconUrl = ""
+ @objc dynamic var isExtractFile: Bool = false
@objc dynamic var livePhoto: Bool = false
@objc dynamic var mountType = ""
+ @objc dynamic var name = ""
@objc dynamic var note = ""
@objc dynamic var ocId = ""
@objc dynamic var ownerId = ""
@@ -405,6 +414,7 @@ class tableMetadata: Object, NCUserBaseUrl {
let shareType = List<Int>()
@objc dynamic var size: Int64 = 0
@objc dynamic var status: Int = 0
+ @objc dynamic var subline: String?
@objc dynamic var trashbinFileName = ""
@objc dynamic var trashbinOriginalLocation = ""
@objc dynamic var trashbinDeletionTime = NSDate()
diff --git a/iOSClient/Data/NCManageDatabase+Account.swift b/iOSClient/Data/NCManageDatabase+Account.swift
index 7b5574ea2..c18fc3e68 100644
--- a/iOSClient/Data/NCManageDatabase+Account.swift
+++ b/iOSClient/Data/NCManageDatabase+Account.swift
@@ -373,62 +373,6 @@ extension NCManageDatabase {
return tableAccount.init(value: returnAccount)
}
- /*
- #if !EXTENSION
- @objc func setAccountHCFeatures(_ features: HCFeatures) -> tableAccount? {
-
- let realm = try! Realm()
-
- var returnAccount = tableAccount()
-
- do {
- guard let account = self.getAccountActive() else {
- return nil
- }
-
- try realm.write {
-
- guard let result = realm.objects(tableAccount.self).filter("account == %@", account.account).first else {
- return
- }
-
- result.hcIsTrial = features.isTrial
- result.hcTrialExpired = features.trialExpired
- result.hcTrialRemainingSec = features.trialRemainingSec
- if features.trialEndTime > 0 {
- result.hcTrialEndTime = Date(timeIntervalSince1970: features.trialEndTime) as NSDate
- } else {
- result.hcTrialEndTime = nil
- }
-
- result.hcAccountRemoveExpired = features.accountRemoveExpired
- result.hcAccountRemoveRemainingSec = features.accountRemoveRemainingSec
- if features.accountRemoveTime > 0 {
- result.hcAccountRemoveTime = Date(timeIntervalSince1970: features.accountRemoveTime) as NSDate
- } else {
- result.hcAccountRemoveTime = nil
- }
-
- result.hcNextGroupExpirationGroup = features.nextGroupExpirationGroup
- result.hcNextGroupExpirationGroupExpired = features.nextGroupExpirationGroupExpired
- if features.nextGroupExpirationExpiresTime > 0 {
- result.hcNextGroupExpirationExpiresTime = Date(timeIntervalSince1970: features.nextGroupExpirationExpiresTime) as NSDate
- } else {
- result.hcNextGroupExpirationExpiresTime = nil
- }
- result.hcNextGroupExpirationExpires = features.nextGroupExpirationExpires
-
- returnAccount = result
- }
- } catch let error {
- print("[LOG] Could not write to database: ", error)
- }
-
- return tableAccount.init(value: returnAccount)
- }
- #endif
- */
-
@objc func setAccountMediaPath(_ path: String, account: String) {
let realm = try! Realm()
@@ -482,20 +426,4 @@ extension NCManageDatabase {
NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
}
}
-
- @objc func setAccountColorFiles(lightColorBackground: String, darkColorBackground: String) {
-
- let realm = try! Realm()
-
- do {
- try realm.safeWrite {
- if let result = realm.objects(tableAccount.self).filter("active == true").first {
- result.lightColorBackground = lightColorBackground
- result.darkColorBackground = darkColorBackground
- }
- }
- } catch let error {
- NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
- }
- }
}
diff --git a/iOSClient/Data/NCManageDatabase+Activity.swift b/iOSClient/Data/NCManageDatabase+Activity.swift
index 3e84bf4df..354b953f2 100644
--- a/iOSClient/Data/NCManageDatabase+Activity.swift
+++ b/iOSClient/Data/NCManageDatabase+Activity.swift
@@ -146,9 +146,17 @@ extension NCManageDatabase {
let realm = try! Realm()
- let results = realm.objects(tableActivitySubjectRich.self).filter("account == %@ && idActivity == %d && id == %@", account, idActivity, id).first
+ let results = realm.objects(tableActivitySubjectRich.self).filter("account == %@ && idActivity == %d && id == %@", account, idActivity, id)
+ var activitySubjectRich = results.first
+ if results.count == 2 {
+ for result in results {
+ if result.key == "newfile" {
+ activitySubjectRich = result
+ }
+ }
+ }
- return results.map { tableActivitySubjectRich.init(value: $0) }
+ return activitySubjectRich.map { tableActivitySubjectRich.init(value: $0) }
}
@objc func getActivityPreview(account: String, idActivity: Int, orderKeysId: [String]) -> [tableActivityPreview] {
@@ -166,19 +174,14 @@ extension NCManageDatabase {
return results
}
- @objc func updateLatestActivityId(_ activities: [NCCommunicationActivity], account: String) {
+ func updateLatestActivityId(activityFirstKnown: Int, activityLastGiven: Int, account: String) {
let realm = try! Realm()
- let previousRecentId = getLatestActivityId(account: account)
do {
try realm.write {
- guard
- let mostRecentActivityId = activities.map({ $0.idActivity }).max(),
- mostRecentActivityId > previousRecentId
- else { return }
-
let newRecentActivity = tableActivityLatestId()
- newRecentActivity.mostRecentlyLoadedActivityId = mostRecentActivityId
+ newRecentActivity.activityFirstKnown = activityFirstKnown
+ newRecentActivity.activityLastGiven = activityLastGiven
newRecentActivity.account = account
realm.add(newRecentActivity, update: .all)
}
@@ -187,15 +190,10 @@ extension NCManageDatabase {
}
}
- @objc func getLatestActivityId(account: String) -> Int {
+ func getLatestActivityId(account: String) -> tableActivityLatestId? {
let realm = try! Realm()
- guard let maxId = realm.objects(tableActivityLatestId.self)
- .filter("account == %@", account)
- .map({ $0.mostRecentlyLoadedActivityId }).max()
- else { return 0 }
-
- return maxId
+ return realm.objects(tableActivityLatestId.self).filter("account == %@", account).first
}
// MARK: -
diff --git a/iOSClient/Data/NCManageDatabase+Metadata.swift b/iOSClient/Data/NCManageDatabase+Metadata.swift
index 2c115ce6d..c98b0aa17 100644
--- a/iOSClient/Data/NCManageDatabase+Metadata.swift
+++ b/iOSClient/Data/NCManageDatabase+Metadata.swift
@@ -60,6 +60,7 @@ extension NCManageDatabase {
metadata.iconName = file.iconName
metadata.livePhoto = file.livePhoto
metadata.mountType = file.mountType
+ metadata.name = file.name
metadata.note = file.note
metadata.ocId = file.ocId
metadata.ownerId = file.ownerId
@@ -87,8 +88,8 @@ extension NCManageDatabase {
}
metadata.size = file.size
metadata.classFile = file.classFile
- //FIXME: iOS 12.0,* don't detect UTI "text/markdown"
- if metadata.contentType == "text/markdown" && metadata.classFile == NCCommunicationCommon.typeClassFile.unknow.rawValue {
+ //FIXME: iOS 12.0,* don't detect UTI text/markdown, text/x-markdown
+ if (metadata.contentType == "text/markdown" || metadata.contentType == "text/x-markdown") && metadata.classFile == NCCommunicationCommon.typeClassFile.unknow.rawValue {
metadata.classFile = NCCommunicationCommon.typeClassFile.document.rawValue
}
if let date = file.uploadDate {
@@ -131,7 +132,7 @@ extension NCManageDatabase {
var counter: Int = 0
var isEncrypted: Bool = false
- var listServerUrl: [String: Bool] = [:]
+ let listServerUrl = ThreadSafeDictionary<String,Bool>()
var metadataFolder = tableMetadata()
var metadataFolders: [tableMetadata] = []
@@ -163,30 +164,50 @@ extension NCManageDatabase {
completion(metadataFolder, metadataFolders, metadatas)
}
- @objc func createMetadata(account: String, user: String, userId: String, fileName: String, fileNameView: String, ocId: String, serverUrl: String, urlBase: String, url: String, contentType: String, livePhoto: Bool) -> tableMetadata {
+ @objc func createMetadata(account: String, user: String, userId: String, fileName: String, fileNameView: String, ocId: String, serverUrl: String, urlBase: String, url: String, contentType: String, isLivePhoto: Bool = false, isUrl: Bool = false, name: String = NCGlobal.shared.appName, subline: String? = nil, iconName: String? = nil, iconUrl: String? = nil) -> tableMetadata {
let metadata = tableMetadata()
- let resultInternalType = NCCommunicationCommon.shared.getInternalType(fileName: fileName, mimeType: contentType, directory: false)
-
+ if isUrl {
+ metadata.contentType = "text/uri-list"
+ if let iconName = iconName {
+ metadata.iconName = iconName
+ } else {
+ metadata.iconName = NCCommunicationCommon.typeIconFile.url.rawValue
+ }
+ metadata.classFile = NCCommunicationCommon.typeClassFile.url.rawValue
+ } else {
+ let (mimeType, classFile, iconName, _, _, _) = NCCommunicationCommon.shared.getInternalType(fileName: fileName, mimeType: contentType, directory: false)
+ metadata.contentType = mimeType
+ metadata.iconName = iconName
+ metadata.classFile = classFile
+ //FIXME: iOS 12.0,* don't detect UTI text/markdown, text/x-markdown
+ if classFile == NCCommunicationCommon.typeClassFile.unknow.rawValue && (mimeType == "text/x-markdown" || mimeType == "text/markdown") {
+ metadata.iconName = NCCommunicationCommon.typeIconFile.txt.rawValue
+ metadata.classFile = NCCommunicationCommon.typeClassFile.document.rawValue
+ }
+ }
+ if let iconUrl = iconUrl {
+ metadata.iconUrl = iconUrl
+ }
+
let fileName = fileName.trimmingCharacters(in: .whitespacesAndNewlines)
metadata.account = account
metadata.chunk = false
- metadata.contentType = resultInternalType.mimeType
metadata.creationDate = Date() as NSDate
metadata.date = Date() as NSDate
metadata.hasPreview = true
- metadata.iconName = resultInternalType.iconName
metadata.etag = ocId
metadata.ext = (fileName as NSString).pathExtension.lowercased()
metadata.fileName = fileName
metadata.fileNameView = fileName
metadata.fileNameWithoutExt = (fileName as NSString).deletingPathExtension
- metadata.livePhoto = livePhoto
+ metadata.livePhoto = isLivePhoto
+ metadata.name = name
metadata.ocId = ocId
metadata.permissions = "RGDNVW"
metadata.serverUrl = serverUrl
- metadata.classFile = resultInternalType.classFile
+ metadata.subline = subline
metadata.uploadDate = Date() as NSDate
metadata.url = url
metadata.urlBase = urlBase
@@ -200,9 +221,11 @@ extension NCManageDatabase {
return metadata
}
- @objc func addMetadata(_ metadata: tableMetadata) {
+ @discardableResult
+ @objc func addMetadata(_ metadata: tableMetadata) -> tableMetadata? {
let realm = try! Realm()
+ let returnMetadata = tableMetadata.init(value: metadata)
do {
try realm.safeWrite {
@@ -210,7 +233,9 @@ extension NCManageDatabase {
}
} catch let error {
NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+ return nil
}
+ return returnMetadata
}
@objc func addMetadatas(_ metadatas: [tableMetadata]) {
@@ -332,7 +357,7 @@ extension NCManageDatabase {
// update
// Workaround: check lock bc no etag changes if lock runs out in directory
// https://github.com/nextcloud/server/issues/8477
- if result.status == NCGlobal.shared.metadataStatusNormal && (result.etag != metadata.etag || result.fileNameView != metadata.fileNameView || result.date != metadata.date || result.permissions != metadata.permissions || result.hasPreview != metadata.hasPreview || result.note != metadata.note || result.lock != metadata.lock) {
+ if result.status == NCGlobal.shared.metadataStatusNormal && (result.etag != metadata.etag || result.fileNameView != metadata.fileNameView || result.date != metadata.date || result.permissions != metadata.permissions || result.hasPreview != metadata.hasPreview || result.note != metadata.note || result.lock != metadata.lock || result.shareType != metadata.shareType || result.sharePermissionsCloudMesh != metadata.sharePermissionsCloudMesh || result.sharePermissionsCollaborationServices != metadata.sharePermissionsCollaborationServices || result.favorite != metadata.favorite) {
ocIdsUdate.append(metadata.ocId)
realm.add(tableMetadata.init(value: metadata), update: .all)
} else if result.status == NCGlobal.shared.metadataStatusNormal && addCompareLivePhoto && result.livePhoto != metadata.livePhoto {
diff --git a/iOSClient/Data/NCManageDatabase.swift b/iOSClient/Data/NCManageDatabase.swift
index 37f9aa4c7..10459c812 100644
--- a/iOSClient/Data/NCManageDatabase.swift
+++ b/iOSClient/Data/NCManageDatabase.swift
@@ -27,6 +27,7 @@ import RealmSwift
import NCCommunication
import SwiftyJSON
import CoreMedia
+import Photos
class NCManageDatabase: NSObject {
@objc static let shared: NCManageDatabase = {
@@ -37,12 +38,20 @@ class NCManageDatabase: NSObject {
override init() {
let dirGroup = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: NCBrandOptions.shared.capabilitiesGroups)
- let databaseFilePath = dirGroup?.appendingPathComponent(NCGlobal.shared.appDatabaseNextcloud + "/" + NCGlobal.shared.databaseDefault)
+ let databaseFileUrlPath = dirGroup?.appendingPathComponent(NCGlobal.shared.appDatabaseNextcloud + "/" + NCGlobal.shared.databaseDefault)
let bundleUrl: URL = Bundle.main.bundleURL
let bundlePathExtension: String = bundleUrl.pathExtension
let isAppex: Bool = bundlePathExtension == "appex"
+ if let databaseFilePath = databaseFileUrlPath?.path {
+ if FileManager.default.fileExists(atPath: databaseFilePath) {
+ NCCommunicationCommon.shared.writeLog("DATABASE FOUND in " + databaseFilePath)
+ } else {
+ NCCommunicationCommon.shared.writeLog("DATABASE NOT FOUND in " + databaseFilePath)
+ }
+ }
+
// Disable file protection for directory DB
// https://docs.mongodb.com/realm/sdk/ios/examples/configure-and-open-a-realm/#std-label-ios-open-a-local-realm
if let folderPathURL = dirGroup?.appendingPathComponent(NCGlobal.shared.appDatabaseNextcloud) {
@@ -72,7 +81,7 @@ class NCManageDatabase: NSObject {
let configCompact = Realm.Configuration(
- fileURL: databaseFilePath,
+ fileURL: databaseFileUrlPath,
schemaVersion: NCGlobal.shared.databaseSchemaVersion,
migrationBlock: { migration, oldSchemaVersion in
@@ -149,9 +158,17 @@ class NCManageDatabase: NSObject {
}
}
- if oldSchemaVersion < 222 && NCUtility.shared.SYSTEM_VERSION_LESS_THAN(version: "13") {
+ if oldSchemaVersion < 227 {
migration.deleteData(forType: tableMetadata.className())
migration.deleteData(forType: tableDirectory.className())
+ migration.deleteData(forType: tableTrash.className())
+ }
+
+ if oldSchemaVersion < 237 {
+ migration.deleteData(forType: tableActivity.className())
+ migration.deleteData(forType: tableActivityLatestId.className())
+ migration.deleteData(forType: tableActivityPreview.className())
+ migration.deleteData(forType: tableActivitySubjectRich.className())
}
}, shouldCompactOnLaunch: { totalBytes, usedBytes in
@@ -168,12 +185,13 @@ class NCManageDatabase: NSObject {
do {
_ = try Realm(configuration: configCompact)
} catch {
- if let databaseFilePath = databaseFilePath {
+ if let databaseFileUrlPath = databaseFileUrlPath {
do {
#if !EXTENSION
NCContentPresenter.shared.messageNotification("_error_", description: "_database_corrupt_", delay: NCGlobal.shared.dismissAfterSecondLong, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
#endif
- try FileManager.default.removeItem(at: databaseFilePath)
+ NCCommunicationCommon.shared.writeLog("DATABASE CORRUPT: removed")
+ try FileManager.default.removeItem(at: databaseFileUrlPath)
} catch {}
}
}
@@ -186,16 +204,17 @@ class NCManageDatabase: NSObject {
Realm.Configuration.defaultConfiguration = config
}
- // Verify Database, if corrupr remove it
+ // Verify Database, if corrupt remove it
do {
_ = try Realm()
} catch {
- if let databaseFilePath = databaseFilePath {
+ if let databaseFileUrlPath = databaseFileUrlPath {
do {
#if !EXTENSION
NCContentPresenter.shared.messageNotification("_error_", description: "_database_corrupt_", delay: NCGlobal.shared.dismissAfterSecondLong, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
#endif
- try FileManager.default.removeItem(at: databaseFilePath)
+ NCCommunicationCommon.shared.writeLog("DATABASE CORRUPT: removed")
+ try FileManager.default.removeItem(at: databaseFileUrlPath)
} catch {}
}
}
@@ -698,23 +717,6 @@ class NCManageDatabase: NSObject {
return tableDirectory.init(value: directory)
}
- /*
- @objc func addDirectoryRichWorkspace(ocId: String, richWorkspace: String?) {
-
- let realm = try! Realm()
-
- do {
- try realm.safeWrite {
- if let result = realm.objects(tableDirectory.self).filter("ocId == %@", ocId).first {
- result.richWorkspace = richWorkspace
- }
- }
- } catch let error {
- NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
- }
- }
- */
-
@objc func addDirectory(encrypted: Bool, favorite: Bool, ocId: String, fileId: String, etag: String? = nil, permissions: String? = nil, serverUrl: String, account: String) {
let realm = try! Realm()
@@ -864,7 +866,7 @@ class NCManageDatabase: NSObject {
}
@discardableResult
- @objc func setDirectory(richWorkspace: String?, serverUrl: String, account: String) -> tableDirectory? {
+ @objc func setDirectory(serverUrl: String, richWorkspace: String?, account: String) -> tableDirectory? {
let realm = try! Realm()
var result: tableDirectory?
@@ -885,6 +887,28 @@ class NCManageDatabase: NSObject {
}
}
+ @discardableResult
+ @objc func setDirectory(serverUrl: String, colorFolder: String?, account: String) -> tableDirectory? {
+
+ let realm = try! Realm()
+ var result: tableDirectory?
+
+ do {
+ try realm.safeWrite {
+ result = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first
+ result?.colorFolder = colorFolder
+ }
+ } catch let error {
+ NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+ }
+
+ if let result = result {
+ return tableDirectory.init(value: result)
+ } else {
+ return nil
+ }
+ }
+
// MARK: -
// MARK: Table e2e Encryption
@@ -1231,6 +1255,14 @@ class NCManageDatabase: NSObject {
}
}
+ @objc func getTableLocalFile(account: String) -> [tableLocalFile] {
+
+ let realm = try! Realm()
+
+ let results = realm.objects(tableLocalFile.self).filter("account == %@", account)
+ return Array(results.map { tableLocalFile.init(value: $0) })
+ }
+
@objc func getTableLocalFile(predicate: NSPredicate) -> tableLocalFile? {
let realm = try! Realm()
diff --git a/iOSClient/Diagnostics/NCCapabilitiesViewController.swift b/iOSClient/Diagnostics/NCCapabilitiesViewController.swift
index 6078ffa28..7451affac 100644
--- a/iOSClient/Diagnostics/NCCapabilitiesViewController.swift
+++ b/iOSClient/Diagnostics/NCCapabilitiesViewController.swift
@@ -86,66 +86,79 @@ class NCCapabilitiesViewController: UIViewController, UIDocumentInteractionContr
textView.layer.cornerRadius = 15
textView.layer.masksToBounds = true
+ textView.backgroundColor = NCBrandColor.shared.secondarySystemBackground
statusFileSharing.layer.cornerRadius = 12.5
statusFileSharing.layer.borderWidth = 0.5
- statusFileSharing.layer.borderColor = UIColor.gray.cgColor
+ statusFileSharing.layer.borderColor = NCBrandColor.shared.systemGray.cgColor
statusFileSharing.layer.masksToBounds = true
+ statusFileSharing.backgroundColor = NCBrandColor.shared.secondarySystemBackground
statusExternalSite.layer.cornerRadius = 12.5
statusExternalSite.layer.borderWidth = 0.5
- statusExternalSite.layer.borderColor = UIColor.gray.cgColor
+ statusExternalSite.layer.borderColor = NCBrandColor.shared.systemGray.cgColor
statusExternalSite.layer.masksToBounds = true
+ statusExternalSite.backgroundColor = NCBrandColor.shared.secondarySystemBackground
statusEndToEndEncryption.layer.cornerRadius = 12.5
statusEndToEndEncryption.layer.borderWidth = 0.5
- statusEndToEndEncryption.layer.borderColor = UIColor.gray.cgColor
+ statusEndToEndEncryption.layer.borderColor = NCBrandColor.shared.systemGray.cgColor
statusEndToEndEncryption.layer.masksToBounds = true
+ statusEndToEndEncryption.backgroundColor = NCBrandColor.shared.secondarySystemBackground
statusActivity.layer.cornerRadius = 12.5
statusActivity.layer.borderWidth = 0.5
- statusActivity.layer.borderColor = UIColor.gray.cgColor
+ statusActivity.layer.borderColor = NCBrandColor.shared.systemGray.cgColor
statusActivity.layer.masksToBounds = true
+ statusActivity.backgroundColor = NCBrandColor.shared.secondarySystemBackground
statusNotification.layer.cornerRadius = 12.5
statusNotification.layer.borderWidth = 0.5
- statusNotification.layer.borderColor = UIColor.gray.cgColor
+ statusNotification.layer.borderColor = NCBrandColor.shared.systemGray.cgColor
statusNotification.layer.masksToBounds = true
+ statusNotification.backgroundColor = NCBrandColor.shared.secondarySystemBackground
statusDeletedFiles.layer.cornerRadius = 12.5
statusDeletedFiles.layer.borderWidth = 0.5
- statusDeletedFiles.layer.borderColor = UIColor.gray.cgColor
+ statusDeletedFiles.layer.borderColor = NCBrandColor.shared.systemGray.cgColor
statusDeletedFiles.layer.masksToBounds = true
+ statusDeletedFiles.backgroundColor = NCBrandColor.shared.secondarySystemBackground
statusText.layer.cornerRadius = 12.5
statusText.layer.borderWidth = 0.5
- statusText.layer.borderColor = UIColor.gray.cgColor
+ statusText.layer.borderColor = NCBrandColor.shared.systemGray.cgColor
statusText.layer.masksToBounds = true
+ statusText.backgroundColor = NCBrandColor.shared.secondarySystemBackground
statusCollabora.layer.cornerRadius = 12.5
statusCollabora.layer.borderWidth = 0.5
- statusCollabora.layer.borderColor = UIColor.gray.cgColor
+ statusCollabora.layer.borderColor = NCBrandColor.shared.systemGray.cgColor
statusCollabora.layer.masksToBounds = true
+ statusCollabora.backgroundColor = NCBrandColor.shared.secondarySystemBackground
statusOnlyOffice.layer.cornerRadius = 12.5
statusOnlyOffice.layer.borderWidth = 0.5
- statusOnlyOffice.layer.borderColor = UIColor.gray.cgColor
+ statusOnlyOffice.layer.borderColor = NCBrandColor.shared.systemGray.cgColor
statusOnlyOffice.layer.masksToBounds = true
+ statusOnlyOffice.backgroundColor = NCBrandColor.shared.secondarySystemBackground
statusUserStatus.layer.cornerRadius = 12.5
statusUserStatus.layer.borderWidth = 0.5
- statusUserStatus.layer.borderColor = UIColor.gray.cgColor
+ statusUserStatus.layer.borderColor = NCBrandColor.shared.systemGray.cgColor
statusUserStatus.layer.masksToBounds = true
+ statusUserStatus.backgroundColor = NCBrandColor.shared.secondarySystemBackground
statusComments.layer.cornerRadius = 12.5
statusComments.layer.borderWidth = 0.5
- statusComments.layer.borderColor = UIColor.gray.cgColor
+ statusComments.layer.borderColor = NCBrandColor.shared.systemGray.cgColor
statusComments.layer.masksToBounds = true
+ statusComments.backgroundColor = NCBrandColor.shared.secondarySystemBackground
statusLockFile.layer.cornerRadius = 12.5
statusLockFile.layer.borderWidth = 0.5
- statusLockFile.layer.borderColor = UIColor.gray.cgColor
+ statusLockFile.layer.borderColor = NCBrandColor.shared.systemGray.cgColor
statusLockFile.layer.masksToBounds = true
+ statusLockFile.backgroundColor = NCBrandColor.shared.secondarySystemBackground
imageFileSharing.image = UIImage(named: "share")!.image(color: NCBrandColor.shared.gray, size: 50)
imageExternalSite.image = NCUtility.shared.loadImage(named: "network", color: NCBrandColor.shared.gray)
diff --git a/iOSClient/EmptyView/NCEmptyDataSet.swift b/iOSClient/EmptyView/NCEmptyDataSet.swift
index 23b91e475..684be71d5 100644
--- a/iOSClient/EmptyView/NCEmptyDataSet.swift
+++ b/iOSClient/EmptyView/NCEmptyDataSet.swift
@@ -42,6 +42,10 @@ class NCEmptyDataSet: NSObject {
private var fillBackgroundName: String = ""
private var fillBackgroundView = UIImageView()
+ private var centerXAnchor: NSLayoutConstraint?
+ private var centerYAnchor: NSLayoutConstraint?
+
+
init(view: UIView, offset: CGFloat = 0, delegate: NCEmptyDataSetDelegate?) {
super.init()
@@ -63,16 +67,25 @@ class NCEmptyDataSet: NSObject {
emptyView.widthAnchor.constraint(equalToConstant: 350).isActive = true
emptyView.heightAnchor.constraint(equalToConstant: 250).isActive = true
+
if let view = view.superview {
- emptyView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
- emptyView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: offset).isActive = true
+ centerXAnchor = emptyView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
+ centerYAnchor = emptyView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: offset)
} else {
- emptyView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
- emptyView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: offset).isActive = true
+ centerXAnchor = emptyView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
+ centerYAnchor = emptyView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: offset)
}
+
+ centerXAnchor?.isActive = true
+ centerYAnchor?.isActive = true
}
}
+ func setOffset(_ offset: CGFloat) {
+
+ centerYAnchor?.constant = offset
+ }
+
func numberOfItemsInSection(_ num: Int, section: Int) {
if section == 0 {
diff --git a/iOSClient/Extensions/Array+Extensions.swift b/iOSClient/Extensions/Array+Extensions.swift
new file mode 100644
index 000000000..1b6a9790a
--- /dev/null
+++ b/iOSClient/Extensions/Array+Extensions.swift
@@ -0,0 +1,41 @@
+//
+// Array+Extensions.swift
+// Nextcloud
+//
+// Created by Marino Faggiana on 16/08/22.
+// Copyright © 2022 Marino Faggiana. All rights reserved.
+//
+// Author Marino Faggiana <marino.faggiana@nextcloud.com>
+// Found in Internet
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+import Foundation
+
+//https://stackoverflow.com/questions/33861036/unique-objects-inside-a-array-swift/45023247#45023247
+extension Array {
+ func unique<T: Hashable>(map: ((Element) -> (T))) -> [Element] {
+ var set = Set<T>() // the unique list kept in a Set for fast retrieval
+ var arrayOrdered = [Element]() // keeping the unique list of elements but ordered
+ for value in self {
+ if !set.contains(map(value)) {
+ set.insert(map(value))
+ arrayOrdered.append(value)
+ }
+ }
+
+ return arrayOrdered
+ }
+}
diff --git a/iOSClient/Extensions/String+Extensions.swift b/iOSClient/Extensions/String+Extensions.swift
index f30751ed7..4e0fa5131 100644
--- a/iOSClient/Extensions/String+Extensions.swift
+++ b/iOSClient/Extensions/String+Extensions.swift
@@ -70,3 +70,7 @@ extension String {
return digestData.map { String(format: "%02hhx", $0) }.joined()
}
}
+
+extension StringProtocol {
+ var firstUppercased: String { lowercased().prefix(1).uppercased() + dropFirst() }
+}
diff --git a/iOSClient/Extensions/UIImage+Extensions.swift b/iOSClient/Extensions/UIImage+Extensions.swift
index c790eb66e..fda843b38 100644
--- a/iOSClient/Extensions/UIImage+Extensions.swift
+++ b/iOSClient/Extensions/UIImage+Extensions.swift
@@ -227,4 +227,17 @@ extension UIImage {
return newImage
}
+
+ func colorizeFolder(metadata: tableMetadata, tableDirectory: tableDirectory? = nil) -> UIImage {
+ let serverUrl = metadata.serverUrl + "/" + metadata.fileName
+ var image = self
+ if let tableDirectory = tableDirectory {
+ if let hex = tableDirectory.colorFolder, let color = UIColor(hex: hex) {
+ image = self.imageColor(color)
+ }
+ } else if let tableDirectory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, serverUrl)), let hex = tableDirectory.colorFolder, let color = UIColor(hex: hex) {
+ image = self.imageColor(color)
+ }
+ return image
+ }
}
diff --git a/iOSClient/Extensions/UINavigationController+Extension.swift b/iOSClient/Extensions/UINavigationController+Extension.swift
new file mode 100644
index 000000000..e0e987df6
--- /dev/null
+++ b/iOSClient/Extensions/UINavigationController+Extension.swift
@@ -0,0 +1,32 @@
+//
+// UINavigationController+Extension.swift
+// Nextcloud
+//
+// Created by Marino Faggiana on 02/08/2022.
+// Copyright © 2022 Marino Faggiana. All rights reserved.
+//
+// Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+import Foundation
+
+extension UINavigationController {
+
+ // https://stackoverflow.com/questions/6131205/how-to-find-topmost-view-controller-on-ios
+ override func topMostViewController() -> UIViewController {
+ return self.visibleViewController!.topMostViewController()
+ }
+}
diff --git a/iOSClient/Extensions/UITabBarController+Extension.swift b/iOSClient/Extensions/UITabBarController+Extension.swift
new file mode 100644
index 000000000..66e57c535
--- /dev/null
+++ b/iOSClient/Extensions/UITabBarController+Extension.swift
@@ -0,0 +1,32 @@
+//
+// UITabBarController+Extension.swift
+// Nextcloud
+//
+// Created by Marino Faggiana on 02/08/2022.
+// Copyright © 2022 Marino Faggiana. All rights reserved.
+//
+// Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+import Foundation
+
+extension UITabBarController {
+
+ // https://stackoverflow.com/questions/6131205/how-to-find-topmost-view-controller-on-ios
+ override func topMostViewController() -> UIViewController {
+ return self.selectedViewController!.topMostViewController()
+ }
+}
diff --git a/iOSClient/Extensions/UIViewController+Extension.swift b/iOSClient/Extensions/UIViewController+Extension.swift
new file mode 100644
index 000000000..172dccb03
--- /dev/null
+++ b/iOSClient/Extensions/UIViewController+Extension.swift
@@ -0,0 +1,64 @@
+//
+// UIViewController+Extension.swift
+// Nextcloud
+//
+// Created by Marino Faggiana on 02/08/2022.
+// Copyright © 2022 Marino Faggiana. All rights reserved.
+//
+// Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+import Foundation
+
+extension UIViewController {
+
+ // https://stackoverflow.com/questions/6131205/how-to-find-topmost-view-controller-on-ios
+ @objc func topMostViewController() -> UIViewController {
+ // Handling Modal views
+ if let presentedViewController = self.presentedViewController {
+ return presentedViewController.topMostViewController()
+ }
+ // Handling UIViewController's added as subviews to some other views.
+ else {
+ for view in self.view.subviews {
+ // Key property which most of us are unaware of / rarely use.
+ if let subViewController = view.next {
+ if subViewController is UIViewController {
+ if let viewController = subViewController as? UIViewController {
+ return viewController.topMostViewController()
+ }
+ }
+ }
+ }
+ return self
+ }
+ }
+
+ // https://stackoverflow.com/questions/23620276/how-to-check-if-a-view-controller-is-presented-modally-or-pushed-on-a-navigation
+ var isModal: Bool {
+ if let index = navigationController?.viewControllers.firstIndex(of: self), index > 0 {
+ return false
+ } else if presentingViewController != nil {
+ return true
+ } else if navigationController?.presentingViewController?.presentedViewController == navigationController {
+ return true
+ } else if tabBarController?.presentingViewController is UITabBarController {
+ return true
+ } else {
+ return false
+ }
+ }
+}
diff --git a/iOSClient/Favorites/NCFavorite.swift b/iOSClient/Favorites/NCFavorite.swift
index a94fc6ba4..448caf426 100644
--- a/iOSClient/Favorites/NCFavorite.swift
+++ b/iOSClient/Favorites/NCFavorite.swift
@@ -33,7 +33,10 @@ class NCFavorite: NCCollectionViewCommon {
titleCurrentFolder = NSLocalizedString("_favorites_", comment: "")
layoutKey = NCGlobal.shared.layoutViewFavorite
- enableSearchBar = true
+ enableSearchBar = false
+ headerMenuButtonsCommand = false
+ headerMenuButtonsView = true
+ headerRichWorkspaceDisable = true
emptyImage = UIImage(named: "star.fill")?.image(color: NCBrandColor.shared.yellowFavorite, size: UIScreen.main.bounds.width)
emptyTitle = "_favorite_no_files_"
emptyDescription = "_tutorial_favorite_view_"
@@ -41,21 +44,28 @@ class NCFavorite: NCCollectionViewCommon {
// MARK: - DataSource + NC Endpoint
- override func reloadDataSource() {
+ override func reloadDataSource(forced: Bool = true) {
super.reloadDataSource()
DispatchQueue.global().async {
+ var metadatas: [tableMetadata] = []
- if !self.isSearching {
-
- if self.serverUrl == "" {
- self.metadatasSource = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND favorite == true", self.appDelegate.account))
- } else {
- self.metadatasSource = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
- }
+ if self.serverUrl.isEmpty {
+ metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND favorite == true", self.appDelegate.account))
+ } else {
+ metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
}
- self.dataSource = NCDataSource(metadatasSource: self.metadatasSource, sort: self.layoutForView?.sort, ascending: self.layoutForView?.ascending, directoryOnTop: self.layoutForView?.directoryOnTop, favoriteOnTop: true, filterLivePhoto: true)
+ self.dataSource = NCDataSource(metadatas: metadatas,
+ account: self.appDelegate.account,
+ sort: self.layoutForView?.sort,
+ ascending: self.layoutForView?.ascending,
+ directoryOnTop: self.layoutForView?.directoryOnTop,
+ favoriteOnTop: true,
+ filterLivePhoto: true,
+ groupByField: self.groupByField,
+ providers: self.providers,
+ searchResults: self.searchResults)
DispatchQueue.main.async {
self.refreshControl.endRefreshing()
@@ -67,15 +77,10 @@ class NCFavorite: NCCollectionViewCommon {
override func reloadDataSourceNetwork(forced: Bool = false) {
super.reloadDataSourceNetwork(forced: forced)
- if isSearching {
- networkSearch()
- return
- }
-
isReloadDataSourceNetworkInProgress = true
collectionView?.reloadData()
- if serverUrl == "" {
+ if serverUrl.isEmpty {
NCNetworking.shared.listingFavoritescompletion(selector: NCGlobal.shared.selectorListingFavorite) { _, _, errorCode, errorDescription in
if errorCode != 0 {
diff --git a/iOSClient/FileViewInFolder/NCFileViewInFolder.storyboard b/iOSClient/FileViewInFolder/NCFileViewInFolder.storyboard
deleted file mode 100644
index 95d7bd36e..000000000
--- a/iOSClient/FileViewInFolder/NCFileViewInFolder.storyboard
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="EFX-fO-Oip">
- <device id="retina5_9" orientation="portrait" appearance="light"/>
- <dependencies>
- <deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17125"/>
- <capability name="Safe area layout guides" minToolsVersion="9.0"/>
- <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
- </dependencies>
- <scenes>
- <!--File View In Folder-->
- <scene sceneID="X4W-6b-l7s">
- <objects>
- <viewController storyboardIdentifier="NCFileViewInFolder.storyboard" extendedLayoutIncludesOpaqueBars="YES" id="EFX-fO-Oip" customClass="NCFileViewInFolder" customModule="Nextcloud" customModuleProvider="target" sceneMemberID="viewController">
- <view key="view" contentMode="scaleToFill" id="QEs-gO-Cmp">
- <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
- <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
- <subviews>
- <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="Zaz-Cl-qpZ">
- <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
- <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- <collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="0.0" minimumInteritemSpacing="0.0" id="fF1-wd-0xN">
- <size key="itemSize" width="0.0" height="0.0"/>
- <size key="headerReferenceSize" width="0.0" height="0.0"/>
- <size key="footerReferenceSize" width="0.0" height="0.0"/>
- <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
- </collectionViewFlowLayout>
- <cells/>
- <connections>
- <outlet property="dataSource" destination="EFX-fO-Oip" id="2On-qP-zuG"/>
- <outlet property="delegate" destination="EFX-fO-Oip" id="s3n-CL-8X2"/>
- </connections>
- </collectionView>
- </subviews>
- <viewLayoutGuide key="safeArea" id="Meh-VD-wWh"/>
- <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- <constraints>
- <constraint firstItem="Zaz-Cl-qpZ" firstAttribute="leading" secondItem="Meh-VD-wWh" secondAttribute="leading" id="1bp-sm-u0X"/>
- <constraint firstItem="Meh-VD-wWh" firstAttribute="trailing" secondItem="Zaz-Cl-qpZ" secondAttribute="trailing" id="aNd-UL-hmu"/>
- <constraint firstItem="Meh-VD-wWh" firstAttribute="bottom" secondItem="Zaz-Cl-qpZ" secondAttribute="bottom" constant="-34" id="aNr-tf-2AH"/>
- <constraint firstItem="Zaz-Cl-qpZ" firstAttribute="top" secondItem="QEs-gO-Cmp" secondAttribute="top" id="tji-wt-R7s"/>
- </constraints>
- </view>
- <connections>
- <outlet property="collectionView" destination="Zaz-Cl-qpZ" id="8oA-Gx-z7T"/>
- </connections>
- </viewController>
- <placeholder placeholderIdentifier="IBFirstResponder" id="JJ0-Le-6eT" userLabel="First Responder" sceneMemberID="firstResponder"/>
- </objects>
- <point key="canvasLocation" x="256.80000000000001" y="228.32512315270938"/>
- </scene>
- </scenes>
-</document>
diff --git a/iOSClient/FileViewInFolder/NCFileViewInFolder.swift b/iOSClient/FileViewInFolder/NCFileViewInFolder.swift
deleted file mode 100644
index ac6f63af8..000000000
--- a/iOSClient/FileViewInFolder/NCFileViewInFolder.swift
+++ /dev/null
@@ -1,152 +0,0 @@
-//
-// NCFileViewInFolder.swift
-// Nextcloud
-//
-// Created by Marino Faggiana on 01/10/2020.
-// Copyright © 2020 Marino Faggiana. All rights reserved.
-//
-// Author Marino Faggiana <marino.faggiana@nextcloud.com>
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-import UIKit
-import NCCommunication
-
-class NCFileViewInFolder: NCCollectionViewCommon {
-
- internal var fileName: String?
-
- // MARK: - View Life Cycle
-
- required init?(coder aDecoder: NSCoder) {
- super.init(coder: aDecoder)
-
- appDelegate.activeFileViewInFolder = self
- titleCurrentFolder = NCBrandOptions.shared.brand
- layoutKey = NCGlobal.shared.layoutViewViewInFolder
- enableSearchBar = false
- emptyImage = UIImage(named: "folder")?.image(color: NCBrandColor.shared.brandElement, size: UIScreen.main.bounds.width)
- emptyTitle = "_files_no_files_"
- emptyDescription = "_no_file_pull_down_"
- }
-
- override func viewWillAppear(_ animated: Bool) {
- super.viewWillAppear(animated)
-
- appDelegate.activeViewController = self
-
- if serverUrl == NCUtilityFileSystem.shared.getHomeServer(account: appDelegate.account) {
- self.navigationItem.title = NCBrandOptions.shared.brand
- } else {
- self.navigationItem.title = (serverUrl as NSString).lastPathComponent
- }
-
- presentationController?.delegate = self
-
- layoutForView = NCUtility.shared.getLayoutForView(key: layoutKey, serverUrl: serverUrl)
- gridLayout.itemForLine = CGFloat(layoutForView?.itemForLine ?? 3)
-
- if layoutForView?.layout == NCGlobal.shared.layoutList {
- collectionView?.collectionViewLayout = listLayout
- } else {
- collectionView?.collectionViewLayout = gridLayout
- }
-
- self.navigationItem.leftBarButtonItem = nil
- self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_close_", comment: ""), style: .plain, target: self, action: #selector(tapClose(sender:)))
- }
-
- // MARK: - TAP EVENT
-
- @objc func tapClose(sender: Any) {
- dismiss(animated: true)
- }
-
- // MARK: - DataSource + NC Endpoint
-
- override func reloadDataSource() {
- super.reloadDataSource()
-
- DispatchQueue.global().async {
-
- if !self.isSearching {
- self.metadatasSource = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
- if self.metadataFolder == nil {
- self.metadataFolder = NCManageDatabase.shared.getMetadataFolder(account: self.appDelegate.account, urlBase: self.appDelegate.urlBase, serverUrl: self.serverUrl)
- }
- }
-
- self.dataSource = NCDataSource(metadatasSource: self.metadatasSource, sort: self.layoutForView?.sort, ascending: self.layoutForView?.ascending, directoryOnTop: self.layoutForView?.directoryOnTop, favoriteOnTop: true, filterLivePhoto: true)
-
- DispatchQueue.main.async {
-
- self.refreshControl.endRefreshing()
- self.collectionView.reloadData()
-
- // Blink file
- if self.fileName != nil {
- if let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", self.appDelegate.account, self.serverUrl, self.fileName!)) {
- if let row = self.dataSource.getIndexMetadata(ocId: metadata.ocId) {
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
- UIView.animate(withDuration: 0.3) {
- self.collectionView.scrollToItem(at: IndexPath(row: row, section: 0), at: .centeredVertically, animated: false)
- } completion: { _ in
- if let cell = self.collectionView.cellForItem(at: IndexPath(row: row, section: 0)) {
- cell.backgroundColor = .darkGray
- UIView.animate(withDuration: 2) {
- cell.backgroundColor = .clear
- self.fileName = nil
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
- override func reloadDataSourceNetwork(forced: Bool = false) {
- super.reloadDataSourceNetwork(forced: forced)
-
- if isSearching {
- networkSearch()
- return
- }
-
- isReloadDataSourceNetworkInProgress = true
- collectionView?.reloadData()
-
- networkReadFolder(forced: forced) { tableDirectory, metadatas, _, _, errorCode, _ in
- if errorCode == 0 {
- for metadata in metadatas ?? [] {
- if !metadata.directory {
- if NCManageDatabase.shared.isDownloadMetadata(metadata, download: false) {
- NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorDownloadFile)
- }
- }
- }
- }
-
- DispatchQueue.main.async {
- self.refreshControl.endRefreshing()
- self.isReloadDataSourceNetworkInProgress = false
- self.richWorkspaceText = tableDirectory?.richWorkspace
- self.reloadDataSource()
- }
- }
- }
-}
diff --git a/iOSClient/Files/NCFiles.swift b/iOSClient/Files/NCFiles.swift
index f90c7f7f5..07cfab334 100644
--- a/iOSClient/Files/NCFiles.swift
+++ b/iOSClient/Files/NCFiles.swift
@@ -27,16 +27,19 @@ import NCCommunication
class NCFiles: NCCollectionViewCommon {
internal var isRoot: Bool = true
+ internal var fileNameBlink: String?
// MARK: - View Life Cycle
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
- appDelegate.activeFiles = self
titleCurrentFolder = NCBrandOptions.shared.brand
layoutKey = NCGlobal.shared.layoutViewFiles
enableSearchBar = true
+ headerMenuButtonsCommand = true
+ headerMenuButtonsView = true
+ headerRichWorkspaceDisable = false
emptyImage = UIImage(named: "folder")?.image(color: NCBrandColor.shared.brandElement, size: UIScreen.main.bounds.width)
emptyTitle = "_files_no_files_"
emptyDescription = "_no_file_pull_down_"
@@ -48,76 +51,127 @@ class NCFiles: NCCollectionViewCommon {
serverUrl = NCUtilityFileSystem.shared.getHomeServer(account: appDelegate.account)
titleCurrentFolder = getNavigationTitle()
}
-
super.viewWillAppear(animated)
}
+ override func viewWillDisappear(_ animated: Bool) {
+ super.viewWillDisappear(animated)
+
+ fileNameBlink = nil
+ }
+
// MARK: - NotificationCenter
- override func initialize() {
+ override func initialize(_ notification: NSNotification) {
if isRoot {
serverUrl = NCUtilityFileSystem.shared.getHomeServer(account: appDelegate.account)
titleCurrentFolder = getNavigationTitle()
- reloadDataSourceNetwork(forced: true)
+ }
+ super.initialize(notification)
+
+ if let userInfo = notification.userInfo as NSDictionary?, userInfo["atStart"] as? Int == 1 {
+ return
}
- super.initialize()
+ reloadDataSource(forced: false)
+ reloadDataSourceNetwork()
}
// MARK: - DataSource + NC Endpoint
+ //
+ // forced: do no make the etag of directory test (default)
+ //
- override func reloadDataSource() {
+ override func reloadDataSource(forced: Bool = true) {
super.reloadDataSource()
- DispatchQueue.global(qos: .background).async {
+ DispatchQueue.main.async { self.refreshControl.endRefreshing() }
+ DispatchQueue.global().async {
+ guard !self.isSearching, !self.appDelegate.account.isEmpty, !self.appDelegate.urlBase.isEmpty, !self.serverUrl.isEmpty else { return }
- if !self.isSearching && self.appDelegate.account != "" && self.appDelegate.urlBase != "" {
- self.metadatasSource = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
- if self.metadataFolder == nil {
- self.metadataFolder = NCManageDatabase.shared.getMetadataFolder(account: self.appDelegate.account, urlBase: self.appDelegate.urlBase, serverUrl: self.serverUrl)
- }
+ let metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
+ if self.metadataFolder == nil {
+ self.metadataFolder = NCManageDatabase.shared.getMetadataFolder(account: self.appDelegate.account, urlBase: self.appDelegate.urlBase, serverUrl: self.serverUrl)
+ }
+ let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
+ let metadataTransfer = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "status != %i AND serverUrl == %@", NCGlobal.shared.metadataStatusNormal, self.serverUrl))
+ self.richWorkspaceText = directory?.richWorkspace
+
+ // FORCED false: test the directory.etag
+ if !forced, let directory = directory, directory.etag == self.dataSource.directory?.etag, metadataTransfer == nil, self.fileNameBlink == nil {
+ return
}
- self.dataSource = NCDataSource(metadatasSource: self.metadatasSource, sort: self.layoutForView?.sort, ascending: self.layoutForView?.ascending, directoryOnTop: self.layoutForView?.directoryOnTop, favoriteOnTop: true, filterLivePhoto: true)
+ self.dataSource = NCDataSource(
+ metadatas: metadatas,
+ account: self.appDelegate.account,
+ directory: directory,
+ sort: self.layoutForView?.sort,
+ ascending: self.layoutForView?.ascending,
+ directoryOnTop: self.layoutForView?.directoryOnTop,
+ favoriteOnTop: true,
+ filterLivePhoto: true,
+ groupByField: self.groupByField,
+ providers: self.providers,
+ searchResults: self.searchResults)
- DispatchQueue.main.async { [weak self] in
- self?.refreshControl.endRefreshing()
- self?.collectionView.reloadData()
+ DispatchQueue.main.async {
+ self.collectionView.reloadData()
+ if !self.dataSource.metadatas.isEmpty {
+ self.blinkCell(fileName: self.fileNameBlink)
+ self.fileNameBlink = nil
+ }
}
}
}
- override func reloadDataSourceNetwork(forced: Bool = false) {
- super.reloadDataSourceNetwork(forced: forced)
-
- if isSearching {
+ override func reloadDataSourceNetwork(forced: Bool = false) { super.reloadDataSourceNetwork(forced: forced)
+ guard !isSearching else {
networkSearch()
return
}
-
isReloadDataSourceNetworkInProgress = true
collectionView?.reloadData()
networkReadFolder(forced: forced) { tableDirectory, metadatas, metadatasUpdate, metadatasDelete, errorCode, _ in
if errorCode == 0 {
for metadata in metadatas ?? [] {
- if !metadata.directory {
- if NCManageDatabase.shared.isDownloadMetadata(metadata, download: false) {
- NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorDownloadFile)
- }
+ if !metadata.directory, NCManageDatabase.shared.isDownloadMetadata(metadata, download: false) {
+ NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorDownloadFile)
}
}
}
- DispatchQueue.main.async {
- self.refreshControl.endRefreshing()
- self.isReloadDataSourceNetworkInProgress = false
- self.richWorkspaceText = tableDirectory?.richWorkspace
- if metadatasUpdate?.count ?? 0 > 0 || metadatasDelete?.count ?? 0 > 0 || forced {
- self.reloadDataSource()
- } else {
- self.collectionView?.reloadData()
+ self.isReloadDataSourceNetworkInProgress = false
+ self.richWorkspaceText = tableDirectory?.richWorkspace
+
+ if metadatasUpdate?.count ?? 0 > 0 || metadatasDelete?.count ?? 0 > 0 || forced {
+ self.reloadDataSource()
+ } else if self.dataSource.getMetadataSourceForAllSections().isEmpty {
+ DispatchQueue.main.async {
+ self.collectionView.reloadData()
+ }
+ }
+ }
+ }
+
+ func blinkCell(fileName: String?) {
+
+ if let fileName = fileName, let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", self.appDelegate.account, self.serverUrl, fileName)) {
+ let (indexPath, _) = self.dataSource.getIndexPathMetadata(ocId: metadata.ocId)
+ if let indexPath = indexPath {
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
+ UIView.animate(withDuration: 0.3) {
+ self.collectionView.scrollToItem(at: indexPath, at: .centeredVertically, animated: false)
+ } completion: { _ in
+ if let cell = self.collectionView.cellForItem(at: indexPath) {
+ cell.backgroundColor = .darkGray
+ UIView.animate(withDuration: 2) {
+ cell.backgroundColor = .clear
+ }
+ }
+ }
}
}
}
diff --git a/iOSClient/Images.xcassets/buttonAddFolder.imageset/Contents.json b/iOSClient/Images.xcassets/buttonAddFolder.imageset/Contents.json
new file mode 100644
index 000000000..a039207ac
--- /dev/null
+++ b/iOSClient/Images.xcassets/buttonAddFolder.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "filename" : "icons8-add-folder-24(@1x).png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "filename" : "icons8-add-folder-48(@2x)-1.png",
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "filename" : "icons8-add-folder-72(@3x).png",
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/iOSClient/Images.xcassets/buttonAddFolder.imageset/icons8-add-folder-24(@1x).png b/iOSClient/Images.xcassets/buttonAddFolder.imageset/icons8-add-folder-24(@1x).png
new file mode 100644
index 000000000..0328885ac
--- /dev/null
+++ b/iOSClient/Images.xcassets/buttonAddFolder.imageset/icons8-add-folder-24(@1x).png
Binary files differ
diff --git a/iOSClient/Images.xcassets/buttonAddFolder.imageset/icons8-add-folder-48(@2x)-1.png b/iOSClient/Images.xcassets/buttonAddFolder.imageset/icons8-add-folder-48(@2x)-1.png
new file mode 100644
index 000000000..2f05bfd73
--- /dev/null
+++ b/iOSClient/Images.xcassets/buttonAddFolder.imageset/icons8-add-folder-48(@2x)-1.png
Binary files differ
diff --git a/iOSClient/Images.xcassets/buttonAddFolder.imageset/icons8-add-folder-72(@3x).png b/iOSClient/Images.xcassets/buttonAddFolder.imageset/icons8-add-folder-72(@3x).png
new file mode 100644
index 000000000..74ffa2d03
--- /dev/null
+++ b/iOSClient/Images.xcassets/buttonAddFolder.imageset/icons8-add-folder-72(@3x).png
Binary files differ
diff --git a/iOSClient/Images.xcassets/buttonAddImage.imageset/Contents.json b/iOSClient/Images.xcassets/buttonAddImage.imageset/Contents.json
new file mode 100644
index 000000000..cc66bc8da
--- /dev/null
+++ b/iOSClient/Images.xcassets/buttonAddImage.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "filename" : "icons8-image-upload-24(@1x).png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "filename" : "icons8-image-upload-48(@2x).png",
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "filename" : "icons8-image-upload-72(@3x).png",
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image-upload-24(@1x).png b/iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image-upload-24(@1x).png
new file mode 100644
index 000000000..0250e8868
--- /dev/null
+++ b/iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image-upload-24(@1x).png
Binary files differ
diff --git a/iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image-upload-48(@2x).png b/iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image-upload-48(@2x).png
new file mode 100644
index 000000000..bafea055b
--- /dev/null
+++ b/iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image-upload-48(@2x).png
Binary files differ
diff --git a/iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image-upload-72(@3x).png b/iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image-upload-72(@3x).png
new file mode 100644
index 000000000..4a60a404a
--- /dev/null
+++ b/iOSClient/Images.xcassets/buttonAddImage.imageset/icons8-image-upload-72(@3x).png
Binary files differ
diff --git a/iOSClient/Images.xcassets/buttonAddScan.imageset/Contents.json b/iOSClient/Images.xcassets/buttonAddScan.imageset/Contents.json
new file mode 100644
index 000000000..899bf6cbe
--- /dev/null
+++ b/iOSClient/Images.xcassets/buttonAddScan.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "filename" : "icons8-scan-24(@1x).png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "filename" : "icons8-scan-48(@2x).png",
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "filename" : "icons8-scan-72(@3x).png",
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan-24(@1x).png b/iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan-24(@1x).png
new file mode 100644
index 000000000..eb6211df7
--- /dev/null
+++ b/iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan-24(@1x).png
Binary files differ
diff --git a/iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan-48(@2x).png b/iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan-48(@2x).png
new file mode 100644
index 000000000..866cc7d77
--- /dev/null
+++ b/iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan-48(@2x).png
Binary files differ
diff --git a/iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan-72(@3x).png b/iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan-72(@3x).png
new file mode 100644
index 000000000..16d88895c
--- /dev/null
+++ b/iOSClient/Images.xcassets/buttonAddScan.imageset/icons8-scan-72(@3x).png
Binary files differ
diff --git a/iOSClient/Images.xcassets/icon-calendar.imageset/Contents.json b/iOSClient/Images.xcassets/icon-calendar.imageset/Contents.json
new file mode 100644
index 000000000..08e460fdf
--- /dev/null
+++ b/iOSClient/Images.xcassets/icon-calendar.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images" : [
+ {
+ "filename" : "icons8-calendario.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/iOSClient/Images.xcassets/icon-calendar.imageset/icons8-calendario.svg b/iOSClient/Images.xcassets/icon-calendar.imageset/icons8-calendario.svg
new file mode 100644
index 000000000..8146bc2cf
--- /dev/null
+++ b/iOSClient/Images.xcassets/icon-calendar.imageset/icons8-calendario.svg
@@ -0,0 +1 @@
+<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="50px" height="50px"><path d="M 12 0 C 10.90625 0 10 0.90625 10 2 L 10 4 L 4 4 C 3.476563 4 2.945313 4.191406 2.570313 4.570313 C 2.191406 4.945313 2 5.476563 2 6 L 2 46 C 2 46.523438 2.191406 47.054688 2.570313 47.433594 C 2.945313 47.808594 3.476563 48 4 48 L 46 48 C 46.523438 48 47.054688 47.808594 47.433594 47.433594 C 47.808594 47.054688 48 46.523438 48 46 L 48 6 C 48 5.476563 47.808594 4.945313 47.433594 4.570313 C 47.054688 4.191406 46.523438 4 46 4 L 40 4 L 40 2 C 40 0.90625 39.09375 0 38 0 L 36 0 C 34.90625 0 34 0.90625 34 2 L 34 4 L 16 4 L 16 2 C 16 0.90625 15.09375 0 14 0 Z M 12 2 L 14 2 L 14 8 L 12 8 Z M 36 2 L 38 2 L 38 8 L 36 8 Z M 4 6 L 10 6 L 10 8 C 10 9.09375 10.90625 10 12 10 L 14 10 C 15.09375 10 16 9.09375 16 8 L 16 6 L 34 6 L 34 8 C 34 9.09375 34.90625 10 36 10 L 38 10 C 39.09375 10 40 9.09375 40 8 L 40 6 L 46 6 L 46 13 L 4 13 Z M 4 15 L 46 15 L 46 46 L 4 46 Z M 10 19 L 10 42 L 40 42 L 40 19 Z M 12 21 L 17 21 L 17 26 L 12 26 Z M 19 21 L 24 21 L 24 26 L 19 26 Z M 26 21 L 31 21 L 31 26 L 26 26 Z M 33 21 L 38 21 L 38 26 L 33 26 Z M 12 28 L 17 28 L 17 33 L 12 33 Z M 19 28 L 24 28 L 24 33 L 19 33 Z M 26 28 L 31 28 L 31 33 L 26 33 Z M 33 28 L 38 28 L 38 33 L 33 33 Z M 12 35 L 17 35 L 17 40 L 12 40 Z M 19 35 L 24 35 L 24 40 L 19 40 Z M 26 35 L 31 35 L 31 40 L 26 40 Z M 33 35 L 38 35 L 38 40 L 33 40 Z"/></svg> \ No newline at end of file
diff --git a/iOSClient/Images.xcassets/icon-confirm.imageset/Contents.json b/iOSClient/Images.xcassets/icon-confirm.imageset/Contents.json
new file mode 100644
index 000000000..45660b0ea
--- /dev/null
+++ b/iOSClient/Images.xcassets/icon-confirm.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images" : [
+ {
+ "filename" : "icon-confirm.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/iOSClient/Images.xcassets/icon-confirm.imageset/icon-confirm.svg b/iOSClient/Images.xcassets/icon-confirm.imageset/icon-confirm.svg
new file mode 100644
index 000000000..f9e268e5b
--- /dev/null
+++ b/iOSClient/Images.xcassets/icon-confirm.imageset/icon-confirm.svg
@@ -0,0 +1 @@
+<?xml version="1.0"?><svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24px" height="24px"> <path d="M 15 4 L 15 9 L 2 9 L 2 15 L 15 15 L 15 20 L 23 12 L 15 4 z"/></svg> \ No newline at end of file
diff --git a/iOSClient/Images.xcassets/icon-contacts.imageset/Contents.json b/iOSClient/Images.xcassets/icon-contacts.imageset/Contents.json
new file mode 100644
index 000000000..39392d2d1
--- /dev/null
+++ b/iOSClient/Images.xcassets/icon-contacts.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images" : [
+ {
+ "filename" : "icons8-gruppo-utente-uomo-uomo.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/iOSClient/Images.xcassets/icon-contacts.imageset/icons8-gruppo-utente-uomo-uomo.svg b/iOSClient/Images.xcassets/icon-contacts.imageset/icons8-gruppo-utente-uomo-uomo.svg
new file mode 100644
index 000000000..927eab246
--- /dev/null
+++ b/iOSClient/Images.xcassets/icon-contacts.imageset/icons8-gruppo-utente-uomo-uomo.svg
@@ -0,0 +1 @@
+<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="50px" height="50px"><path d="M 19.875 4.40625 C 15.203125 4.492188 12.21875 6.378906 10.9375 9.3125 C 9.714844 12.105469 9.988281 15.632813 10.875 19.28125 C 10.398438 19.839844 10.019531 20.589844 10.15625 21.71875 C 10.304688 22.949219 10.644531 23.824219 11.125 24.4375 C 11.390625 24.773438 11.738281 24.804688 12.0625 24.96875 C 12.238281 26.015625 12.53125 27.0625 12.96875 27.9375 C 13.21875 28.441406 13.503906 28.90625 13.78125 29.28125 C 13.90625 29.449219 14.085938 29.546875 14.21875 29.6875 C 14.226563 30.921875 14.230469 31.949219 14.125 33.25 C 13.800781 34.035156 13.042969 34.667969 11.8125 35.28125 C 10.542969 35.914063 8.890625 36.5 7.21875 37.21875 C 5.546875 37.9375 3.828125 38.8125 2.46875 40.1875 C 1.109375 41.5625 0.148438 43.449219 0 45.9375 L -0.0625 47 L 40.0625 47 L 40 45.9375 C 39.894531 44.207031 39.40625 42.773438 38.65625 41.59375 L 50.0625 41.59375 L 50 40.53125 C 49.871094 38.402344 49.039063 36.746094 47.875 35.5625 C 46.710938 34.378906 45.253906 33.640625 43.84375 33.03125 C 42.433594 32.421875 41.050781 31.964844 40 31.4375 C 38.984375 30.929688 38.410156 30.417969 38.15625 29.8125 C 38.074219 28.761719 38.054688 27.90625 38.0625 26.90625 C 38.160156 26.796875 38.316406 26.71875 38.40625 26.59375 C 38.644531 26.265625 38.882813 25.867188 39.09375 25.4375 C 39.449219 24.707031 39.691406 23.84375 39.84375 22.96875 C 40.105469 22.824219 40.382813 22.800781 40.59375 22.53125 C 41.023438 21.984375 41.308594 21.242188 41.4375 20.1875 L 41.4375 20.15625 C 41.546875 19.242188 41.25 18.628906 40.875 18.125 C 41.289063 16.769531 41.796875 14.632813 41.625 12.40625 C 41.527344 11.179688 41.21875 9.941406 40.46875 8.90625 C 39.757813 7.921875 38.59375 7.199219 37.125 6.9375 C 36.171875 5.878906 34.667969 5.40625 32.90625 5.40625 C 30.480469 5.449219 28.597656 6.050781 27.21875 7.125 C 26.589844 6.734375 25.855469 6.449219 25.03125 6.28125 C 23.980469 4.917969 22.089844 4.40625 19.90625 4.40625 Z M 19.90625 6.40625 C 19.917969 6.40625 19.925781 6.40625 19.9375 6.40625 C 21.949219 6.414063 23.253906 7.003906 23.625 7.65625 L 23.875 8.0625 L 24.34375 8.125 C 25.734375 8.316406 26.53125 8.878906 27.09375 9.65625 C 27.65625 10.433594 27.96875 11.519531 28.0625 12.71875 C 28.25 15.117188 27.558594 17.910156 27.125 19.21875 L 26.875 20 L 27.5625 20.40625 C 27.519531 20.378906 27.945313 20.667969 27.84375 21.5 C 27.726563 22.480469 27.492188 22.988281 27.3125 23.21875 C 27.132813 23.449219 27.039063 23.4375 27.03125 23.4375 L 26.1875 23.5 L 26.09375 24.3125 C 26 25.179688 25.652344 26.234375 25.25 27.0625 C 25.046875 27.476563 24.839844 27.839844 24.65625 28.09375 C 24.472656 28.347656 24.277344 28.488281 24.375 28.4375 L 23.84375 28.71875 L 23.84375 29.3125 C 23.84375 30.761719 23.785156 31.949219 23.9375 33.625 L 23.9375 33.75 L 24 33.875 C 24.570313 35.410156 25.890625 36.367188 27.34375 37.09375 C 28.796875 37.820313 30.464844 38.355469 32.03125 39.03125 C 33.371094 39.609375 34.597656 40.296875 35.59375 41.15625 C 35.597656 41.160156 35.589844 41.183594 35.59375 41.1875 C 35.640625 41.234375 35.695313 41.277344 35.75 41.3125 C 35.8125 41.386719 35.886719 41.449219 35.96875 41.5 C 35.972656 41.503906 35.996094 41.496094 36 41.5 C 36.03125 41.53125 36.0625 41.5625 36.09375 41.59375 C 36.9375 42.449219 37.46875 43.582031 37.75 45 L 2.25 45 C 2.53125 43.585938 3.058594 42.449219 3.90625 41.59375 C 4.972656 40.515625 6.425781 39.707031 8 39.03125 C 9.574219 38.355469 11.230469 37.820313 12.6875 37.09375 C 14.144531 36.367188 15.492188 35.410156 16.0625 33.875 L 16.125 33.625 C 16.277344 31.949219 16.21875 30.761719 16.21875 29.3125 L 16.21875 28.71875 L 15.6875 28.4375 C 15.777344 28.484375 15.5625 28.347656 15.375 28.09375 C 15.1875 27.839844 14.957031 27.476563 14.75 27.0625 C 14.335938 26.234375 13.996094 25.167969 13.90625 24.3125 L 13.8125 23.5 L 12.96875 23.4375 C 12.960938 23.4375 12.867188 23.449219 12.6875 23.21875 C 12.507813 22.988281 12.273438 22.480469 12.15625 21.5 C 12.058594 20.667969 12.480469 20.378906 12.4375 20.40625 L 13.09375 20 L 12.90625 19.28125 C 11.964844 15.65625 11.800781 12.363281 12.78125 10.125 C 13.757813 7.894531 15.75 6.492188 19.90625 6.40625 Z M 32.90625 7.40625 C 32.917969 7.40625 32.925781 7.40625 32.9375 7.40625 C 34.601563 7.414063 35.640625 7.90625 35.90625 8.375 L 36.15625 8.78125 L 36.625 8.875 C 37.761719 9.03125 38.394531 9.441406 38.84375 10.0625 C 39.292969 10.683594 39.546875 11.570313 39.625 12.5625 C 39.78125 14.546875 39.203125 16.910156 38.84375 18 L 38.59375 18.75 L 39.28125 19.15625 C 39.191406 19.101563 39.546875 19.292969 39.46875 19.9375 C 39.371094 20.746094 39.160156 21.148438 39.03125 21.3125 C 38.902344 21.476563 38.871094 21.441406 38.90625 21.4375 L 38.0625 21.5 L 38 22.3125 C 37.925781 23.015625 37.613281 23.878906 37.28125 24.5625 C 37.113281 24.902344 36.960938 25.203125 36.8125 25.40625 C 36.722656 25.527344 36.660156 25.617188 36.625 25.65625 L 36.59375 25.65625 C 36.589844 25.660156 36.59375 25.6875 36.59375 25.6875 L 36.0625 25.9375 L 36.0625 26.53125 C 36.0625 27.746094 36.027344 28.765625 36.15625 30.1875 L 36.15625 30.3125 L 36.21875 30.4375 C 36.722656 31.785156 37.886719 32.597656 39.125 33.21875 C 40.363281 33.839844 41.75 34.308594 43.0625 34.875 C 44.375 35.441406 45.566406 36.085938 46.4375 36.96875 C 47.09375 37.636719 47.503906 38.523438 47.75 39.59375 L 36.875 39.59375 C 35.644531 38.550781 34.222656 37.828125 32.8125 37.21875 C 31.148438 36.5 29.515625 35.914063 28.25 35.28125 C 27.035156 34.671875 26.269531 34.054688 25.9375 33.28125 C 25.828125 31.964844 25.835938 30.933594 25.84375 29.6875 C 25.972656 29.546875 26.160156 29.449219 26.28125 29.28125 C 26.554688 28.902344 26.816406 28.441406 27.0625 27.9375 C 27.488281 27.0625 27.796875 26.011719 27.96875 24.96875 C 28.28125 24.804688 28.617188 24.765625 28.875 24.4375 C 29.355469 23.824219 29.695313 22.949219 29.84375 21.71875 C 29.976563 20.625 29.609375 19.902344 29.15625 19.34375 C 29.644531 17.757813 30.269531 15.195313 30.0625 12.5625 C 29.949219 11.125 29.582031 9.691406 28.71875 8.5 C 28.714844 8.492188 28.722656 8.476563 28.71875 8.46875 C 29.660156 7.84375 31 7.445313 32.90625 7.40625 Z"/></svg> \ No newline at end of file
diff --git a/iOSClient/Images.xcassets/icon-deck.imageset/Contents.json b/iOSClient/Images.xcassets/icon-deck.imageset/Contents.json
new file mode 100644
index 000000000..3137099e6
--- /dev/null
+++ b/iOSClient/Images.xcassets/icon-deck.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images" : [
+ {
+ "filename" : "deck.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/iOSClient/Images.xcassets/icon-deck.imageset/deck.svg b/iOSClient/Images.xcassets/icon-deck.imageset/deck.svg
new file mode 100644
index 000000000..0e36f77af
--- /dev/null
+++ b/iOSClient/Images.xcassets/icon-deck.imageset/deck.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg height="16" width="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+ <g fill="#fff">
+ <rect ry="1" height="8" width="14" y="7" x="1" style="fill: rgb(0, 0, 0);"/>
+ <rect ry=".5" height="1" width="12" y="5" x="2" style="fill: rgb(0, 0, 0);"/>
+ <rect ry=".5" height="1" width="10" y="3" x="3" style="fill: rgb(0, 0, 0);"/>
+ <rect ry=".5" height="1" width="8" y="1" x="4" style="fill: rgb(0, 0, 0);"/>
+ </g>
+</svg> \ No newline at end of file
diff --git a/iOSClient/Images.xcassets/icon-mail.imageset/Contents.json b/iOSClient/Images.xcassets/icon-mail.imageset/Contents.json
new file mode 100644
index 000000000..53b2cb365
--- /dev/null
+++ b/iOSClient/Images.xcassets/icon-mail.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images" : [
+ {
+ "filename" : "icons8-nuovo-messaggio.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/iOSClient/Images.xcassets/icon-mail.imageset/icons8-nuovo-messaggio.svg b/iOSClient/Images.xcassets/icon-mail.imageset/icons8-nuovo-messaggio.svg
new file mode 100644
index 000000000..8518704a8
--- /dev/null
+++ b/iOSClient/Images.xcassets/icon-mail.imageset/icons8-nuovo-messaggio.svg
@@ -0,0 +1 @@
+<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="50px" height="50px"><path d="M 0 7 L 0 43 L 50 43 L 50 7 Z M 2 9 L 48 9 L 48 11.53125 L 25 29.71875 L 2 11.53125 Z M 2 14.09375 L 24.375 31.78125 C 24.742188 32.074219 25.257813 32.074219 25.625 31.78125 L 48 14.09375 L 48 41 L 2 41 Z"/></svg> \ No newline at end of file
diff --git a/iOSClient/Images.xcassets/icon-pages.imageset/Contents.json b/iOSClient/Images.xcassets/icon-pages.imageset/Contents.json
new file mode 100644
index 000000000..04a211550
--- /dev/null
+++ b/iOSClient/Images.xcassets/icon-pages.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images" : [
+ {
+ "filename" : "icon-pages.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/iOSClient/Images.xcassets/icon-pages.imageset/icon-pages.svg b/iOSClient/Images.xcassets/icon-pages.imageset/icon-pages.svg
new file mode 100644
index 000000000..67730faf1
--- /dev/null
+++ b/iOSClient/Images.xcassets/icon-pages.imageset/icon-pages.svg
@@ -0,0 +1 @@
+<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="50px" height="50px"><path d="M 7 2 L 7 48 L 43 48 L 43 14.59375 L 42.71875 14.28125 L 30.71875 2.28125 L 30.40625 2 Z M 9 4 L 29 4 L 29 12 L 15 12 L 15 14 L 29 14 L 29 16 L 41 16 L 41 46 L 9 46 Z M 31 5.4375 L 39.5625 14 L 31 14 Z M 15 22 L 15 24 L 18 24 L 18 22 Z M 22 22 L 22 24 L 35 24 L 35 22 Z M 15 28 L 15 30 L 18 30 L 18 28 Z M 22 28 L 22 30 L 35 30 L 35 28 Z M 15 34 L 15 36 L 18 36 L 18 34 Z M 22 34 L 22 36 L 35 36 L 35 34 Z"/></svg> \ No newline at end of file
diff --git a/iOSClient/Images.xcassets/icon-talk.imageset/Contents.json b/iOSClient/Images.xcassets/icon-talk.imageset/Contents.json
new file mode 100644
index 000000000..e1961fe89
--- /dev/null
+++ b/iOSClient/Images.xcassets/icon-talk.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images" : [
+ {
+ "filename" : "app-dark.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/iOSClient/Images.xcassets/icon-talk.imageset/app-dark.svg b/iOSClient/Images.xcassets/icon-talk.imageset/app-dark.svg
new file mode 100644
index 000000000..3e133d0a1
--- /dev/null
+++ b/iOSClient/Images.xcassets/icon-talk.imageset/app-dark.svg
@@ -0,0 +1 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9992 0.999a6.9993 6.9994 0 0 0-6.9992 6.9996 6.9993 6.9994 0 0 0 6.9992 6.9994 6.9993 6.9994 0 0 0 3.6308-1.024c0.86024 0.34184 2.7871 1.356 3.2457 0.91794 0.47922-0.45765-0.56261-2.6116-0.81238-3.412a6.9993 6.9994 0 0 0 0.935-3.4814 6.9993 6.9994 0 0 0-6.9991-6.9993zm8e-4 2.6611a4.34 4.3401 0 0 1 4.34 4.3401 4.34 4.3401 0 0 1-4.34 4.3398 4.34 4.3401 0 0 1-4.34-4.3398 4.34 4.3401 0 0 1 4.34-4.3401z" stroke-width=".14"/></svg>
diff --git a/iOSClient/Images.xcassets/palette.imageset/Contents.json b/iOSClient/Images.xcassets/palette.imageset/Contents.json
new file mode 100644
index 000000000..a4bc71f0b
--- /dev/null
+++ b/iOSClient/Images.xcassets/palette.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images" : [
+ {
+ "filename" : "palette.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/iOSClient/Images.xcassets/palette.imageset/palette.svg b/iOSClient/Images.xcassets/palette.imageset/palette.svg
new file mode 100644
index 000000000..6ded5cbb6
--- /dev/null
+++ b/iOSClient/Images.xcassets/palette.imageset/palette.svg
@@ -0,0 +1 @@
+<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="50px" height="50px"><path d="M 26.3125 0 C 20.257813 0 14.421875 1.878906 10.09375 5.8125 C 5.765625 9.746094 3 15.710938 3 23.6875 C 3 36.703125 13.082031 50 27.40625 50 L 27.59375 50 C 27.605469 50 27.613281 50 27.625 50 C 30.585938 49.945313 33.417969 48.9375 35.53125 47.03125 C 37.644531 45.125 39 42.3125 39 38.8125 C 39 36.878906 38.082031 35.347656 37.625 34.15625 C 37.625 34.144531 37.625 34.136719 37.625 34.125 C 36.9375 32.390625 37.152344 31.59375 37.8125 30.71875 C 38.472656 29.84375 39.792969 28.976563 41.3125 27.875 C 44.347656 25.667969 48.050781 22.273438 48 14.90625 C 48 12.320313 46.574219 8.664063 43.15625 5.5625 C 39.738281 2.460938 34.316406 0 26.3125 0 Z M 26.3125 2 C 33.910156 2 38.8125 4.28125 41.84375 7.03125 C 44.875 9.78125 46 13.09375 46 14.90625 C 46.046875 21.636719 43.039063 24.132813 40.125 26.25 C 38.667969 27.308594 37.214844 28.203125 36.21875 29.53125 C 35.226563 30.851563 34.9375 32.691406 35.78125 34.84375 C 35.785156 34.851563 35.777344 34.867188 35.78125 34.875 C 36.320313 36.273438 37 37.554688 37 38.8125 C 37 41.8125 35.898438 44.019531 34.1875 45.5625 C 32.476563 47.105469 30.132813 47.953125 27.59375 48 L 27.40625 48 C 14.328125 48 5 35.671875 5 23.6875 C 5 16.164063 7.539063 10.824219 11.4375 7.28125 C 15.335938 3.738281 20.667969 2 26.3125 2 Z M 26.5 5 C 25.1875 5 24.035156 5.710938 23.25 6.71875 C 22.464844 7.726563 22 9.046875 22 10.5 C 22 11.953125 22.464844 13.273438 23.25 14.28125 C 24.035156 15.289063 25.1875 16 26.5 16 C 27.8125 16 28.964844 15.289063 29.75 14.28125 C 30.535156 13.273438 31 11.953125 31 10.5 C 31 9.046875 30.535156 7.726563 29.75 6.71875 C 28.964844 5.710938 27.8125 5 26.5 5 Z M 26.5 7 C 27.117188 7 27.707031 7.316406 28.1875 7.9375 C 28.667969 8.558594 29 9.46875 29 10.5 C 29 11.53125 28.667969 12.441406 28.1875 13.0625 C 27.707031 13.683594 27.117188 14 26.5 14 C 25.882813 14 25.292969 13.683594 24.8125 13.0625 C 24.332031 12.441406 24 11.53125 24 10.5 C 24 9.46875 24.332031 8.558594 24.8125 7.9375 C 25.292969 7.316406 25.882813 7 26.5 7 Z M 15.5 10 C 14.1875 10 13.035156 10.710938 12.25 11.71875 C 11.464844 12.726563 11 14.046875 11 15.5 C 11 16.953125 11.464844 18.273438 12.25 19.28125 C 13.035156 20.289063 14.1875 21 15.5 21 C 16.8125 21 17.964844 20.289063 18.75 19.28125 C 19.535156 18.273438 20 16.953125 20 15.5 C 20 14.046875 19.535156 12.726563 18.75 11.71875 C 17.964844 10.710938 16.8125 10 15.5 10 Z M 37.5 10 C 36.1875 10 35.035156 10.710938 34.25 11.71875 C 33.464844 12.726563 33 14.046875 33 15.5 C 33 16.953125 33.464844 18.273438 34.25 19.28125 C 35.035156 20.289063 36.1875 21 37.5 21 C 38.8125 21 39.964844 20.289063 40.75 19.28125 C 41.535156 18.273438 42 16.953125 42 15.5 C 42 14.046875 41.535156 12.726563 40.75 11.71875 C 39.964844 10.710938 38.8125 10 37.5 10 Z M 15.5 12 C 16.117188 12 16.707031 12.316406 17.1875 12.9375 C 17.667969 13.558594 18 14.46875 18 15.5 C 18 16.53125 17.667969 17.441406 17.1875 18.0625 C 16.707031 18.683594 16.117188 19 15.5 19 C 14.882813 19 14.292969 18.683594 13.8125 18.0625 C 13.332031 17.441406 13 16.53125 13 15.5 C 13 14.46875 13.332031 13.558594 13.8125 12.9375 C 14.292969 12.316406 14.882813 12 15.5 12 Z M 37.5 12 C 38.117188 12 38.707031 12.316406 39.1875 12.9375 C 39.667969 13.558594 40 14.46875 40 15.5 C 40 16.53125 39.667969 17.441406 39.1875 18.0625 C 38.707031 18.683594 38.117188 19 37.5 19 C 36.882813 19 36.292969 18.683594 35.8125 18.0625 C 35.332031 17.441406 35 16.53125 35 15.5 C 35 14.46875 35.332031 13.558594 35.8125 12.9375 C 36.292969 12.316406 36.882813 12 37.5 12 Z M 14.5 23 C 13.1875 23 12.035156 23.710938 11.25 24.71875 C 10.464844 25.726563 10 27.046875 10 28.5 C 10 29.953125 10.464844 31.273438 11.25 32.28125 C 12.035156 33.289063 13.1875 34 14.5 34 C 15.8125 34 16.964844 33.289063 17.75 32.28125 C 18.535156 31.273438 19 29.953125 19 28.5 C 19 27.046875 18.535156 25.726563 17.75 24.71875 C 16.964844 23.710938 15.8125 23 14.5 23 Z M 14.5 25 C 15.117188 25 15.707031 25.316406 16.1875 25.9375 C 16.667969 26.558594 17 27.46875 17 28.5 C 17 29.53125 16.667969 30.441406 16.1875 31.0625 C 15.707031 31.683594 15.117188 32 14.5 32 C 13.882813 32 13.292969 31.683594 12.8125 31.0625 C 12.332031 30.441406 12 29.53125 12 28.5 C 12 27.46875 12.332031 26.558594 12.8125 25.9375 C 13.292969 25.316406 13.882813 25 14.5 25 Z M 27 33 C 23.675781 33 21 35.675781 21 39 C 21 42.324219 23.675781 45 27 45 C 30.324219 45 33 42.324219 33 39 C 33 35.675781 30.324219 33 27 33 Z M 27 35 C 29.277344 35 31 36.722656 31 39 C 31 41.277344 29.277344 43 27 43 C 24.722656 43 23 41.277344 23 39 C 23 36.722656 24.722656 35 27 35 Z"/></svg> \ No newline at end of file
diff --git a/iOSClient/Images.xcassets/rgb.imageset/Contents.json b/iOSClient/Images.xcassets/rgb.imageset/Contents.json
new file mode 100644
index 000000000..587109c2c
--- /dev/null
+++ b/iOSClient/Images.xcassets/rgb.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "images" : [
+ {
+ "filename" : "rgb.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/iOSClient/Images.xcassets/rgb.imageset/rgb.svg b/iOSClient/Images.xcassets/rgb.imageset/rgb.svg
new file mode 100644
index 000000000..96e4b9503
--- /dev/null
+++ b/iOSClient/Images.xcassets/rgb.imageset/rgb.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48px" height="48px"><linearGradient id="Y2MBg9lti7D0ov~adiJgUa" x1="16.758" x2="30.883" y1="3.118" y2="17.242" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f44f5a"/><stop offset=".443" stop-color="#ee3d4a"/><stop offset="1" stop-color="#e52030"/></linearGradient><path fill="url(#Y2MBg9lti7D0ov~adiJgUa)" d="M24,4l-1,1v19h2.414L38.14,11.274V9.86C34.52,6.24,29.52,4,24,4z"/><linearGradient id="Y2MBg9lti7D0ov~adiJgUb" x1="-33.907" x2="-.208" y1="19.952" y2="53.652" gradientTransform="rotate(45.001 24.001 92)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fed100"/><stop offset="1" stop-color="#e36001"/></linearGradient><path fill="url(#Y2MBg9lti7D0ov~adiJgUb)" d="M38.142,9.858L24,24l1,1l17.997,0l1-1C43.997,18.881,42.045,13.761,38.142,9.858z"/><linearGradient id="Y2MBg9lti7D0ov~adiJgUc" x1="-46.93" x2="-36.223" y1="74.93" y2="85.637" gradientTransform="rotate(90 24 92)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#ffd747"/><stop offset=".482" stop-color="#ffd645"/><stop offset="1" stop-color="#f5bc00"/></linearGradient><path fill="url(#Y2MBg9lti7D0ov~adiJgUc)" d="M44,24H24v1.414L36.726,38.14h1.414C41.76,34.52,44,29.52,44,24z"/><linearGradient id="Y2MBg9lti7D0ov~adiJgUd" x1="-27.013" x2="-16.306" y1="123.013" y2="133.72" gradientTransform="rotate(134.999 24 92)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#33c481"/><stop offset="1" stop-color="#21a366"/></linearGradient><path fill="url(#Y2MBg9lti7D0ov~adiJgUd)" d="M38.142,38.142L24,24l-1,1l0,17.997l1,1C29.119,43.997,34.239,42.045,38.142,38.142z"/><linearGradient id="Y2MBg9lti7D0ov~adiJgUe" x1="21.07" x2="31.777" y1="142.93" y2="153.637" gradientTransform="rotate(180 24 92)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#28afea"/><stop offset="1" stop-color="#0b88da"/></linearGradient><path fill="url(#Y2MBg9lti7D0ov~adiJgUe)" d="M24,44V24h-1.414L9.86,36.726v1.414C13.48,41.76,18.48,44,24,44z"/><linearGradient id="Y2MBg9lti7D0ov~adiJgUf" x1="67.621" x2="78.328" y1="121.481" y2="132.188" gradientTransform="rotate(-134.999 24 92)" gradientUnits="userSpaceOnUse"><stop offset=".002" stop-color="#427fdb"/><stop offset=".397" stop-color="#2668cb"/><stop offset=".763" stop-color="#1358bf"/><stop offset="1" stop-color="#0c52bb"/></linearGradient><path fill="url(#Y2MBg9lti7D0ov~adiJgUf)" d="M9.858,38.142L24,24l-1-1L5.003,23l-1,1C4.003,29.119,5.955,34.239,9.858,38.142z"/><linearGradient id="Y2MBg9lti7D0ov~adiJgUg" x1="89.07" x2="99.777" y1="74.93" y2="85.637" gradientTransform="rotate(-90 24 92)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#a235d4"/><stop offset=".441" stop-color="#a033d1"/><stop offset=".702" stop-color="#982cc9"/><stop offset=".915" stop-color="#8b21bb"/><stop offset="1" stop-color="#831bb3"/></linearGradient><path fill="url(#Y2MBg9lti7D0ov~adiJgUg)" d="M4,24h20v-1.414L11.274,9.86H9.86C6.24,13.48,4,18.48,4,24z"/><linearGradient id="Y2MBg9lti7D0ov~adiJgUh" x1="69.153" x2="96.498" y1="26.847" y2="54.191" gradientTransform="rotate(-45.001 23.999 92)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#e83c67"/><stop offset=".423" stop-color="#c5214a"/><stop offset=".773" stop-color="#b01038"/><stop offset="1" stop-color="#a80a31"/></linearGradient><path fill="url(#Y2MBg9lti7D0ov~adiJgUh)" d="M9.858,9.858L24,24V4.003C18.881,4.003,13.761,5.955,9.858,9.858z"/></svg> \ No newline at end of file
diff --git a/iOSClient/Login/NCLogin.swift b/iOSClient/Login/NCLogin.swift
index 1fb3c4081..f648198e8 100644
--- a/iOSClient/Login/NCLogin.swift
+++ b/iOSClient/Login/NCLogin.swift
@@ -101,6 +101,8 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
navBarAppearance.configureWithTransparentBackground()
navBarAppearance.shadowColor = .clear
navBarAppearance.shadowImage = UIImage()
+ navBarAppearance.titleTextAttributes = [.foregroundColor: textColor]
+ navBarAppearance.largeTitleTextAttributes = [.foregroundColor: textColor]
self.navigationController?.navigationBar.standardAppearance = navBarAppearance
self.navigationController?.view.backgroundColor = NCBrandColor.shared.customer
} else {
diff --git a/iOSClient/Login/NCLoginWeb.swift b/iOSClient/Login/NCLoginWeb.swift
index 334de625f..448b5de99 100644
--- a/iOSClient/Login/NCLoginWeb.swift
+++ b/iOSClient/Login/NCLoginWeb.swift
@@ -31,6 +31,7 @@ class NCLoginWeb: UIViewController {
var activityIndicator: UIActivityIndicatorView!
var webView: WKWebView?
let appDelegate = UIApplication.shared.delegate as! AppDelegate
+ var titleView: String = ""
@objc var urlBase = ""
@@ -45,6 +46,14 @@ class NCLoginWeb: UIViewController {
super.viewDidLoad()
let accountCount = NCManageDatabase.shared.getAccounts()?.count ?? 0
+ // TITLE
+ titleView = urlBase
+ if let host = URL(string: urlBase)?.host {
+ if let account = NCManageDatabase.shared.getActiveAccount(), CCUtility.getPassword(account.account).isEmpty {
+ titleView = NSLocalizedString("_user_", comment: "") + " " + account.userId + " " + NSLocalizedString("_in_", comment: "") + " " + host
+ }
+ }
+ self.title = titleView
if NCBrandOptions.shared.use_login_web_personalized && accountCount > 0 {
navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .stop, target: self, action: #selector(self.closeView(sender:)))
@@ -93,6 +102,23 @@ class NCLoginWeb: UIViewController {
// Stop timer error network
appDelegate.timerErrorNetworking?.invalidate()
+
+ // ITMS-90076: Potential Loss of Keychain Access
+ if appDelegate.errorITMS90076, !CCUtility.getPresentErrorITMS90076() {
+
+ let message = "\n" + NSLocalizedString("_ITMS-90076_", comment: "")
+ let alertController = UIAlertController(title: titleView, message: message, preferredStyle: .alert)
+ alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in }))
+ present(alertController, animated: true, completion: {
+ CCUtility.setPresentErrorITMS90076(true)
+ })
+ } else if let account = NCManageDatabase.shared.getActiveAccount(), CCUtility.getPassword(account.account).isEmpty {
+
+ let message = "\n" + NSLocalizedString("_password_not_present_", comment: "")
+ let alertController = UIAlertController(title: titleView, message: message, preferredStyle: .alert)
+ alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in }))
+ present(alertController, animated: true)
+ }
}
override func viewDidDisappear(_ animated: Bool) {
diff --git a/iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift b/iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift
index 6c12e8346..c7835f016 100644
--- a/iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift
+++ b/iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift
@@ -54,26 +54,21 @@ class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate {
durationLabel.text = ""
startStopLabel.text = NSLocalizedString("_voice_memo_start_", comment: "")
- changeTheming()
+ view.backgroundColor = .clear
+ contentContainerView.backgroundColor = UIColor.lightGray
+ voiceRecordHUD.fillColor = UIColor.green
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
- override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
- super.traitCollectionDidChange(previousTraitCollection)
-
- changeTheming()
+ override func viewDidAppear(_ animated: Bool) {
+ super.viewDidAppear(animated)
}
- // MARK: - Colors
-
- func changeTheming() {
-
- view.backgroundColor = .clear
- contentContainerView.backgroundColor = UIColor.lightGray
- voiceRecordHUD.fillColor = UIColor.green
+ override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
+ super.traitCollectionDidChange(previousTraitCollection)
}
// MARK: - Action
diff --git a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift
index 0b8a7c674..f1af07cd3 100644
--- a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift
+++ b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift
@@ -24,9 +24,9 @@
import UIKit
import Realm
import NCCommunication
+import EasyTipView
-class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UISearchResultsUpdating, UISearchControllerDelegate, UISearchBarDelegate, NCListCellDelegate, NCGridCellDelegate, NCSectionHeaderMenuDelegate, UIAdaptivePresentationControllerDelegate, NCEmptyDataSetDelegate, UIContextMenuInteractionDelegate, NCAccountRequestDelegate, NCBackgroundImageColorDelegate, NCSelectableNavigationView {
- var selectableDataSource: [RealmSwiftObject] { dataSource.metadatas }
+class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UISearchResultsUpdating, UISearchControllerDelegate, UISearchBarDelegate, NCListCellDelegate, NCGridCellDelegate, NCSectionHeaderMenuDelegate, NCSectionFooterDelegate, UIAdaptivePresentationControllerDelegate, NCEmptyDataSetDelegate, UIContextMenuInteractionDelegate, NCAccountRequestDelegate, NCSelectableNavigationView {
@IBOutlet weak var collectionView: UICollectionView!
@@ -40,25 +40,24 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
internal var isEncryptedFolder = false
internal var isEditMode = false
internal var selectOcId: [String] = []
- internal var metadatasSource: [tableMetadata] = []
internal var metadataFolder: tableMetadata?
internal var dataSource = NCDataSource()
internal var richWorkspaceText: String?
- internal var header: NCSectionHeaderMenu?
+ internal var headerMenu: NCSectionHeaderMenu?
internal var layoutForView: NCGlobal.layoutForViewType?
+ internal var selectableDataSource: [RealmSwiftObject] { dataSource.getMetadataSourceForAllSections() }
private var autoUploadFileName = ""
private var autoUploadDirectory = ""
+ internal var groupByField = "name"
+ internal var providers: [NCCSearchProvider]?
+ internal var searchResults: [NCCSearchResult]?
+
internal var listLayout: NCListLayout!
internal var gridLayout: NCGridLayout!
- private let headerHeight: CGFloat = 50
- private var headerRichWorkspaceHeight: CGFloat = 0
- private let footerHeight: CGFloat = 100
-
- private var timerInputSearch: Timer?
internal var literalSearch: String?
internal var isSearching: Bool = false
@@ -66,10 +65,15 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
private var pushed: Bool = false
+ private var tipView: EasyTipView?
+
// DECLARE
internal var layoutKey = ""
internal var titleCurrentFolder = ""
internal var enableSearchBar: Bool = false
+ internal var headerMenuButtonsCommand: Bool = true
+ internal var headerMenuButtonsView: Bool = true
+ internal var headerRichWorkspaceDisable:Bool = false
internal var emptyImage: UIImage?
internal var emptyTitle: String = ""
internal var emptyDescription: String = ""
@@ -87,12 +91,18 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
collectionView.alwaysBounceVertical = true
+ // Color
+ view.backgroundColor = NCBrandColor.shared.systemBackground
+ collectionView.backgroundColor = NCBrandColor.shared.systemBackground
+ refreshControl.tintColor = .gray
+
if enableSearchBar {
searchController = UISearchController(searchResultsController: nil)
searchController?.searchResultsUpdater = self
searchController?.obscuresBackgroundDuringPresentation = false
searchController?.delegate = self
searchController?.searchBar.delegate = self
+ searchController?.searchBar.autocapitalizationType = .none
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false
}
@@ -104,6 +114,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
// Header
collectionView.register(UINib(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu")
+ collectionView.register(UINib(nibName: "NCSectionHeader", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeader")
// Footer
collectionView.register(UINib(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter")
@@ -114,11 +125,12 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
// Refresh Control
collectionView.addSubview(refreshControl)
refreshControl.action(for: .valueChanged) { _ in
+ self.dataSource.clearDirectory()
self.reloadDataSourceNetwork(forced: true)
}
// Empty
- emptyDataSet = NCEmptyDataSet(view: collectionView, offset: headerHeight, delegate: self)
+ emptyDataSet = NCEmptyDataSet(view: collectionView, offset: getHeaderHeight(), delegate: self)
// Long Press on CollectionView
let longPressedGesture = UILongPressGestureRecognizer(target: self, action: #selector(longPressCollecationView(_:)))
@@ -127,26 +139,46 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
longPressedGesture.delaysTouchesBegan = true
collectionView.addGestureRecognizer(longPressedGesture)
- // Notification
+ // TIP
+ var preferences = EasyTipView.Preferences()
+ preferences.drawing.foregroundColor = .white
+ preferences.drawing.backgroundColor = NCBrandColor.shared.nextcloud
+ preferences.drawing.textAlignment = .left
+ preferences.drawing.arrowPosition = .top
+ preferences.drawing.cornerRadius = 10
- NotificationCenter.default.addObserver(self, selector: #selector(initialize), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterInitialize), object: nil)
- NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil)
+ preferences.animating.dismissTransform = CGAffineTransform(translationX: 0, y: 100)
+ preferences.animating.showInitialTransform = CGAffineTransform(translationX: 0, y: -100)
+ preferences.animating.showInitialAlpha = 0
+ preferences.animating.showDuration = 1.5
+ preferences.animating.dismissDuration = 1.5
+
+ tipView = EasyTipView(text: NSLocalizedString("_tip_accountrequest_", comment: ""), preferences: preferences, delegate: self)
- changeTheming()
+ // Notification
+ NotificationCenter.default.addObserver(self, selector: #selector(initialize(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterInitialize), object: nil)
+ NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
- // ACTIVE
appDelegate.activeViewController = self
- //
+ layoutForView = NCUtility.shared.getLayoutForView(key: layoutKey, serverUrl: serverUrl)
+ gridLayout.itemForLine = CGFloat(layoutForView?.itemForLine ?? 3)
+ if layoutForView?.layout == NCGlobal.shared.layoutList {
+ collectionView?.collectionViewLayout = listLayout
+ } else {
+ collectionView?.collectionViewLayout = gridLayout
+ }
+
NotificationCenter.default.addObserver(self, selector: #selector(closeRichWorkspaceWebView), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterCloseRichWorkspaceWebView), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(changeStatusFolderE2EE(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeStatusFolderE2EE), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(setNavigationItem), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadAvatar), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSource(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSource), object: nil)
+ NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSourceNetwork), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSourceNetwork), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSourceNetworkForced(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSourceNetworkForced), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(deleteFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDeleteFile), object: nil)
@@ -176,14 +208,21 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
navigationController?.setNavigationBarHidden(false, animated: true)
setNavigationItem()
- changeTheming()
- reloadDataSource()
+ reloadDataSource(forced: false)
+ if !isSearching {
+ reloadDataSourceNetwork()
+ }
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
- reloadDataSourceNetwork()
+ // TIP
+ if self is NCFiles, !NCBrandOptions.shared.disable_multiaccount, !NCBrandOptions.shared.disable_manage_account, self.serverUrl == NCUtilityFileSystem.shared.getHomeServer(account: appDelegate.account), let view = self.navigationItem.leftBarButtonItem?.customView {
+ if !NCManageDatabase.shared.tipExists(NCGlobal.shared.tipNCCollectionViewCommonAccountRequest), NCManageDatabase.shared.getAllAccountOrderAlias().count > 0 {
+ self.tipView?.show(forView: view)
+ }
+ }
}
override func viewWillDisappear(_ animated: Bool) {
@@ -194,6 +233,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadAvatar), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSource), object: nil)
+ NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSourceNetwork), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSourceNetworkForced), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDeleteFile), object: nil)
@@ -201,22 +241,20 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterCopyFile), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterRenameFile), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterCreateFolder), object: nil)
- NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterFavoriteFile), object: nil)
-
- NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDownloadStartFile), object: nil)
- NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDownloadedFile), object: nil)
- NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDownloadCancelFile), object: nil)
-
- NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadStartFile), object: nil)
- NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadedFile), object: nil)
- NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadCancelFile), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterProgressTask), object: nil)
pushed = false
+
+ // REQUEST
+ NCNetworking.shared.cancelUnifiedSearchFiles()
+
+ // TIP
+ self.tipView?.dismiss()
}
func presentationControllerDidDismiss( _ presentationController: UIPresentationController) {
+
let viewController = presentationController.presentedViewController
if viewController is NCViewerRichWorkspaceWebView {
closeRichWorkspaceWebView()
@@ -226,30 +264,23 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
- coordinator.animate(alongsideTransition: nil) { _ in
- self.collectionView?.collectionViewLayout.invalidateLayout()
- }
+ self.collectionView?.collectionViewLayout.invalidateLayout()
+ self.collectionView?.reloadData()
}
override var canBecomeFirstResponder: Bool {
return true
}
- override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
- super.traitCollectionDidChange(previousTraitCollection)
-
- changeTheming()
- }
-
// MARK: - NotificationCenter
- @objc func initialize() {
-
- if appDelegate.account == "" { return }
+ @objc func initialize(_ notification: NSNotification) {
+ guard !appDelegate.account.isEmpty else { return }
// Search
- if searchController?.isActive ?? false {
+ if searchController?.isActive ?? false || isSearching {
searchController?.isActive = false
+ isSearching = false
}
// Select
@@ -274,75 +305,28 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
self.navigationController?.popToRootViewController(animated: false)
}
- setNavigationItem()
- reloadDataSource()
- changeTheming()
- }
-
- @objc func changeTheming() {
-
- view.backgroundColor = NCBrandColor.shared.systemBackground
- collectionView.backgroundColor = NCBrandColor.shared.systemBackground
- refreshControl.tintColor = .gray
-
layoutForView = NCUtility.shared.getLayoutForView(key: layoutKey, serverUrl: serverUrl)
gridLayout.itemForLine = CGFloat(layoutForView?.itemForLine ?? 3)
-
if layoutForView?.layout == NCGlobal.shared.layoutList {
collectionView?.collectionViewLayout = listLayout
} else {
collectionView?.collectionViewLayout = gridLayout
}
- // IMAGE BACKGROUND
- if layoutForView?.imageBackgroud != "" {
- let imagePath = CCUtility.getDirectoryGroup().appendingPathComponent(NCGlobal.shared.appBackground).path + "/" + layoutForView!.imageBackgroud
- do {
- let data = try Data(contentsOf: URL(fileURLWithPath: imagePath))
- if let image = UIImage(data: data) {
- backgroundImageView.image = image
- backgroundImageView.contentMode = .scaleToFill
- collectionView.backgroundView = backgroundImageView
- }
- } catch { }
- } else {
- backgroundImageView.image = nil
- collectionView.backgroundView = nil
- }
-
- // COLOR BACKGROUND
- let activeAccount = NCManageDatabase.shared.getActiveAccount()
- if traitCollection.userInterfaceStyle == .dark {
- if activeAccount?.darkColorBackground != "" {
- collectionView.backgroundColor = UIColor(hex: activeAccount?.darkColorBackground ?? "")
- } else {
- collectionView.backgroundColor = NCBrandColor.shared.systemBackground
- }
- } else {
- if activeAccount?.lightColorBackground != "" {
- collectionView.backgroundColor = UIColor(hex: activeAccount?.lightColorBackground ?? "")
- } else {
- collectionView.backgroundColor = NCBrandColor.shared.systemBackground
- }
- }
+ setNavigationItem()
+ }
+ @objc func changeTheming() {
collectionView.reloadData()
}
@objc func reloadDataSource(_ notification: NSNotification) {
-
reloadDataSource()
}
@objc func reloadDataSourceNetworkForced(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let serverUrl = userInfo["serverUrl"] as? String {
- if serverUrl == self.serverUrl {
- reloadDataSourceNetwork(forced: true)
- }
- }
- } else {
+ if !isSearching {
reloadDataSourceNetwork(forced: true)
}
}
@@ -357,94 +341,132 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
@objc func deleteFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary?, let ocId = userInfo["ocId"] as? String, let fileNameView = userInfo["fileNameView"] as? String, let onlyLocalCache = userInfo["onlyLocalCache"] as? Bool {
- if onlyLocalCache {
- reloadDataSource()
- } else if fileNameView.lowercased() == NCGlobal.shared.fileNameRichWorkspace.lowercased() {
- reloadDataSourceNetwork(forced: true)
- } else {
- if let row = dataSource.deleteMetadata(ocId: ocId) {
- let indexPath = IndexPath(row: row, section: 0)
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ let fileNameView = userInfo["fileNameView"] as? String,
+ let serverUrl = userInfo["serverUrl"] as? String,
+ serverUrl == self.serverUrl,
+ let account = userInfo["account"] as? String,
+ account == appDelegate.account,
+ let onlyLocalCache = userInfo["onlyLocalCache"] as? Bool
+ else { return }
+
+ if fileNameView.lowercased() == NCGlobal.shared.fileNameRichWorkspace.lowercased() {
+ reloadDataSourceNetwork(forced: true)
+ } else if onlyLocalCache {
+ self.collectionView?.reloadData()
+ } else {
+ let (indexPath, sameSections) = dataSource.deleteMetadata(ocId: ocId)
+ if let indexPath = indexPath, dataSource.metadatas.count > 0 {
+ if sameSections && (indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section)) {
collectionView?.performBatchUpdates({
collectionView?.deleteItems(at: [indexPath])
}, completion: { _ in
self.collectionView?.reloadData()
})
+ } else {
+ self.collectionView?.reloadData()
}
+ } else {
+ reloadDataSource()
}
}
}
@objc func moveFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary?, let ocId = userInfo["ocId"] as? String, let serverUrlFrom = userInfo["serverUrlFrom"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
- // DEL
- if serverUrlFrom == serverUrl && metadata.account == appDelegate.account {
- if let row = dataSource.deleteMetadata(ocId: ocId) {
- let indexPath = IndexPath(row: row, section: 0)
- collectionView?.performBatchUpdates({
- collectionView?.deleteItems(at: [indexPath])
- }, completion: { _ in
- self.collectionView?.reloadData()
- })
- }
- // ADD
- } else if metadata.serverUrl == serverUrl && metadata.account == appDelegate.account {
- if let row = dataSource.addMetadata(metadata) {
- let indexPath = IndexPath(row: row, section: 0)
- collectionView?.performBatchUpdates({
- collectionView?.insertItems(at: [indexPath])
- }, completion: { _ in
- self.collectionView?.reloadData()
- })
- }
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ let serverUrlFrom = userInfo["serverUrlFrom"] as? String,
+ serverUrlFrom == self.serverUrl
+ else { return }
+
+ let (indexPath, sameSections) = dataSource.deleteMetadata(ocId: ocId)
+ if let indexPath = indexPath {
+ if sameSections && (indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section)) {
+ collectionView?.performBatchUpdates({
+ collectionView?.deleteItems(at: [indexPath])
+ }, completion: { _ in
+ self.collectionView?.reloadData()
+ })
+ } else {
+ self.collectionView?.reloadData()
}
+ } else {
+ reloadDataSource()
}
}
@objc func copyFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary?, let serverUrlTo = userInfo["serverUrlTo"] as? String {
- if serverUrlTo == self.serverUrl {
- reloadDataSource()
- }
- }
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let serverUrlTo = userInfo["serverUrlTo"] as? String,
+ serverUrlTo == self.serverUrl
+ else { return }
+
+ reloadDataSource()
}
@objc func renameFile(_ notification: NSNotification) {
- reloadDataSource()
+ if isSearching {
+ reloadDataSourceNetwork()
+ } else {
+ reloadDataSource()
+ }
}
@objc func createFolder(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary?, let ocId = userInfo["ocId"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
- if metadata.serverUrl == serverUrl && metadata.account == appDelegate.account {
- pushMetadata(metadata)
- }
- } else {
- reloadDataSourceNetwork()
- }
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ let serverUrl = userInfo["serverUrl"] as? String,
+ serverUrl == self.serverUrl,
+ let account = userInfo["account"] as? String,
+ account == appDelegate.account,
+ let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId)
+ else { return }
+
+ reloadDataSource()
+ pushMetadata(metadata)
}
@objc func favoriteFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary?, let ocId = userInfo["ocId"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
- if dataSource.getIndexMetadata(ocId: metadata.ocId) != nil {
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ let serverUrl = userInfo["serverUrl"] as? String,
+ serverUrl == self.serverUrl
+ else {
+ if self is NCFavorite {
reloadDataSource()
}
+ return
}
+
+ dataSource.reloadMetadata(ocId: ocId)
+ collectionView?.reloadData()
}
@objc func downloadStartFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary?, let ocId = userInfo["ocId"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
- if let row = dataSource.reloadMetadata(ocId: metadata.ocId) {
- let indexPath = IndexPath(row: row, section: 0)
- if indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section) {
- collectionView?.reloadItems(at: [indexPath])
- }
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ let serverUrl = userInfo["serverUrl"] as? String,
+ serverUrl == self.serverUrl,
+ let account = userInfo["account"] as? String,
+ account == appDelegate.account
+ else { return }
+
+ let (indexPath, sameSections) = dataSource.reloadMetadata(ocId: ocId)
+ if let indexPath = indexPath {
+ if sameSections && (indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section)) {
+ collectionView?.reloadItems(at: [indexPath])
+ } else {
+ self.collectionView?.reloadData()
}
+ } else {
+ reloadDataSource()
}
}
@@ -452,125 +474,149 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
guard let userInfo = notification.userInfo as NSDictionary?,
let ocId = userInfo["ocId"] as? String,
- let _ = userInfo["errorCode"] as? Int,
- let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId),
- let row = dataSource.reloadMetadata(ocId: metadata.ocId)
+ let serverUrl = userInfo["serverUrl"] as? String,
+ serverUrl == self.serverUrl,
+ let account = userInfo["account"] as? String,
+ account == appDelegate.account
else { return }
- let indexPath = IndexPath(row: row, section: 0)
- if indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section) {
- collectionView?.reloadItems(at: [indexPath])
+
+ let (indexPath, sameSections) = dataSource.reloadMetadata(ocId: ocId)
+ if let indexPath = indexPath {
+ if sameSections && (indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section)) {
+ collectionView?.reloadItems(at: [indexPath])
+ } else {
+ self.collectionView?.reloadData()
+ }
+ } else {
+ reloadDataSource()
}
}
@objc func downloadCancelFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary?, let ocId = userInfo["ocId"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
- if let row = dataSource.reloadMetadata(ocId: metadata.ocId) {
- let indexPath = IndexPath(row: row, section: 0)
- if indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section) {
- collectionView?.reloadItems(at: [indexPath])
- }
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ let serverUrl = userInfo["serverUrl"] as? String,
+ serverUrl == self.serverUrl,
+ let account = userInfo["account"] as? String,
+ account == appDelegate.account
+ else { return }
+
+ let (indexPath, sameSections) = dataSource.reloadMetadata(ocId: ocId)
+ if let indexPath = indexPath {
+ if sameSections && (indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section)) {
+ collectionView?.reloadItems(at: [indexPath])
+ } else {
+ self.collectionView?.reloadData()
}
+ } else {
+ reloadDataSource()
}
}
@objc func uploadStartFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary?, let ocId = userInfo["ocId"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
- if metadata.serverUrl == serverUrl && metadata.account == appDelegate.account {
- dataSource.addMetadata(metadata)
- self.collectionView?.reloadData()
- }
- }
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ let serverUrl = userInfo["serverUrl"] as? String,
+ serverUrl == self.serverUrl,
+ let account = userInfo["account"] as? String,
+ account == appDelegate.account
+ else { return }
+
+ guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return }
+ dataSource.addMetadata(metadata)
+ self.collectionView?.reloadData()
}
@objc func uploadedFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary?, let ocId = userInfo["ocId"] as? String, let ocIdTemp = userInfo["ocIdTemp"] as? String, let _ = userInfo["errorCode"] as? Int, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
- if metadata.serverUrl == serverUrl && metadata.account == appDelegate.account {
- dataSource.reloadMetadata(ocId: metadata.ocId, ocIdTemp: ocIdTemp)
- collectionView?.reloadData()
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ let ocIdTemp = userInfo["ocIdTemp"] as? String,
+ let serverUrl = userInfo["serverUrl"] as? String,
+ serverUrl == self.serverUrl,
+ let account = userInfo["account"] as? String,
+ account == appDelegate.account
+ else { return }
+
+ guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return }
+ if metadata.livePhoto && metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue { return }
+ let (indexPath, sameSections) = dataSource.reloadMetadata(ocId: metadata.ocId, ocIdTemp: ocIdTemp)
+ if let indexPath = indexPath {
+ if sameSections && (indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section)) {
+ collectionView?.performBatchUpdates({
+ collectionView?.reloadItems(at: [indexPath])
+ }, completion: { _ in
+ self.collectionView?.reloadData()
+ })
+ } else {
+ self.collectionView?.reloadData()
}
+ } else {
+ reloadDataSource()
}
}
@objc func uploadCancelFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary?, let ocId = userInfo["ocId"] as? String, let serverUrl = userInfo["serverUrl"] as? String, let account = userInfo["account"] as? String {
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ let serverUrl = userInfo["serverUrl"] as? String,
+ serverUrl == self.serverUrl,
+ let account = userInfo["account"] as? String,
+ account == appDelegate.account
+ else { return }
- if serverUrl == self.serverUrl && account == appDelegate.account {
- if let row = dataSource.deleteMetadata(ocId: ocId) {
- let indexPath = IndexPath(row: row, section: 0)
- collectionView?.performBatchUpdates({
- if indexPath.section < (collectionView?.numberOfSections ?? 0) && indexPath.row < (collectionView?.numberOfItems(inSection: indexPath.section) ?? 0) {
- collectionView?.deleteItems(at: [indexPath])
- }
- }, completion: { _ in
- self.collectionView?.reloadData()
- })
- } else {
- self.reloadDataSource()
- }
+ let (indexPath, sameSections) = dataSource.deleteMetadata(ocId: ocId)
+ if let indexPath = indexPath {
+ if sameSections && (indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section)) {
+ collectionView?.performBatchUpdates({
+ collectionView?.deleteItems(at: [indexPath])
+ }, completion: { _ in
+ self.collectionView?.reloadData()
+ })
+ } else {
+ self.collectionView?.reloadData()
}
+ } else {
+ reloadDataSource()
}
}
@objc func triggerProgressTask(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary?, let progressNumber = userInfo["progress"] as? NSNumber, let totalBytes = userInfo["totalBytes"] as? Int64, let totalBytesExpected = userInfo["totalBytesExpected"] as? Int64, let ocId = userInfo["ocId"] as? String {
-
- let status = userInfo["status"] as? Int ?? NCGlobal.shared.metadataStatusNormal
-
- if let index = dataSource.getIndexMetadata(ocId: ocId) {
- if let cell = collectionView?.cellForItem(at: IndexPath(row: index, section: 0)) {
- if cell is NCListCell {
- let cell = cell as! NCListCell
- if progressNumber.floatValue == 1 {
- cell.progressView?.isHidden = true
- cell.progressView?.progress = .zero
- cell.setButtonMore(named: NCGlobal.shared.buttonMoreMore, image: NCBrandColor.cacheImages.buttonMore)
- if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
- cell.labelInfo.text = CCUtility.dateDiff(metadata.date as Date) + " · " + CCUtility.transformedSize(metadata.size)
- } else {
- cell.labelInfo.text = ""
- }
- } else if progressNumber.floatValue > 0 {
- cell.progressView?.isHidden = false
- cell.progressView?.progress = progressNumber.floatValue
- cell.setButtonMore(named: NCGlobal.shared.buttonMoreStop, image: NCBrandColor.cacheImages.buttonStop)
- if status == NCGlobal.shared.metadataStatusInDownload {
- cell.labelInfo.text = CCUtility.transformedSize(totalBytesExpected) + " - ↓ " + CCUtility.transformedSize(totalBytes)
- } else if status == NCGlobal.shared.metadataStatusInUpload {
- cell.labelInfo.text = CCUtility.transformedSize(totalBytesExpected) + " - ↑ " + CCUtility.transformedSize(totalBytes)
- }
- }
- } else if cell is NCTransferCell {
- let cell = cell as! NCTransferCell
- if progressNumber.floatValue == 1 {
- cell.progressView?.isHidden = true
- cell.progressView?.progress = .zero
- cell.buttonMore.isHidden = true
- cell.labelInfo.text = ""
- } else if progressNumber.floatValue > 0 {
- cell.progressView?.isHidden = false
- cell.progressView?.progress = progressNumber.floatValue
- cell.setButtonMore(named: NCGlobal.shared.buttonMoreStop, image: NCBrandColor.cacheImages.buttonStop)
- if status == NCGlobal.shared.metadataStatusInDownload {
- cell.labelInfo.text = CCUtility.transformedSize(totalBytesExpected) + " - ↓ " + CCUtility.transformedSize(totalBytes)
- } else if status == NCGlobal.shared.metadataStatusInUpload {
- cell.labelInfo.text = CCUtility.transformedSize(totalBytesExpected) + " - ↑ " + CCUtility.transformedSize(totalBytes)
- }
- }
- } else if cell is NCGridCell {
- let cell = cell as! NCGridCell
- if progressNumber.floatValue == 1 {
- cell.progressView.isHidden = true
- cell.progressView.progress = .zero
- cell.setButtonMore(named: NCGlobal.shared.buttonMoreMore, image: NCBrandColor.cacheImages.buttonMore)
- } else if progressNumber.floatValue > 0 {
- cell.progressView.isHidden = false
- cell.progressView.progress = progressNumber.floatValue
- cell.setButtonMore(named: NCGlobal.shared.buttonMoreStop, image: NCBrandColor.cacheImages.buttonStop)
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let progressNumber = userInfo["progress"] as? NSNumber,
+ let totalBytes = userInfo["totalBytes"] as? Int64,
+ let totalBytesExpected = userInfo["totalBytesExpected"] as? Int64,
+ let ocId = userInfo["ocId"] as? String,
+ let (indexPath, _) = self.dataSource.getIndexPathMetadata(ocId: ocId) as? (IndexPath, NCMetadataForSection?)
+ else { return }
+
+ let status = userInfo["status"] as? Int ?? NCGlobal.shared.metadataStatusNormal
+ if let cell = collectionView?.cellForItem(at: indexPath) {
+ if let cell = cell as? NCCellProtocol {
+ if progressNumber.floatValue == 1 && !(cell is NCTransferCell) {
+ cell.fileProgressView?.isHidden = true
+ cell.fileProgressView?.progress = .zero
+ cell.setButtonMore(named: NCGlobal.shared.buttonMoreMore, image: NCBrandColor.cacheImages.buttonMore)
+ if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
+ cell.writeInfoDateSize(date: metadata.date, size: metadata.size)
+ } else {
+ cell.fileInfoLabel?.text = ""
+ }
+ } else {
+ cell.fileProgressView?.isHidden = false
+ cell.fileProgressView?.progress = progressNumber.floatValue
+ cell.setButtonMore(named: NCGlobal.shared.buttonMoreStop, image: NCBrandColor.cacheImages.buttonStop)
+ if status == NCGlobal.shared.metadataStatusInDownload {
+ cell.fileInfoLabel?.text = CCUtility.transformedSize(totalBytesExpected) + " - ↓ " + CCUtility.transformedSize(totalBytes)
+ } else if status == NCGlobal.shared.metadataStatusInUpload {
+ if totalBytes > 0 {
+ cell.fileInfoLabel?.text = CCUtility.transformedSize(totalBytesExpected) + " - ↑ " + CCUtility.transformedSize(totalBytes)
+ } else {
+ cell.fileInfoLabel?.text = CCUtility.transformedSize(totalBytesExpected) + " - ↑ …"
}
}
}
@@ -582,6 +628,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
@objc func setNavigationItem() {
self.setNavigationHeader()
+
guard !isEditMode, layoutKey == NCGlobal.shared.layoutViewFiles else { return }
// PROFILE BUTTON
@@ -634,6 +681,9 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
UIApplication.shared.keyWindow?.rootViewController?.present(popup, animated: true)
}
+
+ // TIP
+ self.dismissTip()
}
}
navigationItem.setLeftBarButton(UIBarButtonItem(customView: button), animated: true)
@@ -641,6 +691,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
}
func getNavigationTitle() -> String {
+
let activeAccount = NCManageDatabase.shared.getActiveAccount()
guard let userAlias = activeAccount?.alias, !userAlias.isEmpty else {
return NCBrandOptions.shared.brand
@@ -648,28 +699,12 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
return userAlias
}
- // MARK: - BackgroundImageColor Delegate
-
- func colorPickerCancel() {
- changeTheming()
- }
-
- func colorPickerWillChange(color: UIColor) {
- collectionView.backgroundColor = color
- }
-
- func colorPickerDidChange(lightColor: String, darkColor: String) {
-
- NCManageDatabase.shared.setAccountColorFiles(lightColorBackground: lightColor, darkColorBackground: darkColor)
-
- changeTheming()
- }
-
// MARK: - Empty
func emptyDataSetView(_ view: NCEmptyView) {
- if searchController?.isActive ?? false {
+ self.emptyDataSet?.setOffset(getHeaderHeight())
+ if isSearching {
view.emptyImage.image = UIImage(named: "search")?.image(color: .gray, size: UIScreen.main.bounds.width)
if isReloadDataSourceNetworkInProgress {
view.emptyTitle.text = NSLocalizedString("_search_in_progress_", comment: "")
@@ -697,30 +732,45 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
// MARK: - SEARCH
func updateSearchResults(for searchController: UISearchController) {
-
- timerInputSearch?.invalidate()
- timerInputSearch = Timer.scheduledTimer(timeInterval: 1.5, target: self, selector: #selector(reloadDataSourceNetwork), userInfo: nil, repeats: false)
- literalSearch = searchController.searchBar.text
- collectionView?.reloadData()
+ self.literalSearch = searchController.searchBar.text
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
- isSearching = true
- metadatasSource.removeAll()
- reloadDataSource()
+ self.isSearching = true
+ self.providers?.removeAll()
+ self.dataSource.clearDataSource()
+ self.collectionView.reloadData()
+
+ // TIP
+ self.tipView?.dismiss()
+ }
+
+ func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
+
+ if self.isSearching && self.literalSearch?.count ?? 0 >= 2 {
+ reloadDataSourceNetwork()
+ }
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
- isSearching = false
- literalSearch = ""
- reloadDataSource()
+ DispatchQueue.global().async {
+ NCNetworking.shared.cancelUnifiedSearchFiles()
+
+ self.isSearching = false
+ self.literalSearch = ""
+ self.providers?.removeAll()
+ self.dataSource.clearDataSource()
+
+ self.reloadDataSource()
+ }
}
// MARK: - TAP EVENT
func accountRequestChangeAccount(account: String) {
+
NCManageDatabase.shared.setAccountActive(account)
if let activeAccount = NCManageDatabase.shared.getActiveAccount() {
@@ -737,43 +787,76 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
appDelegate.openLogin(viewController: self, selector: NCGlobal.shared.introLogin, openLoginWeb: false)
}
- func tapSwitchHeader(sender: Any) {
+ func tapButtonSwitch(_ sender: Any) {
+
+ if layoutForView?.layout == NCGlobal.shared.layoutGrid {
- if collectionView.collectionViewLayout == gridLayout {
// list layout
- header?.buttonSwitch.accessibilityLabel = NSLocalizedString("_grid_view_", comment: "")
- UIView.animate(withDuration: 0.0, animations: {
- self.collectionView.collectionViewLayout.invalidateLayout()
- self.collectionView.setCollectionViewLayout(self.listLayout, animated: false, completion: { _ in
- self.collectionView.reloadData()
- })
- })
+ headerMenu?.buttonSwitch.accessibilityLabel = NSLocalizedString("_grid_view_", comment: "")
layoutForView?.layout = NCGlobal.shared.layoutList
NCUtility.shared.setLayoutForView(key: layoutKey, serverUrl: serverUrl, layout: layoutForView?.layout)
+ self.groupByField = "name"
+ if self.dataSource.groupByField != self.groupByField {
+ self.dataSource.changeGroupByField(self.groupByField)
+ }
+
+ self.collectionView.reloadData()
+ self.collectionView.collectionViewLayout.invalidateLayout()
+ self.collectionView.setCollectionViewLayout(self.listLayout, animated: true)
+
} else {
+
// grid layout
- header?.buttonSwitch.accessibilityLabel = NSLocalizedString("_list_view_", comment: "")
- UIView.animate(withDuration: 0.0, animations: {
- self.collectionView.collectionViewLayout.invalidateLayout()
- self.collectionView.setCollectionViewLayout(self.gridLayout, animated: false, completion: { _ in
- self.collectionView.reloadData()
- })
- })
+ headerMenu?.buttonSwitch.accessibilityLabel = NSLocalizedString("_list_view_", comment: "")
layoutForView?.layout = NCGlobal.shared.layoutGrid
NCUtility.shared.setLayoutForView(key: layoutKey, serverUrl: serverUrl, layout: layoutForView?.layout)
+ if self.isSearching {
+ self.groupByField = "name"
+ } else {
+ self.groupByField = "classFile"
+ }
+ if self.dataSource.groupByField != self.groupByField {
+ self.dataSource.changeGroupByField(self.groupByField)
+ }
+
+ self.collectionView.reloadData()
+ self.collectionView.collectionViewLayout.invalidateLayout()
+ self.collectionView.setCollectionViewLayout(self.gridLayout, animated: true)
}
}
- func tapOrderHeader(sender: Any) {
+ func tapButtonOrder(_ sender: Any) {
let sortMenu = NCSortMenu()
sortMenu.toggleMenu(viewController: self, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl)
}
- func tapMoreHeader(sender: Any) { }
+ func tapButton1(_ sender: Any) {
- func tapMoreListItem(with objectId: String, namedButtonMore: String, image: UIImage?, sender: Any) {
+ NCAskAuthorization.shared.askAuthorizationPhotoLibrary(viewController: self) { hasPermission in
+ if hasPermission {
+ NCPhotosPickerViewController.init(viewController: self, maxSelectedAssets: 0, singleSelectedMode: false)
+ }
+ }
+ }
+
+ func tapButton2(_ sender: Any) {
+ guard !appDelegate.activeServerUrl.isEmpty else { return }
+ let alertController = UIAlertController.createFolder(serverUrl: appDelegate.activeServerUrl, urlBase: appDelegate)
+ appDelegate.window?.rootViewController?.present(alertController, animated: true, completion: nil)
+ }
+
+ func tapButton3(_ sender: Any) {
+
+ if #available(iOS 13.0, *) {
+ if let viewController = appDelegate.window?.rootViewController {
+ NCCreateScanDocument.shared.openScannerDocument(viewController: viewController)
+ }
+ }
+ }
+
+ func tapMoreListItem(with objectId: String, namedButtonMore: String, image: UIImage?, sender: Any) {
tapMoreGridItem(with: objectId, namedButtonMore: namedButtonMore, image: image, sender: sender)
}
@@ -798,19 +881,24 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
}
}
- func tapRichWorkspace(sender: Any) {
+ func tapRichWorkspace(_ sender: Any) {
if let navigationController = UIStoryboard(name: "NCViewerRichWorkspace", bundle: nil).instantiateInitialViewController() as? UINavigationController {
if let viewerRichWorkspace = navigationController.topViewController as? NCViewerRichWorkspace {
viewerRichWorkspace.richWorkspaceText = richWorkspaceText ?? ""
viewerRichWorkspace.serverUrl = serverUrl
-
+ viewerRichWorkspace.delegate = self
+
navigationController.modalPresentationStyle = .fullScreen
self.present(navigationController, animated: true, completion: nil)
}
}
}
+ func tapButtonSection(_ sender: Any, metadataForSection: NCMetadataForSection?) {
+ unifiedSearchMore(metadataForSection: metadataForSection)
+ }
+
func longPressListItem(with objectId: String, gestureRecognizer: UILongPressGestureRecognizer) {
}
@@ -826,13 +914,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
@objc func longPressCollecationView(_ gestureRecognizer: UILongPressGestureRecognizer) {
openMenuItems(with: nil, gestureRecognizer: gestureRecognizer)
- /*
- if #available(iOS 13.0, *) {
-
- let interaction = UIContextMenuInteraction(delegate: self)
- self.view.addInteraction(interaction)
- }
- */
}
@available(iOS 13.0, *)
@@ -863,11 +944,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
if serverUrl != "" {
listMenuItems.append(UIMenuItem(title: NSLocalizedString("_paste_file_", comment: ""), action: #selector(pasteFilesMenu)))
}
- if #available(iOS 13.0, *) {
- if !NCBrandOptions.shared.disable_background_color {
- listMenuItems.append(UIMenuItem(title: NSLocalizedString("_background_", comment: ""), action: #selector(backgroundFilesMenu)))
- }
- }
if listMenuItems.count > 0 {
UIMenuController.shared.menuItems = listMenuItems
@@ -885,11 +961,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
return true
}
}
-
- if #selector(backgroundFilesMenu) == action {
- return true
- }
-
return false
}
@@ -897,33 +968,10 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
NCFunctionCenter.shared.pastePasteboard(serverUrl: serverUrl)
}
- @objc func backgroundFilesMenu() {
-
- if let vcBackgroundImageColor = UIStoryboard(name: "NCBackgroundImageColor", bundle: nil).instantiateInitialViewController() as? NCBackgroundImageColor {
-
- vcBackgroundImageColor.delegate = self
- vcBackgroundImageColor.setupColor = collectionView.backgroundColor
- if let activeAccount = NCManageDatabase.shared.getActiveAccount() {
- vcBackgroundImageColor.lightColor = activeAccount.lightColorBackground
- vcBackgroundImageColor.darkColor = activeAccount.darkColorBackground
- }
-
- let popup = NCPopupViewController(contentController: vcBackgroundImageColor, popupWidth: vcBackgroundImageColor.width, popupHeight: vcBackgroundImageColor.height)
- popup.backgroundAlpha = 0
-
- self.present(popup, animated: true)
- }
- }
-
// MARK: - DataSource + NC Endpoint
- @objc func reloadDataSource() {
-
- if appDelegate.account == "" { return }
-
- // Get richWorkspace Text
- let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", appDelegate.account, serverUrl))
- richWorkspaceText = directory?.richWorkspace
+ @objc func reloadDataSource(forced: Bool = true) {
+ guard !appDelegate.account.isEmpty else { return }
// E2EE
isEncryptedFolder = CCUtility.isFolderEncrypted(serverUrl, e2eEncrypted: metadataFolder?.e2eEncrypted ?? false, account: appDelegate.account, urlBase: appDelegate.urlBase)
@@ -934,91 +982,138 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
// get layout for view
layoutForView = NCUtility.shared.getLayoutForView(key: layoutKey, serverUrl: serverUrl)
+
+ // set GroupField for Grid
+ if !self.isSearching && layoutForView?.layout == NCGlobal.shared.layoutGrid {
+ groupByField = "classFile"
+ } else {
+ groupByField = "name"
+ }
}
@objc func reloadDataSourceNetwork(forced: Bool = false) { }
@objc func networkSearch() {
+ guard !appDelegate.account.isEmpty, let literalSearch = literalSearch, !literalSearch.isEmpty
+ else {
+ self.refreshControl.endRefreshing()
+ return
+ }
- if appDelegate.account == "" { return }
-
- if literalSearch?.count ?? 0 > 1 {
-
- isReloadDataSourceNetworkInProgress = true
- collectionView?.reloadData()
-
- NCNetworking.shared.searchFiles(urlBase: appDelegate.urlBase, user: appDelegate.user, literal: literalSearch!) { _, metadatas, errorCode, _ in
-
+ isReloadDataSourceNetworkInProgress = true
+ self.dataSource.clearDataSource()
+ self.refreshControl.beginRefreshing()
+ self.collectionView.reloadData()
+
+ let serverVersionMajor = NCManageDatabase.shared.getCapabilitiesServerInt(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesVersionMajor)
+ if serverVersionMajor >= NCGlobal.shared.nextcloudVersion20 {
+ NCNetworking.shared.unifiedSearchFiles(urlBase: appDelegate, literal: literalSearch) { allProviders in
+ self.providers = allProviders
+ self.searchResults = []
+ self.dataSource = NCDataSource(
+ metadatas: [] ,
+ account: self.appDelegate.account,
+ sort: self.layoutForView?.sort,
+ ascending: self.layoutForView?.ascending,
+ directoryOnTop: self.layoutForView?.directoryOnTop,
+ favoriteOnTop: true,
+ filterLivePhoto: true,
+ providers: self.providers,
+ searchResults: self.searchResults)
+ } update: { id, searchResult, metadatas in
+ guard let metadatas = metadatas, metadatas.count > 0, self.isSearching , let searchResult = searchResult else { return }
+ NCOperationQueue.shared.unifiedSearchAddSection(collectionViewCommon: self, metadatas: metadatas, searchResult: searchResult)
+ } completion: {errorCode, errorDescription in
+ self.refreshControl.endRefreshing()
+ self.isReloadDataSourceNetworkInProgress = false
+ self.collectionView.reloadData()
+ }
+ } else {
+ NCNetworking.shared.searchFiles(urlBase: appDelegate, literal: literalSearch) { metadatas, errorCode, errorDescription in
DispatchQueue.main.async {
- if self.searchController?.isActive ?? false && errorCode == 0 {
- self.metadatasSource = metadatas!
- }
self.refreshControl.endRefreshing()
- self.isReloadDataSourceNetworkInProgress = false
- self.reloadDataSource()
+ self.collectionView.reloadData()
}
+ guard let metadatas = metadatas, errorCode == 0, self.isSearching else { return }
+ self.dataSource = NCDataSource(
+ metadatas: metadatas,
+ account: self.appDelegate.account,
+ sort: self.layoutForView?.sort,
+ ascending: self.layoutForView?.ascending,
+ directoryOnTop: self.layoutForView?.directoryOnTop,
+ favoriteOnTop: true,
+ filterLivePhoto: true,
+ groupByField: self.groupByField,
+ providers: self.providers,
+ searchResults: self.searchResults)
+ self.isReloadDataSourceNetworkInProgress = false
}
- } else {
- self.refreshControl.endRefreshing()
}
}
- @objc func networkReadFolder(forced: Bool, completion: @escaping(_ tableDirectory: tableDirectory?, _ metadatas: [tableMetadata]?, _ metadatasUpdate: [tableMetadata]?, _ metadatasDelete: [tableMetadata]?, _ errorCode: Int, _ errorDescription: String) -> Void) {
+ func unifiedSearchMore(metadataForSection: NCMetadataForSection?) {
- var tableDirectory: tableDirectory?
-
- NCNetworking.shared.readFile(serverUrlFileName: serverUrl, account: appDelegate.account) { account, metadataFolder, errorCode, errorDescription in
+ guard let metadataForSection = metadataForSection, let searchResult = metadataForSection.lastSearchResult, let cursor = searchResult.cursor, let term = literalSearch else { return }
- if errorCode == 0 {
+ metadataForSection.unifiedSearchInProgress = true
+ self.collectionView?.reloadData()
- if let metadataFolder = metadataFolder {
- tableDirectory = NCManageDatabase.shared.setDirectory(richWorkspace: metadataFolder.richWorkspace, serverUrl: self.serverUrl, account: account)
- }
+ NCNetworking.shared.unifiedSearchFilesProvider(urlBase: appDelegate, id: searchResult.id, term: term, limit: 5, cursor: cursor) { searchResult, metadatas, errorCode, errorDescription in
- if forced || tableDirectory?.etag != metadataFolder?.etag || metadataFolder?.e2eEncrypted ?? false {
-
- NCNetworking.shared.readFolder(serverUrl: self.serverUrl, account: self.appDelegate.account) { account, metadataFolder, metadatas, metadatasUpdate, _, metadatasDelete, errorCode, errorDescription in
-
- if errorCode == 0 {
- self.metadataFolder = metadataFolder
-
- // E2EE
- if let metadataFolder = metadataFolder {
- if metadataFolder.e2eEncrypted && CCUtility.isEnd(toEndEnabled: self.appDelegate.account) {
-
- NCCommunication.shared.getE2EEMetadata(fileId: metadataFolder.ocId, e2eToken: nil) { account, e2eMetadata, errorCode, errorDescription in
+ if errorCode != 0 {
+ NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+ }
- if errorCode == 0 && e2eMetadata != nil {
+ metadataForSection.unifiedSearchInProgress = false
+ guard let searchResult = searchResult, let metadatas = metadatas else { return }
+ self.dataSource.appendMetadatasToSection(metadatas, metadataForSection: metadataForSection, lastSearchResult: searchResult)
- if !NCEndToEndMetadata.shared.decoderMetadata(e2eMetadata!, privateKey: CCUtility.getEndToEndPrivateKey(account), serverUrl: self.serverUrl, account: account, urlBase: self.appDelegate.urlBase) {
+ DispatchQueue.main.async {
+ self.collectionView?.reloadData()
+ }
+ }
+ }
- NCContentPresenter.shared.messageNotification("_error_e2ee_", description: "_e2e_error_decode_metadata_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorDecodeMetadata)
- } else {
- self.reloadDataSource()
- }
+ @objc func networkReadFolder(forced: Bool, completion: @escaping(_ tableDirectory: tableDirectory?, _ metadatas: [tableMetadata]?, _ metadatasUpdate: [tableMetadata]?, _ metadatasDelete: [tableMetadata]?, _ errorCode: Int, _ errorDescription: String) -> Void) {
- } else if errorCode != NCGlobal.shared.errorResourceNotFound {
+ var tableDirectory: tableDirectory?
- NCContentPresenter.shared.messageNotification("_error_e2ee_", description: "_e2e_error_decode_metadata_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorDecodeMetadata)
- }
+ NCNetworking.shared.readFile(serverUrlFileName: serverUrl) { (account, metadataFolder, errorCode, errorDescription) in
+ guard errorCode == 0 else {
+ completion(nil, nil, nil, nil, errorCode, errorDescription)
+ return
+ }
- completion(tableDirectory, metadatas, metadatasUpdate, metadatasDelete, errorCode, errorDescription)
- }
+ if let metadataFolder = metadataFolder {
+ tableDirectory = NCManageDatabase.shared.setDirectory(serverUrl: self.serverUrl, richWorkspace: metadataFolder.richWorkspace, account: account)
+ }
+ if forced || tableDirectory?.etag != metadataFolder?.etag || metadataFolder?.e2eEncrypted ?? false {
+ NCNetworking.shared.readFolder(serverUrl: self.serverUrl, account: self.appDelegate.account) { account, metadataFolder, metadatas, metadatasUpdate, _, metadatasDelete, errorCode, errorDescription in
+ guard errorCode == 0 else {
+ completion(tableDirectory, nil, nil, nil, errorCode, errorDescription)
+ return
+ }
+ self.metadataFolder = metadataFolder
+ // E2EE
+ if let metadataFolder = metadataFolder, metadataFolder.e2eEncrypted, CCUtility.isEnd(toEndEnabled: self.appDelegate.account) {
+ NCCommunication.shared.getE2EEMetadata(fileId: metadataFolder.ocId, e2eToken: nil) { account, e2eMetadata, errorCode, errorDescription in
+ if errorCode == 0, let e2eMetadata = e2eMetadata {
+ if NCEndToEndMetadata.shared.decoderMetadata(e2eMetadata, privateKey: CCUtility.getEndToEndPrivateKey(account), serverUrl: self.serverUrl, account: account, urlBase: self.appDelegate.urlBase) {
+ self.reloadDataSource()
} else {
- completion(tableDirectory, metadatas, metadatasUpdate, metadatasDelete, errorCode, errorDescription)
+ NCContentPresenter.shared.messageNotification("_error_e2ee_", description: "_e2e_error_decode_metadata_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorDecodeMetadata)
}
- } else {
- completion(tableDirectory, metadatas, metadatasUpdate, metadatasDelete, errorCode, errorDescription)
+ } else if errorCode != NCGlobal.shared.errorResourceNotFound {
+ NCContentPresenter.shared.messageNotification("_error_e2ee_", description: "_e2e_error_decode_metadata_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorDecodeMetadata)
}
- } else {
- completion(tableDirectory, nil, nil, nil, errorCode, errorDescription)
+ completion(tableDirectory, metadatas, metadatasUpdate, metadatasDelete, errorCode, errorDescription)
}
+ } else {
+ completion(tableDirectory, metadatas, metadatasUpdate, metadatasDelete, errorCode, errorDescription)
}
- } else {
- completion(tableDirectory, nil, nil, nil, 0, "")
}
} else {
- completion(nil, nil, nil, nil, errorCode, errorDescription)
+ completion(tableDirectory, nil, nil, nil, 0, "")
}
}
}
@@ -1124,18 +1219,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
}
}
- // VIEW IN FOLDER
- if layoutKey == NCGlobal.shared.layoutViewViewInFolder && !pushed {
-
- if let viewController: NCFileViewInFolder = UIStoryboard(name: "NCFileViewInFolder", bundle: nil).instantiateInitialViewController() as? NCFileViewInFolder {
-
- viewController.serverUrl = serverUrlPush
- viewController.titleCurrentFolder = metadata.fileNameView
-
- pushViewController(viewController: viewController)
- }
- }
-
// SHARES ( for push use Files ... he he he )
if layoutKey == NCGlobal.shared.layoutViewShares && !pushed {
@@ -1170,6 +1253,7 @@ extension NCCollectionViewCommon: UICollectionViewDelegate {
guard let metadata = dataSource.cellForItemAt(indexPath: indexPath) else { return }
appDelegate.activeMetadata = metadata
+ let metadataSourceForAllSections = dataSource.getMetadataSourceForAllSections()
if isEditMode {
if let index = selectOcId.firstIndex(of: metadata.ocId) {
@@ -1178,7 +1262,7 @@ extension NCCollectionViewCommon: UICollectionViewDelegate {
selectOcId.append(metadata.ocId)
}
collectionView.reloadItems(at: [indexPath])
- self.navigationItem.title = NSLocalizedString("_selected_", comment: "") + " : \(selectOcId.count)" + " / \(dataSource.metadatas.count)"
+ self.navigationItem.title = NSLocalizedString("_selected_", comment: "") + " : \(selectOcId.count)" + " / \(metadataSourceForAllSections.count)"
return
}
@@ -1191,13 +1275,13 @@ extension NCCollectionViewCommon: UICollectionViewDelegate {
pushMetadata(metadata)
- } else if !(self is NCFileViewInFolder) {
+ } else {
let imageIcon = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag))
if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
var metadatas: [tableMetadata] = []
- for metadata in dataSource.metadatas {
+ for metadata in metadataSourceForAllSections {
if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
metadatas.append(metadata)
}
@@ -1226,8 +1310,9 @@ extension NCCollectionViewCommon: UICollectionViewDelegate {
@available(iOS 13.0, *)
func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
- if isEditMode { return nil }
guard let metadata = dataSource.cellForItemAt(indexPath: indexPath) else { return nil }
+ if isEditMode || metadata.classFile == NCCommunicationCommon.typeClassFile.url.rawValue { return nil }
+
let identifier = indexPath as NSCopying
var image: UIImage?
let cell = collectionView.cellForItem(at: indexPath)
@@ -1249,8 +1334,8 @@ extension NCCollectionViewCommon: UICollectionViewDelegate {
@available(iOS 13.0, *)
func collectionView(_ collectionView: UICollectionView, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating) {
- animator.addCompletion {
+ animator.addCompletion {
if let indexPath = configuration.identifier as? IndexPath {
self.collectionView(collectionView, didSelectItemAt: indexPath)
}
@@ -1260,49 +1345,72 @@ extension NCCollectionViewCommon: UICollectionViewDelegate {
extension NCCollectionViewCommon: UICollectionViewDataSource {
- func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
-
- if kind == UICollectionView.elementKindSectionHeader {
-
- let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionHeaderMenu", for: indexPath) as! NCSectionHeaderMenu
- self.header = header
-
- if collectionView.collectionViewLayout == gridLayout {
- header.buttonSwitch.setImage(UIImage(named: "switchList")!.image(color: NCBrandColor.shared.gray, size: 50), for: .normal)
- header.buttonSwitch.accessibilityLabel = NSLocalizedString("_list_view_", comment: "")
- } else {
- header.buttonSwitch.setImage(UIImage(named: "switchGrid")!.image(color: NCBrandColor.shared.gray, size: 50), for: .normal)
- header.buttonSwitch.accessibilityLabel = NSLocalizedString("_grid_view_", comment: "")
- }
-
- header.delegate = self
- header.setStatusButton(count: dataSource.metadatas.count)
- header.setTitleSorted(datasourceTitleButton: layoutForView?.titleButtonHeader ?? "")
- header.viewRichWorkspaceHeightConstraint.constant = headerRichWorkspaceHeight
- header.setRichWorkspaceText(richWorkspaceText: richWorkspaceText)
-
- return header
-
- } else {
-
- let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as! NCSectionFooter
-
- let info = dataSource.getFilesInformation()
- footer.setTitleLabel(directories: info.directories, files: info.files, size: info.size )
-
- return footer
- }
- }
-
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
guard let metadata = dataSource.cellForItemAt(indexPath: indexPath) else { return }
// Thumbnail
if !metadata.directory {
- if FileManager().fileExists(atPath: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) {
- (cell as! NCCellProtocol).filePreviewImageView?.image = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag))
+ if metadata.name == NCGlobal.shared.appName {
+
+ let filePath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
+ let iconImagePath = CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)!
+
+ if FileManager().fileExists(atPath: iconImagePath) {
+ (cell as! NCCellProtocol).filePreviewImageView?.image = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag))
+ } else if metadata.status > NCGlobal.shared.metadataStatusNormal && metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && FileManager().fileExists(atPath: filePath) {
+ if let image = UIImage(contentsOfFile: filePath), let image = image.resizeImage(size: CGSize(width: NCGlobal.shared.sizeIcon, height: NCGlobal.shared.sizeIcon), isAspectRation: true), let data = image.jpegData(compressionQuality: 0.5) {
+ do {
+ try data.write(to: URL.init(fileURLWithPath: iconImagePath), options: .atomic)
+ (cell as! NCCellProtocol).filePreviewImageView?.image = image
+ } catch { }
+ }
+ } else if metadata.status > NCGlobal.shared.metadataStatusNormal && metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue && FileManager().fileExists(atPath: filePath) {
+ if let image = NCUtility.shared.imageFromVideo(url: URL(fileURLWithPath: filePath), at: 0), let image = image.resizeImage(size: CGSize(width: NCGlobal.shared.sizeIcon, height: NCGlobal.shared.sizeIcon), isAspectRation: true), let data = image.jpegData(compressionQuality: 0.5) {
+ do {
+ try data.write(to: URL.init(fileURLWithPath: iconImagePath), options: .atomic)
+ (cell as! NCCellProtocol).filePreviewImageView?.image = image
+ } catch { }
+ }
+ } else {
+ NCOperationQueue.shared.downloadThumbnail(metadata: metadata, placeholder: true, cell: cell, view: collectionView)
+ }
} else {
- NCOperationQueue.shared.downloadThumbnail(metadata: metadata, placeholder: true, cell: cell, view: collectionView)
+ // Unified search
+ switch metadata.iconName {
+ case let str where str.contains("contacts"):
+ (cell as! NCCellProtocol).filePreviewImageView?.image = NCBrandColor.cacheImages.iconContacts
+ case let str where str.contains("conversation"):
+ (cell as! NCCellProtocol).filePreviewImageView?.image = NCBrandColor.cacheImages.iconTalk
+ case let str where str.contains("calendar"):
+ (cell as! NCCellProtocol).filePreviewImageView?.image = NCBrandColor.cacheImages.iconCalendar
+ case let str where str.contains("deck"):
+ (cell as! NCCellProtocol).filePreviewImageView?.image = NCBrandColor.cacheImages.iconDeck
+ case let str where str.contains("mail"):
+ (cell as! NCCellProtocol).filePreviewImageView?.image = NCBrandColor.cacheImages.iconMail
+ case let str where str.contains("talk"):
+ (cell as! NCCellProtocol).filePreviewImageView?.image = NCBrandColor.cacheImages.iconTalk
+ case let str where str.contains("confirm"):
+ (cell as! NCCellProtocol).filePreviewImageView?.image = NCBrandColor.cacheImages.iconConfirm
+ case let str where str.contains("pages"):
+ (cell as! NCCellProtocol).filePreviewImageView?.image = NCBrandColor.cacheImages.iconPages
+ default:
+ (cell as! NCCellProtocol).filePreviewImageView?.image = NCBrandColor.cacheImages.file
+ }
+
+ if !metadata.iconUrl.isEmpty {
+ if let ownerId = NCUtility.shared.getAvatarFromIconUrl(metadata: metadata), let cell = cell as? NCCellProtocol {
+ let fileName = metadata.userBaseUrl + "-" + ownerId + ".png"
+ NCOperationQueue.shared.downloadAvatar(user: ownerId, dispalyName: nil, fileName: fileName, cell: cell, view: collectionView, cellImageView: cell.filePreviewImageView)
+ }
+ }
+
+// if metadata.iconName.contains("contacts"), let subline = metadata.subline, !subline.isEmpty, let cell = cell as? NCCellProtocol {
+// let components = subline.components(separatedBy: "@")
+// if let user = components.first {
+// let fileName = metadata.userBaseUrl + "-" + user + ".png"
+// NCOperationQueue.shared.downloadAvatar(user: user, dispalyName: nil, fileName: fileName, cell: cell, view: collectionView, cellImageView: cell.filePreviewImageView)
+// }
+// }
}
}
@@ -1312,384 +1420,433 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
appDelegate.account == metadata.account,
let cell = cell as? NCCellProtocol {
let fileName = metadata.userBaseUrl + "-" + metadata.ownerId + ".png"
- NCOperationQueue.shared.downloadAvatar(user: metadata.ownerId, dispalyName: metadata.ownerDisplayName, fileName: fileName, cell: cell, view: collectionView)
+ NCOperationQueue.shared.downloadAvatar(user: metadata.ownerId, dispalyName: metadata.ownerDisplayName, fileName: fileName, cell: cell, view: collectionView, cellImageView: cell.fileAvatarImageView)
}
}
- func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
-
- }
+ func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { }
func numberOfSections(in collectionView: UICollectionView) -> Int {
- return 1
+ return dataSource.numberOfSections()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
- let numberItems = dataSource.numberOfItems()
+
+ let numberItems = dataSource.numberOfItemsInSection(section)
emptyDataSet?.numberOfItemsInSection(numberItems, section: section)
return numberItems
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
- guard let metadata = dataSource.cellForItemAt(indexPath: indexPath) else {
- if layoutForView?.layout == NCGlobal.shared.layoutList {
- return collectionView.dequeueReusableCell(withReuseIdentifier: "listCell", for: indexPath) as! NCListCell
- } else {
- return collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as! NCGridCell
- }
+ var cell: NCCellProtocol & UICollectionViewCell
+
+ // LAYOUT LIST
+ if layoutForView?.layout == NCGlobal.shared.layoutList {
+ guard let listCell = collectionView.dequeueReusableCell(withReuseIdentifier: "listCell", for: indexPath) as? NCListCell else { return UICollectionViewCell() }
+ listCell.delegate = self
+ cell = listCell
+ } else {
+ // LAYOUT GRID
+ guard let gridCell = collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as? NCGridCell else { return UICollectionViewCell() }
+ gridCell.delegate = self
+ cell = gridCell
}
- var tableShare: tableShare?
+ guard let metadata = dataSource.cellForItemAt(indexPath: indexPath) else { return cell }
+
+ let tableShare = dataSource.metadatasForSection[indexPath.section].metadataShare[metadata.ocId]
+ let tableDirectory = dataSource.metadatasForSection[indexPath.section].directories?.filter({ $0.ocId == metadata.ocId }).first
var isShare = false
var isMounted = false
+ var a11yValues: [String] = []
if metadataFolder != nil {
isShare = metadata.permissions.contains(NCGlobal.shared.permissionShared) && !metadataFolder!.permissions.contains(NCGlobal.shared.permissionShared)
isMounted = metadata.permissions.contains(NCGlobal.shared.permissionMounted) && !metadataFolder!.permissions.contains(NCGlobal.shared.permissionMounted)
}
- if dataSource.metadataShare[metadata.ocId] != nil {
- tableShare = dataSource.metadataShare[metadata.ocId]
+ cell.fileSelectImage?.image = nil
+ cell.fileStatusImage?.image = nil
+ cell.fileLocalImage?.image = nil
+ cell.fileFavoriteImage?.image = nil
+ cell.fileSharedImage?.image = nil
+ cell.fileMoreImage?.image = nil
+ cell.filePreviewImageView?.image = nil
+ cell.filePreviewImageView?.backgroundColor = nil
+ cell.fileObjectId = metadata.ocId
+ cell.fileUser = metadata.ownerId
+ cell.fileProgressView?.isHidden = true
+ cell.fileProgressView?.progress = 0.0
+ cell.hideButtonShare(false)
+ cell.hideButtonMore(false)
+ cell.titleInfoTrailingDefault()
+
+ if isSearching {
+ cell.fileTitleLabel?.text = metadata.fileName
+ cell.fileTitleLabel?.lineBreakMode = .byTruncatingTail
+ if metadata.name == NCGlobal.shared.appName {
+ cell.fileInfoLabel?.text = NSLocalizedString("_in_", comment: "") + " " + NCUtilityFileSystem.shared.getPath(metadata: metadata, withFileName: false)
+ } else {
+ cell.fileInfoLabel?.text = metadata.subline
+ cell.titleInfoTrailingFull()
+ }
+ } else {
+ cell.fileTitleLabel?.text = metadata.fileNameView
+ cell.fileTitleLabel?.lineBreakMode = .byTruncatingMiddle
+ cell.writeInfoDateSize(date: metadata.date, size: metadata.size)
}
- //
- // LAYOUT LIST
- //
- if layoutForView?.layout == NCGlobal.shared.layoutList {
-
- let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "listCell", for: indexPath) as! NCListCell
- cell.delegate = self
+ if metadata.status == NCGlobal.shared.metadataStatusDownloading || metadata.status == NCGlobal.shared.metadataStatusUploading {
+ cell.fileProgressView?.isHidden = false
+ }
- cell.fileObjectId = metadata.ocId
- cell.fileUser = metadata.ownerId
- if isSearching {
- cell.labelTitle.text = NCUtilityFileSystem.shared.getPath(metadata: metadata)
- cell.labelTitle.lineBreakMode = .byTruncatingHead
- } else {
- cell.labelTitle.text = metadata.fileNameView
- cell.labelTitle.lineBreakMode = .byTruncatingMiddle
+ // Accessibility [shared]
+ if metadata.ownerId != appDelegate.userId, appDelegate.account == metadata.account {
+ a11yValues.append(NSLocalizedString("_shared_with_you_by_", comment: "") + " " + metadata.ownerDisplayName)
+ }
- }
- cell.labelTitle.textColor = NCBrandColor.shared.label
- cell.labelInfo.text = CCUtility.dateDiff(metadata.date as Date) + " · " + CCUtility.transformedSize(metadata.size)
- cell.labelInfo.textColor = NCBrandColor.shared.systemGray
-
- cell.imageSelect.image = nil
- cell.imageStatus.image = nil
- cell.imageLocal.image = nil
- cell.imageFavorite.image = nil
- cell.imageShared.image = nil
- cell.imageMore.image = nil
-
- cell.imageItem.image = nil
- cell.imageItem.backgroundColor = nil
-
- // Progress
- var progress: Float = 0.0
- var totalBytes: Int64 = 0
- if let progressType = appDelegate.listProgress[metadata.ocId] {
- progress = progressType.progress
- totalBytes = progressType.totalBytes
- }
+ if metadata.directory {
- if metadata.status == NCGlobal.shared.metadataStatusDownloading || metadata.status == NCGlobal.shared.metadataStatusUploading {
- cell.progressView.isHidden = false
- cell.progressView.progress = progress
+ if metadata.e2eEncrypted {
+ cell.filePreviewImageView?.image = NCBrandColor.cacheImages.folderEncrypted
+ } else if isShare {
+ cell.filePreviewImageView?.image = NCBrandColor.cacheImages.folderSharedWithMe
+ } else if tableShare != nil && tableShare?.shareType != 3 {
+ cell.filePreviewImageView?.image = NCBrandColor.cacheImages.folderSharedWithMe
+ } else if tableShare != nil && tableShare?.shareType == 3 {
+ cell.filePreviewImageView?.image = NCBrandColor.cacheImages.folderPublic
+ } else if metadata.mountType == "group" {
+ cell.filePreviewImageView?.image = NCBrandColor.cacheImages.folderGroup
+ } else if isMounted {
+ cell.filePreviewImageView?.image = NCBrandColor.cacheImages.folderExternal
+ } else if metadata.fileName == autoUploadFileName && metadata.serverUrl == autoUploadDirectory {
+ cell.filePreviewImageView?.image = NCBrandColor.cacheImages.folderAutomaticUpload
+ if cell is NCListCell {
+ cell.fileTitleLabel?.text = (cell.fileTitleLabel?.text ?? "") + " - " + NSLocalizedString("_auto_upload_folder_", comment: "")
+ }
} else {
- cell.progressView.isHidden = true
- cell.progressView.progress = 0.0
+ cell.filePreviewImageView?.image = NCBrandColor.cacheImages.folder
}
- var a11yValues: [String] = []
- if metadata.ownerId != appDelegate.userId, appDelegate.account == metadata.account {
- a11yValues.append(NSLocalizedString("_shared_with_you_by_", comment: "") + " " + metadata.ownerDisplayName)
+ // Local image: offline
+ if let tableDirectory = tableDirectory, tableDirectory.offline {
+ cell.fileLocalImage?.image = NCBrandColor.cacheImages.offlineFlag
}
- if metadata.directory {
-
- if metadata.e2eEncrypted {
- cell.imageItem.image = NCBrandColor.cacheImages.folderEncrypted
- } else if isShare {
- cell.imageItem.image = NCBrandColor.cacheImages.folderSharedWithMe
- } else if tableShare != nil && tableShare?.shareType != 3 {
- cell.imageItem.image = NCBrandColor.cacheImages.folderSharedWithMe
- } else if tableShare != nil && tableShare?.shareType == 3 {
- cell.imageItem.image = NCBrandColor.cacheImages.folderPublic
- } else if metadata.mountType == "group" {
- cell.imageItem.image = NCBrandColor.cacheImages.folderGroup
- } else if isMounted {
- cell.imageItem.image = NCBrandColor.cacheImages.folderExternal
- } else if metadata.fileName == autoUploadFileName && metadata.serverUrl == autoUploadDirectory {
- cell.imageItem.image = NCBrandColor.cacheImages.folderAutomaticUpload
- } else {
- cell.imageItem.image = NCBrandColor.cacheImages.folder
- }
-
- let lockServerUrl = CCUtility.stringAppendServerUrl(metadata.serverUrl, addFileName: metadata.fileName)!
- let tableDirectory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", appDelegate.account, lockServerUrl))
+ // color folder
+ cell.filePreviewImageView?.image = cell.filePreviewImageView?.image?.colorizeFolder(metadata: metadata, tableDirectory: tableDirectory)
- // Local image: offline
- if tableDirectory != nil && tableDirectory!.offline {
- cell.imageLocal.image = NCBrandColor.cacheImages.offlineFlag
- }
-
- } else {
+ } else {
- // image local
- if dataSource.metadataOffLine.contains(metadata.ocId) {
- a11yValues.append(NSLocalizedString("_offline_", comment: ""))
- cell.imageLocal.image = NCBrandColor.cacheImages.offlineFlag
- } else if CCUtility.fileProviderStorageExists(metadata) {
- cell.imageLocal.image = NCBrandColor.cacheImages.local
- }
+ // image local
+ if dataSource.metadatasForSection[indexPath.section].metadataOffLine.contains(metadata.ocId) {
+ a11yValues.append(NSLocalizedString("_offline_", comment: ""))
+ cell.fileLocalImage?.image = NCBrandColor.cacheImages.offlineFlag
+ } else if CCUtility.fileProviderStorageExists(metadata) {
+ cell.fileLocalImage?.image = NCBrandColor.cacheImages.local
}
+ }
- // image Favorite
- if metadata.favorite {
- cell.imageFavorite.image = NCBrandColor.cacheImages.favorite
- a11yValues.append(NSLocalizedString("_favorite_", comment: ""))
- }
+ // image Favorite
+ if metadata.favorite {
+ cell.fileFavoriteImage?.image = NCBrandColor.cacheImages.favorite
+ a11yValues.append(NSLocalizedString("_favorite_", comment: ""))
+ }
- // Share image
- if isShare {
- cell.imageShared.image = NCBrandColor.cacheImages.shared
- } else if tableShare != nil && tableShare?.shareType == 3 {
- cell.imageShared.image = NCBrandColor.cacheImages.shareByLink
- } else if tableShare != nil && tableShare?.shareType != 3 {
- cell.imageShared.image = NCBrandColor.cacheImages.shared
- } else {
- cell.imageShared.image = NCBrandColor.cacheImages.canShare
- }
- if appDelegate.account != metadata.account {
- cell.imageShared.image = NCBrandColor.cacheImages.shared
- }
+ // Share image
+ if isShare {
+ cell.fileSharedImage?.image = NCBrandColor.cacheImages.shared
+ } else if tableShare != nil && tableShare?.shareType == 3 {
+ cell.fileSharedImage?.image = NCBrandColor.cacheImages.shareByLink
+ } else if tableShare != nil && tableShare?.shareType != 3 {
+ cell.fileSharedImage?.image = NCBrandColor.cacheImages.shared
+ } else {
+ cell.fileSharedImage?.image = NCBrandColor.cacheImages.canShare
+ }
+ if appDelegate.account != metadata.account {
+ cell.fileSharedImage?.image = NCBrandColor.cacheImages.shared
+ }
- if metadata.status == NCGlobal.shared.metadataStatusInDownload || metadata.status == NCGlobal.shared.metadataStatusDownloading || metadata.status == NCGlobal.shared.metadataStatusInUpload || metadata.status == NCGlobal.shared.metadataStatusUploading {
- cell.setButtonMore(named: NCGlobal.shared.buttonMoreStop, image: NCBrandColor.cacheImages.buttonStop)
- } else if metadata.lock == true {
- cell.setButtonMore(named: NCGlobal.shared.buttonMoreLock, image: NCBrandColor.cacheImages.buttonMoreLock)
- a11yValues.append(String(format: NSLocalizedString("_locked_by_", comment: ""), metadata.lockOwnerDisplayName))
+ // Button More
+ if metadata.status == NCGlobal.shared.metadataStatusInDownload || metadata.status == NCGlobal.shared.metadataStatusDownloading || metadata.status == NCGlobal.shared.metadataStatusInUpload || metadata.status == NCGlobal.shared.metadataStatusUploading {
+ cell.setButtonMore(named: NCGlobal.shared.buttonMoreStop, image: NCBrandColor.cacheImages.buttonStop)
+ } else if metadata.lock == true {
+ cell.setButtonMore(named: NCGlobal.shared.buttonMoreLock, image: NCBrandColor.cacheImages.buttonMoreLock)
+ a11yValues.append(String(format: NSLocalizedString("_locked_by_", comment: ""), metadata.lockOwnerDisplayName))
+ } else {
+ cell.setButtonMore(named: NCGlobal.shared.buttonMoreMore, image: NCBrandColor.cacheImages.buttonMore)
+ }
+
+ // Write status on Label Info
+ switch metadata.status {
+ case NCGlobal.shared.metadataStatusWaitDownload:
+ cell.fileInfoLabel?.text = CCUtility.transformedSize(metadata.size) + " - " + NSLocalizedString("_status_wait_download_", comment: "")
+ break
+ case NCGlobal.shared.metadataStatusInDownload:
+ cell.fileInfoLabel?.text = CCUtility.transformedSize(metadata.size) + " - " + NSLocalizedString("_status_in_download_", comment: "")
+ break
+ case NCGlobal.shared.metadataStatusDownloading:
+ cell.fileInfoLabel?.text = CCUtility.transformedSize(metadata.size) + " - ↓ …"
+ break
+ case NCGlobal.shared.metadataStatusWaitUpload:
+ cell.fileInfoLabel?.text = CCUtility.transformedSize(metadata.size) + " - " + NSLocalizedString("_status_wait_upload_", comment: "")
+ break
+ case NCGlobal.shared.metadataStatusInUpload:
+ cell.fileInfoLabel?.text = CCUtility.transformedSize(metadata.size) + " - " + NSLocalizedString("_status_in_upload_", comment: "")
+ break
+ case NCGlobal.shared.metadataStatusUploading:
+ cell.fileInfoLabel?.text = CCUtility.transformedSize(metadata.size) + " - ↑ …"
+ break
+ case NCGlobal.shared.metadataStatusUploadError:
+ if metadata.sessionError != "" {
+ cell.fileInfoLabel?.text = NSLocalizedString("_status_wait_upload_", comment: "") + " " + metadata.sessionError
} else {
- cell.setButtonMore(named: NCGlobal.shared.buttonMoreMore, image: NCBrandColor.cacheImages.buttonMore)
+ cell.fileInfoLabel?.text = NSLocalizedString("_status_wait_upload_", comment: "")
}
+ break
+ default:
+ break
+ }
- // Write status on Label Info
- switch metadata.status {
- case NCGlobal.shared.metadataStatusWaitDownload:
- cell.labelInfo.text = CCUtility.transformedSize(metadata.size) + " - " + NSLocalizedString("_status_wait_download_", comment: "")
- break
- case NCGlobal.shared.metadataStatusInDownload:
- cell.labelInfo.text = CCUtility.transformedSize(metadata.size) + " - " + NSLocalizedString("_status_in_download_", comment: "")
- break
- case NCGlobal.shared.metadataStatusDownloading:
- cell.labelInfo.text = CCUtility.transformedSize(metadata.size) + " - ↓ " + CCUtility.transformedSize(totalBytes)
- break
- case NCGlobal.shared.metadataStatusWaitUpload:
- cell.labelInfo.text = CCUtility.transformedSize(metadata.size) + " - " + NSLocalizedString("_status_wait_upload_", comment: "")
- break
- case NCGlobal.shared.metadataStatusInUpload:
- cell.labelInfo.text = CCUtility.transformedSize(metadata.size) + " - " + NSLocalizedString("_status_in_upload_", comment: "")
- break
- case NCGlobal.shared.metadataStatusUploading:
- cell.labelInfo.text = CCUtility.transformedSize(metadata.size) + " - ↑ " + CCUtility.transformedSize(totalBytes)
- break
- case NCGlobal.shared.metadataStatusUploadError:
- if metadata.sessionError != "" {
- cell.labelInfo.text = NSLocalizedString("_status_wait_upload_", comment: "") + " " + metadata.sessionError
- } else {
- cell.labelInfo.text = NSLocalizedString("_status_wait_upload_", comment: "")
- }
- break
- default:
- break
- }
+ // Live Photo
+ if metadata.livePhoto {
+ cell.fileStatusImage?.image = NCBrandColor.cacheImages.livePhoto
+ a11yValues.append(NSLocalizedString("_upload_mov_livephoto_", comment: ""))
+ }
- cell.accessibilityLabel = metadata.fileNameView + ", " + (cell.labelInfo.text ?? "")
+ // E2EE
+ if metadata.e2eEncrypted || isEncryptedFolder {
+ cell.hideButtonShare(true)
+ }
- // Live Photo
- if metadata.livePhoto {
- cell.imageStatus.image = NCBrandColor.cacheImages.livePhoto
- a11yValues.append(NSLocalizedString("_upload_mov_livephoto_", comment: ""))
+ // URL
+ if metadata.classFile == NCCommunicationCommon.typeClassFile.url.rawValue {
+ cell.fileLocalImage?.image = nil
+ cell.hideButtonShare(true)
+ cell.hideButtonMore(true)
+ if let ownerId = NCUtility.shared.getAvatarFromIconUrl(metadata: metadata) {
+ cell.fileUser = ownerId
}
+ }
- // E2EE
- if metadata.e2eEncrypted || isEncryptedFolder {
- cell.hideButtonShare(true)
- } else {
- cell.hideButtonShare(false)
- }
+ // Disable Share Button
+ if appDelegate.disableSharesView {
+ cell.hideButtonShare(true)
+ }
- // Remove last separator
- if collectionView.numberOfItems(inSection: indexPath.section) == indexPath.row + 1 {
- cell.separator.isHidden = true
- } else {
- cell.separator.isHidden = false
- }
+ // Separator
+ if collectionView.numberOfItems(inSection: indexPath.section) == indexPath.row + 1 || isSearching {
+ cell.cellSeparatorView?.isHidden = true
+ } else {
+ cell.cellSeparatorView?.isHidden = false
+ }
- // Edit mode
- if isEditMode {
- cell.selectMode(true)
- if selectOcId.contains(metadata.ocId) {
- cell.selected(true)
- a11yValues.append(NSLocalizedString("_selected_", comment: ""))
- } else {
- cell.selected(false)
- }
+ // Edit mode
+ if isEditMode {
+ cell.selectMode(true)
+ if selectOcId.contains(metadata.ocId) {
+ cell.selected(true)
+ a11yValues.append(NSLocalizedString("_selected_", comment: ""))
} else {
- cell.selectMode(false)
+ cell.selected(false)
}
- cell.accessibilityValue = a11yValues.joined(separator: ", ")
-
- // Disable Share Button
- if appDelegate.disableSharesView {
- cell.hideButtonShare(true)
- }
-
- return cell
+ } else {
+ cell.selectMode(false)
}
- //
- // LAYOUT GRID
- //
- if layoutForView?.layout == NCGlobal.shared.layoutGrid {
+ // Accessibility
+ cell.setAccessibility(label: metadata.fileNameView + ", " + (cell.fileInfoLabel?.text ?? ""), value: a11yValues.joined(separator: ", "))
- let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as! NCGridCell
- cell.delegate = self
+ // Color string find in search
+ if isSearching, let literalSearch = self.literalSearch, let title = cell.fileTitleLabel?.text {
+ let longestWordRange = (title.lowercased() as NSString).range(of: literalSearch)
+ let attributedString = NSMutableAttributedString(string: title, attributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 15)])
+ attributedString.setAttributes([NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 15), NSAttributedString.Key.foregroundColor : NCBrandColor.shared.annotationColor], range: longestWordRange)
+ cell.fileTitleLabel?.attributedText = attributedString
+ }
+ return cell
+ }
- cell.fileObjectId = metadata.ocId
- cell.fileUser = metadata.ownerId
- cell.labelTitle.text = metadata.fileNameView
- cell.labelTitle.textColor = NCBrandColor.shared.label
+ func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
- cell.imageSelect.image = nil
- cell.imageStatus.image = nil
- cell.imageLocal.image = nil
- cell.imageFavorite.image = nil
+ if kind == UICollectionView.elementKindSectionHeader {
- cell.imageItem.image = nil
- cell.imageItem.backgroundColor = nil
+ if indexPath.section == 0 {
- // Progress
- var progress: Float = 0.0
- if let progressType = appDelegate.listProgress[metadata.ocId] {
- progress = progressType.progress
- }
+ let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionHeaderMenu", for: indexPath) as! NCSectionHeaderMenu
+ let (_, heightHeaderRichWorkspace, heightHeaderSection) = getHeaderHeight(section: indexPath.section)
- if metadata.status == NCGlobal.shared.metadataStatusDownloading || metadata.status == NCGlobal.shared.metadataStatusUploading {
- cell.progressView.isHidden = false
- cell.progressView.progress = progress
- cell.accessibilityLabel = metadata.fileNameView + ", \(Int(progress * 100))%"
- } else {
- cell.progressView.isHidden = true
- cell.progressView.progress = 0.0
- cell.accessibilityLabel = metadata.fileNameView
- }
+ self.headerMenu = header
- var a11yValues: [String] = []
- if metadata.ownerId != appDelegate.userId, appDelegate.account == metadata.account {
- a11yValues.append(NSLocalizedString("_shared_with_you_by_", comment: "") + " " + metadata.ownerDisplayName)
- }
+ if layoutForView?.layout == NCGlobal.shared.layoutGrid {
+ header.setImageSwitchList()
+ header.buttonSwitch.accessibilityLabel = NSLocalizedString("_list_view_", comment: "")
+ } else {
+ header.setImageSwitchGrid()
+ header.buttonSwitch.accessibilityLabel = NSLocalizedString("_grid_view_", comment: "")
+ }
- if metadata.directory {
-
- if metadata.e2eEncrypted {
- cell.imageItem.image = NCBrandColor.cacheImages.folderEncrypted
- } else if isShare {
- cell.imageItem.image = NCBrandColor.cacheImages.folderSharedWithMe
- } else if tableShare != nil && tableShare!.shareType != 3 {
- cell.imageItem.image = NCBrandColor.cacheImages.folderSharedWithMe
- } else if tableShare != nil && tableShare!.shareType == 3 {
- cell.imageItem.image = NCBrandColor.cacheImages.folderPublic
- } else if metadata.mountType == "group" {
- cell.imageItem.image = NCBrandColor.cacheImages.folderGroup
- } else if isMounted {
- cell.imageItem.image = NCBrandColor.cacheImages.folderExternal
- } else if metadata.fileName == autoUploadFileName && metadata.serverUrl == autoUploadDirectory {
- cell.imageItem.image = NCBrandColor.cacheImages.folderAutomaticUpload
+ header.delegate = self
+ if headerMenuButtonsCommand && !isSearching {
+ header.setButtonsCommand(heigt: NCGlobal.shared.heightButtonsCommand, imageButton1: UIImage(named: "buttonAddImage"), titleButton1: NSLocalizedString("_upload_", comment: ""), imageButton2: UIImage(named: "buttonAddFolder"), titleButton2: NSLocalizedString("_folder_", comment: ""), imageButton3: UIImage(named: "buttonAddScan"), titleButton3: NSLocalizedString("_scan_", comment: ""))
+ } else {
+ header.setButtonsCommand(heigt: 0)
+ }
+ if headerMenuButtonsView {
+ header.setStatusButtonsView(enable: !dataSource.getMetadataSourceForAllSections().isEmpty)
+ header.setButtonsView(heigt: NCGlobal.shared.heightButtonsView)
+ header.setSortedTitle(layoutForView?.titleButtonHeader ?? "")
} else {
- cell.imageItem.image = NCBrandColor.cacheImages.folder
+ header.setButtonsView(heigt: 0)
}
- let lockServerUrl = CCUtility.stringAppendServerUrl(metadata.serverUrl, addFileName: metadata.fileName)!
- let tableDirectory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", appDelegate.account, lockServerUrl))
+ header.setRichWorkspaceHeight(heightHeaderRichWorkspace)
+ header.setRichWorkspaceText(richWorkspaceText)
- // Local image: offline
- if tableDirectory != nil && tableDirectory!.offline {
- cell.imageLocal.image = NCBrandColor.cacheImages.offlineFlag
+ header.setSectionHeight(heightHeaderSection)
+ if heightHeaderSection == 0 {
+ header.labelSection.text = ""
+
+ } else {
+ header.labelSection.text = self.dataSource.getSectionValue(indexPath: indexPath)
}
+ header.labelSection.textColor = NCBrandColor.shared.label
+
+ return header
} else {
- // image Local
- if dataSource.metadataOffLine.contains(metadata.ocId) {
- cell.imageLocal.image = NCBrandColor.cacheImages.offlineFlag
- a11yValues.append(NSLocalizedString("_offline_", comment: ""))
- } else if CCUtility.fileProviderStorageExists(metadata) {
- cell.imageLocal.image = NCBrandColor.cacheImages.local
- }
- }
+ let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionHeader", for: indexPath) as! NCSectionHeader
- // image Favorite
- if metadata.favorite {
- cell.imageFavorite.image = NCBrandColor.cacheImages.favorite
- a11yValues.append(NSLocalizedString("_favorite_", comment: ""))
- }
+ header.labelSection.text = self.dataSource.getSectionValue(indexPath: indexPath)
+ header.labelSection.textColor = NCBrandColor.shared.label
- // Transfer
- if metadata.status == NCGlobal.shared.metadataStatusInDownload || metadata.status == NCGlobal.shared.metadataStatusDownloading || metadata.status == NCGlobal.shared.metadataStatusInUpload || metadata.status == NCGlobal.shared.metadataStatusUploading {
- cell.setButtonMore(named: NCGlobal.shared.buttonMoreStop, image: NCBrandColor.cacheImages.buttonStop)
- } else if metadata.lock == true {
- cell.setButtonMore(named: NCGlobal.shared.buttonMoreLock, image: NCBrandColor.cacheImages.buttonMoreLock)
- a11yValues.append(String(format: NSLocalizedString("_locked_by_", comment: ""), metadata.lockOwnerDisplayName))
- } else {
- cell.setButtonMore(named: NCGlobal.shared.buttonMoreMore, image: NCBrandColor.cacheImages.buttonMore)
+ return header
}
- // Live Photo
- if metadata.livePhoto {
- cell.imageStatus.image = NCBrandColor.cacheImages.livePhoto
- a11yValues.append(NSLocalizedString("_upload_mov_livephoto_", comment: ""))
- }
+ } else {
- // Edit mode
- if isEditMode {
- cell.selectMode(true)
- if selectOcId.contains(metadata.ocId) {
- cell.selected(true)
- a11yValues.append(NSLocalizedString("_selected_", comment: ""))
- } else {
- cell.selected(false)
+ let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as! NCSectionFooter
+ let sections = dataSource.numberOfSections()
+ let section = indexPath.section
+ let metadataForSection = self.dataSource.getMetadataForSection(indexPath.section)
+ let isPaginated = metadataForSection?.lastSearchResult?.isPaginated ?? false
+ let metadatasCount: Int = metadataForSection?.metadatas.count ?? 0
+ let unifiedSearchInProgress = metadataForSection?.unifiedSearchInProgress ?? false
+
+ footer.delegate = self
+ footer.metadataForSection = metadataForSection
+
+ footer.setTitleLabel("")
+ footer.setButtonText(NSLocalizedString("_show_more_results_", comment: ""))
+ footer.separatorIsHidden(true)
+ footer.buttonIsHidden(true)
+ footer.hideActivityIndicatorSection()
+
+ if isSearching {
+ if sections > 1 && section != sections - 1 {
+ footer.separatorIsHidden(false)
+ }
+ if isSearching && isPaginated && metadatasCount > 0 {
+ footer.buttonIsHidden(false)
+ }
+ if unifiedSearchInProgress {
+ footer.showActivityIndicatorSection()
}
} else {
- cell.selectMode(false)
+ if sections == 1 || section == sections - 1 {
+ let info = dataSource.getFooterInformationAllMetadatas()
+ footer.setTitleLabel(directories: info.directories, files: info.files, size: info.size)
+ } else {
+ footer.separatorIsHidden(false)
+ }
}
- cell.accessibilityValue = a11yValues.joined(separator: ", ")
- return cell
+ return footer
}
-
- return collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as! NCGridCell
}
}
extension NCCollectionViewCommon: UICollectionViewDelegateFlowLayout {
- func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
+ func getHeaderHeight() -> CGFloat {
- headerRichWorkspaceHeight = 0
+ var size: CGFloat = 0
- if let richWorkspaceText = richWorkspaceText {
+ if headerMenuButtonsCommand && !isSearching {
+ size += NCGlobal.shared.heightButtonsCommand
+ }
+ if headerMenuButtonsView {
+ size += NCGlobal.shared.heightButtonsView
+ }
+
+ return size
+ }
+
+ func getHeaderHeight(section:Int) -> (heightHeaderCommands: CGFloat, heightHeaderRichWorkspace: CGFloat, heightHeaderSection: CGFloat) {
+
+ var headerRichWorkspace: CGFloat = 0
+
+ if let richWorkspaceText = richWorkspaceText, !headerRichWorkspaceDisable {
let trimmed = richWorkspaceText.trimmingCharacters(in: .whitespaces)
if trimmed.count > 0 && !isSearching {
- headerRichWorkspaceHeight = UIScreen.main.bounds.size.height / 4
+ headerRichWorkspace = UIScreen.main.bounds.size.height / 6
}
}
- return CGSize(width: collectionView.frame.width, height: headerHeight + headerRichWorkspaceHeight)
+ if isSearching || layoutForView?.layout == NCGlobal.shared.layoutGrid || dataSource.numberOfSections() > 1 {
+ if section == 0 {
+ return (getHeaderHeight(), headerRichWorkspace, NCGlobal.shared.heightSection)
+ } else {
+ return (0, 0, NCGlobal.shared.heightSection)
+ }
+ } else {
+ return (getHeaderHeight(), headerRichWorkspace, 0)
+ }
+ }
+
+ func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
+
+ let (heightHeaderCommands, heightHeaderRichWorkspace, heightHeaderSection) = getHeaderHeight(section: section)
+ let heightHeader = heightHeaderCommands + heightHeaderRichWorkspace + heightHeaderSection
+
+ return CGSize(width: collectionView.frame.width, height: heightHeader)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
- return CGSize(width: collectionView.frame.width, height: footerHeight)
+
+ let sections = dataSource.numberOfSections()
+ let metadataForSection = self.dataSource.getMetadataForSection(section)
+ let isPaginated = metadataForSection?.lastSearchResult?.isPaginated ?? false
+ let metadatasCount: Int = metadataForSection?.lastSearchResult?.entries.count ?? 0
+ var size = CGSize(width: collectionView.frame.width, height: 0)
+
+ if section == sections - 1 {
+ size.height += NCGlobal.shared.endHeightFooter
+ } else {
+ size.height += NCGlobal.shared.heightFooter
+ }
+
+ if isSearching && isPaginated && metadatasCount > 0 {
+ size.height += NCGlobal.shared.heightFooterButton
+ }
+
+ return size
+ }
+}
+
+extension NCCollectionViewCommon: EasyTipViewDelegate {
+
+ func easyTipViewDidTap(_ tipView: EasyTipView) {
+ NCManageDatabase.shared.addTip(NCGlobal.shared.tipNCCollectionViewCommonAccountRequest)
+ }
+
+ func easyTipViewDidDismiss(_ tipView: EasyTipView) { }
+
+ func dismissTip() {
+ NCManageDatabase.shared.addTip(NCGlobal.shared.tipNCCollectionViewCommonAccountRequest)
+ self.tipView?.dismiss()
}
}
+
diff --git a/iOSClient/Main/Collection Common/NCGridCell.swift b/iOSClient/Main/Collection Common/NCGridCell.swift
index 9fcd361c8..5c5522882 100644
--- a/iOSClient/Main/Collection Common/NCGridCell.swift
+++ b/iOSClient/Main/Collection Common/NCGridCell.swift
@@ -23,8 +23,7 @@
import UIKit
-class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProtocol, NCTrashCell {
- var labelInfo: UILabel?
+class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProtocol, NCTrashCellProtocol {
@IBOutlet weak var imageItem: UIImageView!
@IBOutlet weak var imageSelect: UIImageView!
@@ -32,6 +31,7 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
@IBOutlet weak var imageFavorite: UIImageView!
@IBOutlet weak var imageLocal: UIImageView!
@IBOutlet weak var labelTitle: UILabel!
+ @IBOutlet weak var labelInfo: UILabel!
@IBOutlet weak var buttonMore: UIButton!
@IBOutlet weak var imageVisualEffect: UIVisualEffectView!
@IBOutlet weak var progressView: UIProgressView!
@@ -42,31 +42,45 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
weak var delegate: NCGridCellDelegate?
var namedButtonMore = ""
- var fileAvatarImageView: UIImageView? {
- get {
- return nil
- }
- }
var fileObjectId: String? {
- get {
- return objectId
- }
- set {
- objectId = newValue ?? ""
- }
+ get { return objectId }
+ set { objectId = newValue ?? "" }
}
var filePreviewImageView: UIImageView? {
- get {
- return imageItem
- }
+ get { return imageItem }
+ set { imageItem = newValue }
}
var fileUser: String? {
- get {
- return user
- }
- set {
- user = newValue ?? ""
- }
+ get { return user }
+ set { user = newValue ?? "" }
+ }
+ var fileTitleLabel: UILabel? {
+ get { return labelTitle }
+ set { labelTitle = newValue }
+ }
+ var fileInfoLabel: UILabel? {
+ get { return labelInfo }
+ set { labelInfo = newValue }
+ }
+ var fileProgressView: UIProgressView? {
+ get { return progressView }
+ set { progressView = newValue }
+ }
+ var fileSelectImage: UIImageView? {
+ get { return imageSelect }
+ set { imageSelect = newValue }
+ }
+ var fileStatusImage: UIImageView? {
+ get { return imageStatus }
+ set { imageStatus = newValue }
+ }
+ var fileLocalImage: UIImageView? {
+ get { return imageLocal }
+ set { imageLocal = newValue }
+ }
+ var fileFavoriteImage: UIImageView? {
+ get { return imageFavorite }
+ set { imageFavorite = newValue }
}
override func awakeFromNib() {
@@ -100,6 +114,11 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
longPressedGestureMore.delegate = self
longPressedGestureMore.delaysTouchesBegan = true
buttonMore.addGestureRecognizer(longPressedGestureMore)
+
+ labelTitle.text = ""
+ labelInfo.text = ""
+ labelTitle.textColor = NCBrandColor.shared.label
+ labelInfo.textColor = NCBrandColor.shared.systemGray
}
override func prepareForReuse() {
@@ -110,6 +129,10 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
accessibilityValue = nil
}
+ override func snapshotView(afterScreenUpdates afterUpdates: Bool) -> UIView? {
+ return nil
+ }
+
@IBAction func touchUpInsideMore(_ sender: Any) {
delegate?.tapMoreGridItem(with: objectId, namedButtonMore: namedButtonMore, image: imageItem.image, sender: sender)
}
@@ -170,6 +193,21 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
imageVisualEffect.isHidden = true
}
}
+
+ func writeInfoDateSize(date: NSDate, size: Int64) {
+
+ let dateFormatter = DateFormatter()
+ dateFormatter.dateStyle = .short
+ dateFormatter.timeStyle = .none
+ dateFormatter.locale = Locale.current
+
+ labelInfo.text = dateFormatter.string(from: date as Date) + " · " + CCUtility.transformedSize(size)
+ }
+
+ func setAccessibility(label: String, value: String) {
+ accessibilityLabel = label
+ accessibilityValue = value
+ }
}
protocol NCGridCellDelegate: AnyObject {
@@ -189,10 +227,10 @@ extension NCGridCellDelegate {
class NCGridLayout: UICollectionViewFlowLayout {
- var heightLabelPlusButton: CGFloat = 45
- var marginLeftRight: CGFloat = 6
+ var heightLabelPlusButton: CGFloat = 60
+ var marginLeftRight: CGFloat = 10
var itemForLine: CGFloat = 3
- var itemWidthDefault: CGFloat = 120
+ var itemWidthDefault: CGFloat = 140
// MARK: - View Life Cycle
diff --git a/iOSClient/Main/Collection Common/NCGridCell.xib b/iOSClient/Main/Collection Common/NCGridCell.xib
index b80dc577b..f9f24e7a4 100644
--- a/iOSClient/Main/Collection Common/NCGridCell.xib
+++ b/iOSClient/Main/Collection Common/NCGridCell.xib
@@ -1,33 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
+ <capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="gridCell" id="vf1-Kf-9uL" customClass="NCGridCell" customModule="Nextcloud" customModuleProvider="target">
- <rect key="frame" x="0.0" y="0.0" width="220" height="265"/>
+ <rect key="frame" x="0.0" y="0.0" width="416" height="494"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
- <rect key="frame" x="0.0" y="0.0" width="220" height="265"/>
+ <rect key="frame" x="0.0" y="0.0" width="416" height="494"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="5Ci-V1-hf5" userLabel="imageItem">
- <rect key="frame" x="0.0" y="0.0" width="220" height="220"/>
+ <rect key="frame" x="0.0" y="0.0" width="416" height="434"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="eU3-lY-fKr" userLabel="labelTitle">
- <rect key="frame" x="5" y="230" width="180" height="15"/>
- <fontDescription key="fontDescription" type="system" pointSize="12"/>
+ <rect key="frame" x="5" y="444" width="406" height="13.5"/>
+ <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="11"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2po-8g-XeS">
+ <rect key="frame" x="5" y="464.5" width="386" height="12"/>
+ <fontDescription key="fontDescription" type="system" pointSize="10"/>
+ <color key="textColor" systemColor="systemGray2Color"/>
+ <nil key="highlightedColor"/>
+ </label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="EJs-Ro-nbe" userLabel="buttonMoreGrid">
- <rect key="frame" x="195" y="225" width="25" height="25"/>
+ <rect key="frame" x="391" y="458" width="25" height="25"/>
<constraints>
<constraint firstAttribute="height" constant="25" id="4Ba-Uy-pX2"/>
<constraint firstAttribute="width" constant="25" id="aRK-GA-Nba"/>
@@ -38,30 +45,30 @@
</connections>
</button>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="AYs-f2-vve" userLabel="imageFavorite">
- <rect key="frame" x="200" y="5" width="15" height="15"/>
+ <rect key="frame" x="396" y="5" width="15" height="15"/>
<constraints>
<constraint firstAttribute="height" constant="15" id="ZjS-Hv-JNm"/>
<constraint firstAttribute="width" constant="15" id="kDr-15-VeJ"/>
</constraints>
</imageView>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="a0p-rj-jnV" userLabel="imageStatus">
- <rect key="frame" x="5" y="200" width="15" height="15"/>
+ <rect key="frame" x="5" y="414" width="15" height="15"/>
<constraints>
<constraint firstAttribute="height" constant="15" id="gq1-0a-eLC"/>
<constraint firstAttribute="width" constant="15" id="uJE-4b-Qt7"/>
</constraints>
</imageView>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="81G-wH-fjN" userLabel="imageLocal">
- <rect key="frame" x="200" y="200" width="15" height="15"/>
+ <rect key="frame" x="396" y="414" width="15" height="15"/>
<constraints>
<constraint firstAttribute="height" constant="15" id="NTa-Gi-uzY"/>
<constraint firstAttribute="width" constant="15" id="xLe-lb-N1p"/>
</constraints>
</imageView>
<visualEffectView hidden="YES" opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="W0L-HY-al1">
- <rect key="frame" x="0.0" y="0.0" width="220" height="220"/>
+ <rect key="frame" x="0.0" y="0.0" width="416" height="434"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" id="0m6-A2-SwD">
- <rect key="frame" x="0.0" y="0.0" width="220" height="220"/>
+ <rect key="frame" x="0.0" y="0.0" width="416" height="434"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
</view>
<blurEffect style="extraLight"/>
@@ -74,7 +81,7 @@
</constraints>
</imageView>
<progressView hidden="YES" opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="JQo-Vc-Ejk">
- <rect key="frame" x="5" y="256" width="210" height="4"/>
+ <rect key="frame" x="5" y="485" width="406" height="4"/>
</progressView>
</subviews>
</view>
@@ -83,8 +90,11 @@
<constraint firstItem="DHy-Up-3Bh" firstAttribute="leading" secondItem="VXh-sQ-LeX" secondAttribute="leading" constant="5" id="1T3-8p-uIW"/>
<constraint firstItem="AYs-f2-vve" firstAttribute="leading" secondItem="5Ci-V1-hf5" secondAttribute="trailing" constant="-20" id="3e3-0A-NSl"/>
<constraint firstItem="eU3-lY-fKr" firstAttribute="top" secondItem="5Ci-V1-hf5" secondAttribute="bottom" constant="10" id="4Yq-Nh-z1l"/>
+ <constraint firstItem="2po-8g-XeS" firstAttribute="leading" secondItem="VXh-sQ-LeX" secondAttribute="leading" constant="5" id="5dp-1s-MQi"/>
+ <constraint firstItem="2po-8g-XeS" firstAttribute="top" secondItem="eU3-lY-fKr" secondAttribute="bottom" constant="7" id="5wo-Td-XeT"/>
<constraint firstItem="W0L-HY-al1" firstAttribute="leading" secondItem="VXh-sQ-LeX" secondAttribute="leading" id="6tC-PK-fYX"/>
- <constraint firstItem="EJs-Ro-nbe" firstAttribute="top" secondItem="5Ci-V1-hf5" secondAttribute="bottom" constant="5" id="89Q-77-ulE"/>
+ <constraint firstItem="EJs-Ro-nbe" firstAttribute="centerY" secondItem="2po-8g-XeS" secondAttribute="centerY" id="8qW-SF-u1h"/>
+ <constraint firstItem="EJs-Ro-nbe" firstAttribute="leading" secondItem="2po-8g-XeS" secondAttribute="trailing" id="ABr-PB-TZg"/>
<constraint firstItem="VXh-sQ-LeX" firstAttribute="trailing" secondItem="JQo-Vc-Ejk" secondAttribute="trailing" constant="5" id="E03-Dk-iZ5"/>
<constraint firstItem="DHy-Up-3Bh" firstAttribute="top" secondItem="VXh-sQ-LeX" secondAttribute="top" constant="5" id="ESV-qE-tbO"/>
<constraint firstItem="5Ci-V1-hf5" firstAttribute="top" secondItem="VXh-sQ-LeX" secondAttribute="top" id="Ouj-ZD-UFm"/>
@@ -94,10 +104,10 @@
<constraint firstItem="VXh-sQ-LeX" firstAttribute="trailing" secondItem="W0L-HY-al1" secondAttribute="trailing" id="VMW-0Y-aOH"/>
<constraint firstItem="81G-wH-fjN" firstAttribute="top" secondItem="5Ci-V1-hf5" secondAttribute="bottom" constant="-20" id="aEb-vq-8sk"/>
<constraint firstItem="VXh-sQ-LeX" firstAttribute="trailing" secondItem="5Ci-V1-hf5" secondAttribute="trailing" id="cHT-cP-NN6"/>
- <constraint firstItem="VXh-sQ-LeX" firstAttribute="bottom" secondItem="5Ci-V1-hf5" secondAttribute="bottom" constant="45" id="eEC-eB-alE"/>
+ <constraint firstItem="VXh-sQ-LeX" firstAttribute="trailing" secondItem="eU3-lY-fKr" secondAttribute="trailing" constant="5" id="csl-Ny-rdF"/>
+ <constraint firstItem="VXh-sQ-LeX" firstAttribute="bottom" secondItem="5Ci-V1-hf5" secondAttribute="bottom" constant="60" id="eEC-eB-alE"/>
<constraint firstItem="eU3-lY-fKr" firstAttribute="leading" secondItem="VXh-sQ-LeX" secondAttribute="leading" constant="5" id="gZe-FC-8XQ"/>
- <constraint firstItem="VXh-sQ-LeX" firstAttribute="bottom" secondItem="W0L-HY-al1" secondAttribute="bottom" constant="45" id="jI9-M1-Nl8"/>
- <constraint firstItem="EJs-Ro-nbe" firstAttribute="leading" secondItem="eU3-lY-fKr" secondAttribute="trailing" constant="10" id="mhP-9c-PC9"/>
+ <constraint firstItem="VXh-sQ-LeX" firstAttribute="bottom" secondItem="W0L-HY-al1" secondAttribute="bottom" constant="60" id="jI9-M1-Nl8"/>
<constraint firstItem="81G-wH-fjN" firstAttribute="leading" secondItem="5Ci-V1-hf5" secondAttribute="trailing" constant="-20" id="nFH-Pc-end"/>
<constraint firstItem="5Ci-V1-hf5" firstAttribute="leading" secondItem="VXh-sQ-LeX" secondAttribute="leading" id="qT3-WD-iTV"/>
<constraint firstItem="5Ci-V1-hf5" firstAttribute="top" secondItem="AYs-f2-vve" secondAttribute="bottom" constant="-20" id="rLL-6g-ypv"/>
@@ -105,7 +115,7 @@
<constraint firstItem="JQo-Vc-Ejk" firstAttribute="leading" secondItem="VXh-sQ-LeX" secondAttribute="leading" constant="5" id="wiV-1m-wt8"/>
<constraint firstItem="VXh-sQ-LeX" firstAttribute="bottom" secondItem="JQo-Vc-Ejk" secondAttribute="bottom" constant="5" id="zV9-iQ-Zm5"/>
</constraints>
- <size key="customSize" width="220" height="260"/>
+ <size key="customSize" width="416" height="489"/>
<connections>
<outlet property="buttonMore" destination="EJs-Ro-nbe" id="BdI-ay-LuX"/>
<outlet property="imageFavorite" destination="AYs-f2-vve" id="UeH-R7-bZr"/>
@@ -114,13 +124,17 @@
<outlet property="imageSelect" destination="DHy-Up-3Bh" id="mo9-rP-P4I"/>
<outlet property="imageStatus" destination="a0p-rj-jnV" id="6Dg-tf-evd"/>
<outlet property="imageVisualEffect" destination="W0L-HY-al1" id="WDW-2d-Npa"/>
+ <outlet property="labelInfo" destination="2po-8g-XeS" id="FJ4-wI-9cW"/>
<outlet property="labelTitle" destination="eU3-lY-fKr" id="0P7-yM-Asb"/>
<outlet property="progressView" destination="JQo-Vc-Ejk" id="cdf-7W-tao"/>
</connections>
- <point key="canvasLocation" x="88" y="141.67916041979012"/>
+ <point key="canvasLocation" x="244.80000000000001" y="244.6776611694153"/>
</collectionViewCell>
</objects>
<resources>
<image name="more" width="425" height="425"/>
+ <systemColor name="systemGray2Color">
+ <color red="0.68235294117647061" green="0.68235294117647061" blue="0.69803921568627447" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ </systemColor>
</resources>
</document>
diff --git a/iOSClient/Main/Collection Common/NCListCell.swift b/iOSClient/Main/Collection Common/NCListCell.swift
index 71e3bd43a..2e2a3aec7 100755
--- a/iOSClient/Main/Collection Common/NCListCell.swift
+++ b/iOSClient/Main/Collection Common/NCListCell.swift
@@ -26,7 +26,6 @@ import UIKit
class NCListCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProtocol {
@IBOutlet weak var imageItem: UIImageView!
- @IBOutlet weak var imageItemLeftConstraint: NSLayoutConstraint!
@IBOutlet weak var imageSelect: UIImageView!
@IBOutlet weak var imageStatus: UIImageView!
@IBOutlet weak var imageFavorite: UIImageView!
@@ -39,7 +38,11 @@ class NCListCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
@IBOutlet weak var buttonMore: UIButton!
@IBOutlet weak var progressView: UIProgressView!
@IBOutlet weak var separator: UIView!
+
+ @IBOutlet weak var imageItemLeftConstraint: NSLayoutConstraint!
@IBOutlet weak var separatorHeightConstraint: NSLayoutConstraint!
+ @IBOutlet weak var titleTrailingConstraint: NSLayoutConstraint!
+ @IBOutlet weak var infoTrailingConstraint: NSLayoutConstraint!
private var objectId = ""
private var user = ""
@@ -48,32 +51,61 @@ class NCListCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
var namedButtonMore = ""
var fileAvatarImageView: UIImageView? {
- get {
- return imageShared
- }
+ get { return imageShared }
}
var fileObjectId: String? {
- get {
- return objectId
- }
- set {
- objectId = newValue ?? ""
- }
+ get { return objectId }
+ set { objectId = newValue ?? "" }
}
var filePreviewImageView: UIImageView? {
- get {
- return imageItem
- }
+ get { return imageItem }
+ set { imageItem = newValue }
}
var fileUser: String? {
- get {
- return user
- }
- set {
- user = newValue ?? ""
- }
+ get { return user }
+ set { user = newValue ?? "" }
}
-
+ var fileTitleLabel: UILabel? {
+ get { return labelTitle }
+ set { labelTitle = newValue }
+ }
+ var fileInfoLabel: UILabel? {
+ get { return labelInfo }
+ set { labelInfo = newValue }
+ }
+ var fileProgressView: UIProgressView? {
+ get { return progressView }
+ set { progressView = newValue }
+ }
+ var fileSelectImage: UIImageView? {
+ get { return imageSelect }
+ set { imageSelect = newValue }
+ }
+ var fileStatusImage: UIImageView? {
+ get { return imageStatus }
+ set { imageStatus = newValue }
+ }
+ var fileLocalImage: UIImageView? {
+ get { return imageLocal }
+ set { imageLocal = newValue }
+ }
+ var fileFavoriteImage: UIImageView? {
+ get { return imageFavorite }
+ set { imageFavorite = newValue }
+ }
+ var fileSharedImage: UIImageView? {
+ get { return imageShared }
+ set { imageShared = newValue }
+ }
+ var fileMoreImage: UIImageView? {
+ get { return imageMore }
+ set { imageMore = newValue }
+ }
+ var cellSeparatorView: UIView? {
+ get { return separator }
+ set { separator = newValue }
+ }
+
override func awakeFromNib() {
super.awakeFromNib()
@@ -104,6 +136,11 @@ class NCListCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
separator.backgroundColor = NCBrandColor.shared.separator
separatorHeightConstraint.constant = 0.5
+
+ labelTitle.text = ""
+ labelInfo.text = ""
+ labelTitle.textColor = NCBrandColor.shared.label
+ labelInfo.textColor = NCBrandColor.shared.systemGray
}
override func prepareForReuse() {
@@ -114,6 +151,10 @@ class NCListCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
accessibilityValue = nil
}
+ override func snapshotView(afterScreenUpdates afterUpdates: Bool) -> UIView? {
+ return nil
+ }
+
@IBAction func touchUpInsideShare(_ sender: Any) {
delegate?.tapShareListItem(with: objectId, sender: sender)
}
@@ -143,6 +184,16 @@ class NCListCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
selector: #selector(touchUpInsideMore))
]
}
+
+ func titleInfoTrailingFull() {
+ titleTrailingConstraint.constant = 10
+ infoTrailingConstraint.constant = 10
+ }
+
+ func titleInfoTrailingDefault() {
+ titleTrailingConstraint.constant = 90
+ infoTrailingConstraint.constant = 90
+ }
func setButtonMore(named: String, image: UIImage) {
namedButtonMore = named
@@ -161,6 +212,10 @@ class NCListCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
buttonShared.isHidden = status
}
+ func hideSeparator(_ status: Bool) {
+ separator.isHidden = status
+ }
+
func selectMode(_ status: Bool) {
if status {
imageItemLeftConstraint.constant = 45
@@ -198,6 +253,15 @@ class NCListCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
separator.isHidden = false
}
}
+
+ func writeInfoDateSize(date: NSDate, size: Int64) {
+ labelInfo.text = CCUtility.dateDiff(date as Date) + " · " + CCUtility.transformedSize(size)
+ }
+
+ func setAccessibility(label: String, value: String) {
+ accessibilityLabel = label
+ accessibilityValue = value
+ }
}
protocol NCListCellDelegate: AnyObject {
diff --git a/iOSClient/Main/Collection Common/NCListCell.xib b/iOSClient/Main/Collection Common/NCListCell.xib
index a92157f9f..684a73871 100755
--- a/iOSClient/Main/Collection Common/NCListCell.xib
+++ b/iOSClient/Main/Collection Common/NCListCell.xib
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@@ -157,11 +157,13 @@
<outlet property="imageSelect" destination="AyA-hP-r6w" id="c1t-yz-HBg"/>
<outlet property="imageShared" destination="jc6-Vg-TaS" id="6CL-wO-WaN"/>
<outlet property="imageStatus" destination="7Q9-Tv-9yo" id="Qug-Q7-rRZ"/>
+ <outlet property="infoTrailingConstraint" destination="p0M-zU-aDG" id="BJv-hA-VCb"/>
<outlet property="labelInfo" destination="AXX-71-9Q6" id="krb-tZ-UQ7"/>
<outlet property="labelTitle" destination="UtT-L6-mgW" id="Xv6-zM-2v1"/>
<outlet property="progressView" destination="m2p-oJ-j15" id="yFv-KS-nEy"/>
<outlet property="separator" destination="Egg-cb-EhZ" id="uhq-Nc-z8K"/>
<outlet property="separatorHeightConstraint" destination="G5S-67-boG" id="B6g-qe-MTb"/>
+ <outlet property="titleTrailingConstraint" destination="Tq4-bB-YMV" id="v4n-j5-ZWT"/>
</connections>
<point key="canvasLocation" x="97.599999999999994" y="129.53523238380811"/>
</collectionViewCell>
diff --git a/iOSClient/Main/Collection Common/NCSelectableNavigationView.swift b/iOSClient/Main/Collection Common/NCSelectableNavigationView.swift
index 84b706e48..77648ec13 100644
--- a/iOSClient/Main/Collection Common/NCSelectableNavigationView.swift
+++ b/iOSClient/Main/Collection Common/NCSelectableNavigationView.swift
@@ -34,6 +34,7 @@ extension RealmSwiftObject {
}
protocol NCSelectableNavigationView: AnyObject {
+
var appDelegate: AppDelegate { get }
var selectableDataSource: [RealmSwiftObject] { get }
var collectionView: UICollectionView! { get set }
@@ -44,7 +45,7 @@ protocol NCSelectableNavigationView: AnyObject {
var selectActions: [NCMenuAction] { get }
- func reloadDataSource()
+ func reloadDataSource(forced: Bool)
func setNavigationItem()
func tapSelectMenu()
@@ -52,7 +53,10 @@ protocol NCSelectableNavigationView: AnyObject {
}
extension NCSelectableNavigationView {
- func setNavigationItem() { setNavigationHeader() }
+
+ func setNavigationItem() {
+ setNavigationHeader()
+ }
func setNavigationHeader() {
if isEditMode {
@@ -132,7 +136,7 @@ extension NCSelectableNavigationView where Self: UIViewController {
actions.append(.saveMediaAction(selectedMediaMetadatas: selectedMediaMetadatas, completion: tapSelect))
}
actions.append(.setAvailableOfflineAction(selectedMetadatas: selectedMetadatas, isAnyOffline: isAnyOffline, viewController: self, completion: {
- self.reloadDataSource()
+ self.reloadDataSource(forced: true)
self.tapSelect()
}))
diff --git a/iOSClient/Main/Create cloud/NCCreateFormUploadAssets.swift b/iOSClient/Main/Create cloud/NCCreateFormUploadAssets.swift
index adcd666d2..3a32d1cf0 100644
--- a/iOSClient/Main/Create cloud/NCCreateFormUploadAssets.swift
+++ b/iOSClient/Main/Create cloud/NCCreateFormUploadAssets.swift
@@ -79,6 +79,10 @@ class NCCreateFormUploadAssets: XLFormViewController, NCSelectDelegate {
self.title = NSLocalizedString("_upload_photos_videos_", comment: "")
+ view.backgroundColor = NCBrandColor.shared.systemGroupedBackground
+ tableView.backgroundColor = NCBrandColor.shared.systemGroupedBackground
+ cellBackgoundColor = NCBrandColor.shared.secondarySystemGroupedBackground
+
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_cancel_", comment: ""), style: UIBarButtonItem.Style.plain, target: self, action: #selector(cancel))
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_save_", comment: ""), style: UIBarButtonItem.Style.plain, target: self, action: #selector(save))
@@ -90,8 +94,6 @@ class NCCreateFormUploadAssets: XLFormViewController, NCSelectDelegate {
})
}
- changeTheming()
-
initializeForm()
reloadForm()
}
@@ -102,23 +104,6 @@ class NCCreateFormUploadAssets: XLFormViewController, NCSelectDelegate {
self.delegate?.dismissFormUploadAssets()
}
- override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
- super.traitCollectionDidChange(previousTraitCollection)
-
- changeTheming()
- }
-
- // MARK: - Theming
-
- func changeTheming() {
-
- view.backgroundColor = NCBrandColor.shared.systemGroupedBackground
- tableView.backgroundColor = NCBrandColor.shared.systemGroupedBackground
- cellBackgoundColor = NCBrandColor.shared.secondarySystemGroupedBackground
-
- tableView.reloadData()
- }
-
// MARK: XLForm
func initializeForm() {
@@ -335,26 +320,6 @@ class NCCreateFormUploadAssets: XLFormViewController, NCSelectDelegate {
}
}
- /*
- func save() {
-
- self.dismiss(animated: true, completion: {
-
- let useFolderPhotoRow : XLFormRowDescriptor = self.form.formRow(withTag: "useFolderAutoUpload")!
- let useSubFolderRow : XLFormRowDescriptor = self.form.formRow(withTag: "useSubFolder")!
- var useSubFolder : Bool = false
-
- if (useFolderPhotoRow.value! as AnyObject).boolValue == true {
-
- self.serverUrl = NCManageDatabase.shared.getAccountAutoUploadPath(urlBase: self.appDelegate.urlBase, account: self.appDelegate.account)
- useSubFolder = (useSubFolderRow.value! as AnyObject).boolValue
- }
-
- self.appDelegate.activeMain.uploadFileAsset(self.assets, serverUrl: self.serverUrl, useSubFolder: useSubFolder, session: self.session)
- })
- }
- */
-
@objc func save() {
DispatchQueue.global().async {
@@ -362,16 +327,15 @@ class NCCreateFormUploadAssets: XLFormViewController, NCSelectDelegate {
let useFolderPhotoRow: XLFormRowDescriptor = self.form.formRow(withTag: "useFolderAutoUpload")!
let useSubFolderRow: XLFormRowDescriptor = self.form.formRow(withTag: "useSubFolder")!
var useSubFolder: Bool = false
- var metadatasMOV: [tableMetadata] = []
var metadatasNOConflict: [tableMetadata] = []
var metadatasUploadInConflict: [tableMetadata] = []
+ let autoUploadPath = NCManageDatabase.shared.getAccountAutoUploadPath(urlBase: self.appDelegate.urlBase, account: self.appDelegate.account)
if (useFolderPhotoRow.value! as AnyObject).boolValue == true {
self.serverUrl = NCManageDatabase.shared.getAccountAutoUploadPath(urlBase: self.appDelegate.urlBase, account: self.appDelegate.account)
useSubFolder = (useSubFolderRow.value! as AnyObject).boolValue
}
- let autoUploadPath = NCManageDatabase.shared.getAccountAutoUploadPath(urlBase: self.appDelegate.urlBase, account: self.appDelegate.account)
if autoUploadPath == self.serverUrl {
if !NCNetworking.shared.createFolder(assets: self.assets, selector: NCGlobal.shared.selectorUploadFile, useSubFolder: useSubFolder, account: self.appDelegate.account, urlBase: self.appDelegate.urlBase) {
NCContentPresenter.shared.messageNotification("_error_", description: "_error_createsubfolders_upload_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError)
@@ -385,66 +349,31 @@ class NCCreateFormUploadAssets: XLFormViewController, NCSelectDelegate {
var livePhoto: Bool = false
let fileName = CCUtility.createFileName(asset.value(forKey: "filename") as? String, fileDate: asset.creationDate, fileType: asset.mediaType, keyFileName: NCGlobal.shared.keyFileNameMask, keyFileNameType: NCGlobal.shared.keyFileNameType, keyFileNameOriginal: NCGlobal.shared.keyFileNameOriginal, forcedNewFileName: false)!
let assetDate = asset.creationDate ?? Date()
- let dateFormatter = DateFormatter()
- // Detect LivePhoto Upload
if asset.mediaSubtypes.contains(.photoLive) && CCUtility.getLivePhoto() {
livePhoto = true
}
- // Create serverUrl if use sub folder
if useSubFolder {
-
+ let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy"
let yearString = dateFormatter.string(from: assetDate)
-
dateFormatter.dateFormat = "MM"
let monthString = dateFormatter.string(from: assetDate)
-
serverUrl = autoUploadPath + "/" + yearString + "/" + monthString
}
// Check if is in upload
let isRecordInSessions = NCManageDatabase.shared.getAdvancedMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@ AND session != ''", self.appDelegate.account, serverUrl, fileName), sorted: "fileName", ascending: false)
- if isRecordInSessions.count > 0 {
- continue
- }
+ if isRecordInSessions.count > 0 { continue }
- let metadataForUpload = NCManageDatabase.shared.createMetadata(account: self.appDelegate.account, user: self.appDelegate.user, userId: self.appDelegate.userId, fileName: fileName, fileNameView: fileName, ocId: NSUUID().uuidString, serverUrl: serverUrl, urlBase: self.appDelegate.urlBase, url: "", contentType: "", livePhoto: livePhoto)
+ let metadataForUpload = NCManageDatabase.shared.createMetadata(account: self.appDelegate.account, user: self.appDelegate.user, userId: self.appDelegate.userId, fileName: fileName, fileNameView: fileName, ocId: NSUUID().uuidString, serverUrl: serverUrl, urlBase: self.appDelegate.urlBase, url: "", contentType: "", isLivePhoto: livePhoto)
metadataForUpload.assetLocalIdentifier = asset.localIdentifier
metadataForUpload.session = self.session
metadataForUpload.sessionSelector = NCGlobal.shared.selectorUploadFile
metadataForUpload.status = NCGlobal.shared.metadataStatusWaitUpload
- if livePhoto {
-
- let fileNameMove = (fileName as NSString).deletingPathExtension + ".mov"
- let ocId = NSUUID().uuidString
- let filePath = CCUtility.getDirectoryProviderStorageOcId(ocId, fileNameView: fileNameMove)!
-
- let semaphore = Semaphore()
- CCUtility.extractLivePhotoAsset(asset, filePath: filePath) { url in
- if let url = url {
- let fileSize = NCUtilityFileSystem.shared.getFileSize(filePath: url.path)
- let metadataMOVForUpload = NCManageDatabase.shared.createMetadata(account: self.appDelegate.account, user: self.appDelegate.user, userId: self.appDelegate.userId, fileName: fileNameMove, fileNameView: fileNameMove, ocId: ocId, serverUrl: serverUrl, urlBase: self.appDelegate.urlBase, url: "", contentType: "", livePhoto: livePhoto)
-
- metadataForUpload.livePhoto = true
- metadataMOVForUpload.livePhoto = true
-
- metadataMOVForUpload.session = self.session
- metadataMOVForUpload.sessionSelector = NCGlobal.shared.selectorUploadFile
- metadataMOVForUpload.size = fileSize
- metadataMOVForUpload.status = NCGlobal.shared.metadataStatusWaitUpload
- metadataMOVForUpload.classFile = NCCommunicationCommon.typeClassFile.video.rawValue
-
- metadatasMOV.append(metadataMOVForUpload)
- }
- semaphore.continue()
- }
- semaphore.wait()
- }
-
if NCManageDatabase.shared.getMetadataConflict(account: self.appDelegate.account, serverUrl: serverUrl, fileName: fileName) != nil {
metadatasUploadInConflict.append(metadataForUpload)
} else {
@@ -460,7 +389,6 @@ class NCCreateFormUploadAssets: XLFormViewController, NCSelectDelegate {
conflict.serverUrl = self.serverUrl
conflict.metadatasNOConflict = metadatasNOConflict
- conflict.metadatasMOV = metadatasMOV
conflict.metadatasUploadInConflict = metadatasUploadInConflict
conflict.delegate = self.appDelegate
@@ -471,7 +399,6 @@ class NCCreateFormUploadAssets: XLFormViewController, NCSelectDelegate {
} else {
self.appDelegate.networkingProcessUpload?.createProcessUploads(metadatas: metadatasNOConflict)
- self.appDelegate.networkingProcessUpload?.createProcessUploads(metadatas: metadatasMOV)
}
DispatchQueue.main.async {self.dismiss(animated: true, completion: nil) }
diff --git a/iOSClient/Main/Create cloud/NCCreateFormUploadConflict.swift b/iOSClient/Main/Create cloud/NCCreateFormUploadConflict.swift
index 48cda3166..67d42110f 100644
--- a/iOSClient/Main/Create cloud/NCCreateFormUploadConflict.swift
+++ b/iOSClient/Main/Create cloud/NCCreateFormUploadConflict.swift
@@ -23,6 +23,7 @@
import UIKit
import NCCommunication
+import Photos
@objc protocol NCCreateFormUploadConflictDelegate {
@objc func dismissCreateFormUploadConflict(metadatas: [tableMetadata]?)
@@ -52,7 +53,6 @@ extension NCCreateFormUploadConflictDelegate {
@objc var metadatasNOConflict: [tableMetadata]
@objc var metadatasUploadInConflict: [tableMetadata]
- @objc var metadatasMOV: [tableMetadata]
@objc var serverUrl: String?
@objc weak var delegate: NCCreateFormUploadConflictDelegate?
@objc var alwaysNewFileNameNumber: Bool = false
@@ -60,14 +60,13 @@ extension NCCreateFormUploadConflictDelegate {
var metadatasConflictNewFiles: [String] = []
var metadatasConflictAlreadyExistingFiles: [String] = []
- var fileNamesPath: [String: String] = [:]
+ let fileNamesPath = ThreadSafeDictionary<String,String>()
var blurView: UIVisualEffectView!
// MARK: - View Life Cycle
@objc required init?(coder aDecoder: NSCoder) {
self.metadatasNOConflict = []
- self.metadatasMOV = []
self.metadatasUploadInConflict = []
super.init(coder: aDecoder)
}
@@ -80,6 +79,11 @@ extension NCCreateFormUploadConflictDelegate {
tableView.allowsSelection = false
tableView.tableFooterView = UIView()
+ view.backgroundColor = NCBrandColor.shared.systemGroupedBackground
+ tableView.backgroundColor = NCBrandColor.shared.systemGroupedBackground
+ viewSwitch.backgroundColor = NCBrandColor.shared.systemGroupedBackground
+ viewButton.backgroundColor = NCBrandColor.shared.systemGroupedBackground
+
tableView.register(UINib(nibName: "NCCreateFormUploadConflictCell", bundle: nil), forCellReuseIdentifier: "Cell")
if metadatasUploadInConflict.count == 1 {
@@ -99,13 +103,18 @@ extension NCCreateFormUploadConflictDelegate {
buttonCancel.layer.cornerRadius = 20
buttonCancel.layer.masksToBounds = true
+ buttonCancel.layer.borderWidth = 0.5
+ buttonCancel.layer.borderColor = UIColor.darkGray.cgColor
+ buttonCancel.backgroundColor = NCBrandColor.shared.systemGray5
buttonCancel.setTitle(NSLocalizedString("_cancel_", comment: ""), for: .normal)
+ buttonCancel.setTitleColor(NCBrandColor.shared.label, for: .normal)
buttonContinue.layer.cornerRadius = 20
buttonContinue.layer.masksToBounds = true
+ buttonContinue.backgroundColor = NCBrandColor.shared.brand
buttonContinue.setTitle(NSLocalizedString("_continue_", comment: ""), for: .normal)
buttonContinue.isEnabled = false
- buttonContinue.setTitleColor(NCBrandColor.shared.gray, for: .normal)
+ buttonContinue.setTitleColor(NCBrandColor.shared.brandText, for: .normal)
let blurEffect = UIBlurEffect(style: .light)
blurView = UIVisualEffectView(effect: blurEffect)
@@ -113,29 +122,11 @@ extension NCCreateFormUploadConflictDelegate {
blurView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(blurView)
- changeTheming()
-
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.conflictDialog(fileCount: self.metadatasUploadInConflict.count)
}
}
- override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
- super.traitCollectionDidChange(previousTraitCollection)
-
- changeTheming()
- }
-
- // MARK: - Theming
-
- func changeTheming() {
-
- view.backgroundColor = NCBrandColor.shared.systemGroupedBackground
- tableView.backgroundColor = NCBrandColor.shared.systemGroupedBackground
- viewSwitch.backgroundColor = NCBrandColor.shared.systemGroupedBackground
- viewButton.backgroundColor = NCBrandColor.shared.systemGroupedBackground
- }
-
// MARK: - ConflictDialog
func conflictDialog(fileCount: Int) {
@@ -250,7 +241,6 @@ extension NCCreateFormUploadConflictDelegate {
// keep both
if metadatasConflictNewFiles.contains(metadata.ocId) && metadatasConflictAlreadyExistingFiles.contains(metadata.ocId) {
- let fileNameMOV = (metadata.fileNameView as NSString).deletingPathExtension + ".mov"
var fileName = metadata.fileNameView
let fileNameExtension = (fileName as NSString).pathExtension.lowercased()
let fileNameWithoutExtension = (fileName as NSString).deletingPathExtension
@@ -272,46 +262,16 @@ extension NCCreateFormUploadConflictDelegate {
metadatasNOConflict.append(metadata)
- // MOV (Live Photo)
- if let metadataMOV = self.metadatasMOV.first(where: { $0.fileName == fileNameMOV }) {
-
- let oldPath = CCUtility.getDirectoryProviderStorageOcId(metadataMOV.ocId, fileNameView: metadataMOV.fileNameView)
- let newFileNameMOV = (newFileName as NSString).deletingPathExtension + ".mov"
-
- metadataMOV.ocId = UUID().uuidString
- metadataMOV.fileName = newFileNameMOV
- metadataMOV.fileNameView = newFileNameMOV
-
- let newPath = CCUtility.getDirectoryProviderStorageOcId(metadataMOV.ocId, fileNameView: newFileNameMOV)
- CCUtility.moveFile(atPath: oldPath, toPath: newPath)
- }
-
// overwrite
} else if metadatasConflictNewFiles.contains(metadata.ocId) {
metadatasNOConflict.append(metadata)
- // remove (MOV)
- } else if metadatasConflictAlreadyExistingFiles.contains(metadata.ocId) {
-
- let fileNameMOV = (metadata.fileNameView as NSString).deletingPathExtension + ".mov"
- var index = 0
-
- for metadataMOV in metadatasMOV {
- if metadataMOV.fileNameView == fileNameMOV {
- metadatasMOV.remove(at: index)
- break
- }
- index += 1
- }
-
} else {
// used UIAlert (replace all)
}
}
- metadatasNOConflict.append(contentsOf: metadatasMOV)
-
dismiss(animated: true) {
self.delegate?.dismissCreateFormUploadConflict(metadatas: self.metadatasNOConflict)
}
@@ -423,29 +383,24 @@ extension NCCreateFormUploadConflict: UITableViewDataSource {
} else {
- CCUtility.extractImageVideoFromAssetLocalIdentifier(forUpload: metadataNewFile) { metadataNew, fileNamePath in
-
- if metadataNew != nil {
+ // PREVIEW
+ NCUtility.shared.extractImageVideoFromAssetLocalIdentifier(metadata: metadataNewFile, modifyMetadataForUpload: false) { metadata, fileNamePath, error in
+ if !error {
self.fileNamesPath[metadataNewFile.fileNameView] = fileNamePath!
-
do {
-
let fileDictionary = try FileManager.default.attributesOfItem(atPath: fileNamePath!)
let fileSize = fileDictionary[FileAttributeKey.size] as! Int64
-
if mediaType == PHAssetMediaType.image {
let data = try Data(contentsOf: URL(fileURLWithPath: fileNamePath!))
if let image = UIImage(data: data) {
- cell.imageNewFile.image = image
+ DispatchQueue.main.async { cell.imageNewFile.image = image }
}
} else if mediaType == PHAssetMediaType.video {
if let image = NCUtility.shared.imageFromVideo(url: URL(fileURLWithPath: fileNamePath!), at: 0) {
- cell.imageNewFile.image = image
+ DispatchQueue.main.async { cell.imageNewFile.image = image }
}
}
-
- cell.labelDetailNewFile.text = CCUtility.dateDiff(date) + "\n" + CCUtility.transformedSize(fileSize)
-
+ DispatchQueue.main.async { cell.labelDetailNewFile.text = CCUtility.dateDiff(date) + "\n" + CCUtility.transformedSize(fileSize) }
} catch { print("Error: \(error)") }
}
}
diff --git a/iOSClient/Main/Create cloud/NCCreateFormUploadDocuments.swift b/iOSClient/Main/Create cloud/NCCreateFormUploadDocuments.swift
index 313215913..55f17283e 100644
--- a/iOSClient/Main/Create cloud/NCCreateFormUploadDocuments.swift
+++ b/iOSClient/Main/Create cloud/NCCreateFormUploadDocuments.swift
@@ -65,6 +65,10 @@ import XLForm
self.tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
+ view.backgroundColor = NCBrandColor.shared.systemGroupedBackground
+ collectionView.backgroundColor = NCBrandColor.shared.systemGroupedBackground
+ tableView.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground
+
let cancelButton: UIBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_cancel_", comment: ""), style: UIBarButtonItem.Style.plain, target: self, action: #selector(cancel))
let saveButton: UIBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_save_", comment: ""), style: UIBarButtonItem.Style.plain, target: self, action: #selector(save))
@@ -75,31 +79,11 @@ import XLForm
// title
self.title = titleForm
- changeTheming()
-
initializeForm()
-
- // load the templates available
getTemplate()
}
- override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
- super.traitCollectionDidChange(previousTraitCollection)
-
- changeTheming()
- }
- // MARK: - Theming
-
- func changeTheming() {
-
- view.backgroundColor = NCBrandColor.shared.systemGroupedBackground
- collectionView.backgroundColor = NCBrandColor.shared.systemGroupedBackground
- tableView.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground
-
- tableView.reloadData()
- collectionView.reloadData()
- }
// MARK: - Tableview (XLForm)
@@ -149,6 +133,8 @@ import XLForm
section.addFormRow(row)
self.form = form
+ //tableView.reloadData()
+ //collectionView.reloadData()
}
override func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
@@ -284,7 +270,7 @@ import XLForm
if NCManageDatabase.shared.getMetadataConflict(account: appDelegate.account, serverUrl: serverUrl, fileName: String(describing: fileNameForm)) != nil {
- let metadataForUpload = NCManageDatabase.shared.createMetadata(account: appDelegate.account, user: appDelegate.user, userId: appDelegate.userId, fileName: String(describing: fileNameForm), fileNameView: String(describing: fileNameForm), ocId: "", serverUrl: serverUrl, urlBase: appDelegate.urlBase, url: "", contentType: "", livePhoto: false)
+ let metadataForUpload = NCManageDatabase.shared.createMetadata(account: appDelegate.account, user: appDelegate.user, userId: appDelegate.userId, fileName: String(describing: fileNameForm), fileNameView: String(describing: fileNameForm), ocId: "", serverUrl: serverUrl, urlBase: appDelegate.urlBase, url: "", contentType: "")
guard let conflictViewController = UIStoryboard(name: "NCCreateFormUploadConflict", bundle: nil).instantiateInitialViewController() as? NCCreateFormUploadConflict else { return }
conflictViewController.textLabelDetailNewFile = NSLocalizedString("_now_", comment: "")
@@ -322,6 +308,8 @@ import XLForm
func createDocument(fileNamePath: String, fileName: String) {
+ self.navigationItem.rightBarButtonItem?.isEnabled = false
+
if self.editorId == NCGlobal.shared.editorText || self.editorId == NCGlobal.shared.editorOnlyoffice {
var customUserAgent: String?
@@ -333,50 +321,43 @@ import XLForm
} // else: use default
NCCommunication.shared.NCTextCreateFile(fileNamePath: fileNamePath, editorId: editorId, creatorId: creatorId, templateId: templateIdentifier, customUserAgent: customUserAgent) { account, url, errorCode, errorMessage in
+ guard errorCode == 0, account == self.appDelegate.account, let url = url else {
+ self.navigationItem.rightBarButtonItem?.isEnabled = true
+ NCContentPresenter.shared.messageNotification("_error_", description: errorMessage, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+ return
+ }
- if errorCode == 0 && account == self.appDelegate.account {
-
- if url != nil && url!.count > 0 {
- let results = NCCommunicationCommon.shared.getInternalType(fileName: fileName, mimeType: "", directory: false)
-
- self.dismiss(animated: true, completion: {
- let metadata = NCManageDatabase.shared.createMetadata(account: self.appDelegate.account, user: self.appDelegate.user, userId: self.appDelegate.userId, fileName: fileName, fileNameView: fileName, ocId: CCUtility.createRandomString(12), serverUrl: self.serverUrl, urlBase: self.appDelegate.urlBase, url: url ?? "", contentType: results.mimeType, livePhoto: false)
+ var results = NCCommunicationCommon.shared.getInternalType(fileName: fileName, mimeType: "", directory: false)
+ //FIXME: iOS 12.0,* don't detect UTI text/markdown, text/x-markdown
+ if results.mimeType.isEmpty {
+ results.mimeType = "text/x-markdown"
+ }
- if let viewController = self.appDelegate.activeViewController {
- NCViewer.shared.view(viewController: viewController, metadata: metadata, metadatas: [metadata], imageIcon: nil)
- }
- })
+ self.dismiss(animated: true, completion: {
+ let metadata = NCManageDatabase.shared.createMetadata(account: self.appDelegate.account, user: self.appDelegate.user, userId: self.appDelegate.userId, fileName: fileName, fileNameView: fileName, ocId: CCUtility.createRandomString(12), serverUrl: self.serverUrl, urlBase: self.appDelegate.urlBase, url: url, contentType: results.mimeType)
+ if let viewController = self.appDelegate.activeViewController {
+ NCViewer.shared.view(viewController: viewController, metadata: metadata, metadatas: [metadata], imageIcon: nil)
}
-
- } else if errorCode != 0 {
- NCContentPresenter.shared.messageNotification("_error_", description: errorMessage, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
- } else {
- print("[LOG] It has been changed user during networking process, error.")
- }
+ })
}
}
if self.editorId == NCGlobal.shared.editorCollabora {
NCCommunication.shared.createRichdocuments(path: fileNamePath, templateId: templateIdentifier) { account, url, errorCode, errorDescription in
-
- if errorCode == 0 && account == self.appDelegate.account && url != nil {
-
- self.dismiss(animated: true, completion: {
-
- let createFileName = (fileName as NSString).deletingPathExtension + "." + self.fileNameExtension
- let metadata = NCManageDatabase.shared.createMetadata(account: self.appDelegate.account, user: self.appDelegate.user, userId: self.appDelegate.userId, fileName: createFileName, fileNameView: createFileName, ocId: CCUtility.createRandomString(12), serverUrl: self.serverUrl, urlBase: self.appDelegate.urlBase, url: url!, contentType: "", livePhoto: false)
-
- if let viewController = self.appDelegate.activeViewController {
- NCViewer.shared.view(viewController: viewController, metadata: metadata, metadatas: [metadata], imageIcon: nil)
- }
- })
-
- } else if errorCode != 0 {
+ guard errorCode == 0, account == self.appDelegate.account, let url = url else {
+ self.navigationItem.rightBarButtonItem?.isEnabled = true
NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
- } else {
- print("[LOG] It has been changed user during networking process, error.")
+ return
}
+
+ self.dismiss(animated: true, completion: {
+ let createFileName = (fileName as NSString).deletingPathExtension + "." + self.fileNameExtension
+ let metadata = NCManageDatabase.shared.createMetadata(account: self.appDelegate.account, user: self.appDelegate.user, userId: self.appDelegate.userId, fileName: createFileName, fileNameView: createFileName, ocId: CCUtility.createRandomString(12), serverUrl: self.serverUrl, urlBase: self.appDelegate.urlBase, url: url, contentType: "")
+ if let viewController = self.appDelegate.activeViewController {
+ NCViewer.shared.view(viewController: viewController, metadata: metadata, metadatas: [metadata], imageIcon: nil)
+ }
+ })
}
}
}
diff --git a/iOSClient/Main/Create cloud/NCCreateFormUploadScanDocument.swift b/iOSClient/Main/Create cloud/NCCreateFormUploadScanDocument.swift
index 565d3fc2b..08b7fdfe1 100644
--- a/iOSClient/Main/Create cloud/NCCreateFormUploadScanDocument.swift
+++ b/iOSClient/Main/Create cloud/NCCreateFormUploadScanDocument.swift
@@ -71,6 +71,10 @@ class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NC
self.title = NSLocalizedString("_save_settings_", comment: "")
+ view.backgroundColor = NCBrandColor.shared.systemGroupedBackground
+ tableView.backgroundColor = NCBrandColor.shared.systemGroupedBackground
+ cellBackgoundColor = NCBrandColor.shared.secondarySystemGroupedBackground
+
let saveButton: UIBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_save_", comment: ""), style: UIBarButtonItem.Style.plain, target: self, action: #selector(save))
self.navigationItem.rightBarButtonItem = saveButton
@@ -85,31 +89,12 @@ class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NC
// let rowCell = row.cell(forForm: self)
// rowCell.becomeFirstResponder()
- changeTheming()
-
initializeForm()
let value = CCUtility.getTextRecognitionStatus()
setTextRecognition(newValue: value)
}
- override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
- super.traitCollectionDidChange(previousTraitCollection)
-
- changeTheming()
- }
-
- // MARK: - Theming
-
- @objc func changeTheming() {
-
- view.backgroundColor = NCBrandColor.shared.systemGroupedBackground
- tableView.backgroundColor = NCBrandColor.shared.systemGroupedBackground
- cellBackgoundColor = NCBrandColor.shared.secondarySystemGroupedBackground
-
- tableView.reloadData()
- }
-
// MARK: XLForm
func initializeForm() {
@@ -414,7 +399,7 @@ class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NC
}
// Create metadata for upload
- let metadataForUpload = NCManageDatabase.shared.createMetadata(account: appDelegate.account, user: appDelegate.user, userId: appDelegate.userId, fileName: fileNameSave, fileNameView: fileNameSave, ocId: UUID().uuidString, serverUrl: serverUrl, urlBase: appDelegate.urlBase, url: "", contentType: "", livePhoto: false)
+ let metadataForUpload = NCManageDatabase.shared.createMetadata(account: appDelegate.account, user: appDelegate.user, userId: appDelegate.userId, fileName: fileNameSave, fileNameView: fileNameSave, ocId: UUID().uuidString, serverUrl: serverUrl, urlBase: appDelegate.urlBase, url: "", contentType: "")
metadataForUpload.session = NCNetworking.shared.sessionIdentifierBackground
metadataForUpload.sessionSelector = NCGlobal.shared.selectorUploadFile
@@ -432,7 +417,7 @@ class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NC
} else {
- NCUtility.shared.startActivityIndicator(backgroundView: self.view, blurEffect: true)
+ NCActivityIndicator.shared.start(backgroundView: self.view)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.dismissAndUpload(metadataForUpload)
@@ -444,7 +429,7 @@ class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NC
if metadatas != nil && metadatas!.count > 0 {
- NCUtility.shared.startActivityIndicator(backgroundView: self.view, blurEffect: true)
+ NCActivityIndicator.shared.start(backgroundView: self.view)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.dismissAndUpload(metadatas![0])
@@ -455,7 +440,7 @@ class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NC
func dismissAndUpload(_ metadata: tableMetadata) {
guard let fileNameGenerateExport = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView) else {
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
NCContentPresenter.shared.messageNotification("_error_", description: "_error_creation_file_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorCreationFile)
return
}
@@ -471,7 +456,7 @@ class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NC
let request = VNRecognizeTextRequest { request, _ in
guard let observations = request.results as? [VNRecognizedTextObservation] else {
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
return
}
for observation in observations {
@@ -492,7 +477,7 @@ class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NC
do {
try textFile.write(to: fileUrl, atomically: true, encoding: .utf8)
} catch {
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
NCContentPresenter.shared.messageNotification("_error_", description: "_error_creation_file_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorCreationFile)
return
}
@@ -528,7 +513,7 @@ class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NC
let request = VNRecognizeTextRequest { request, _ in
guard let observations = request.results as? [VNRecognizedTextObservation] else {
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
return
}
for observation in observations {
@@ -574,7 +559,7 @@ class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NC
let image = changeCompressionImage(self.arrayImages[0])
guard let data = image.jpegData(compressionQuality: CGFloat(0.5)) else {
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
NCContentPresenter.shared.messageNotification("_error_", description: "_error_creation_file_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorCreationFile)
return
}
@@ -582,14 +567,14 @@ class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NC
do {
try data.write(to: fileUrl, options: .atomic)
} catch {
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
NCContentPresenter.shared.messageNotification("_error_", description: "_error_creation_file_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorCreationFile)
return
}
}
metadata.size = NCUtilityFileSystem.shared.getFileSize(filePath: fileNameGenerateExport)
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
appDelegate.networkingProcessUpload?.createProcessUploads(metadatas: [metadata])
diff --git a/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift b/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift
index 795dadedd..874873027 100644
--- a/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift
+++ b/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift
@@ -55,7 +55,10 @@ class NCCreateFormUploadVoiceNote: XLFormViewController, NCSelectDelegate, AVAud
self.tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
- // title
+ view.backgroundColor = NCBrandColor.shared.systemGroupedBackground
+ tableView.backgroundColor = NCBrandColor.shared.systemGroupedBackground
+ cellBackgoundColor = NCBrandColor.shared.secondarySystemGroupedBackground
+
self.title = NSLocalizedString("_voice_memo_title_", comment: "")
// Button Play Stop
@@ -69,8 +72,6 @@ class NCCreateFormUploadVoiceNote: XLFormViewController, NCSelectDelegate, AVAud
labelTimer.textColor = NCBrandColor.shared.label
labelDuration.textColor = NCBrandColor.shared.label
- changeTheming()
-
initializeForm()
}
@@ -88,23 +89,6 @@ class NCCreateFormUploadVoiceNote: XLFormViewController, NCSelectDelegate, AVAud
}
}
- override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
- super.traitCollectionDidChange(previousTraitCollection)
-
- changeTheming()
- }
-
- // MARK: - Theming
-
- @objc func changeTheming() {
-
- view.backgroundColor = NCBrandColor.shared.systemGroupedBackground
- tableView.backgroundColor = NCBrandColor.shared.systemGroupedBackground
- cellBackgoundColor = NCBrandColor.shared.secondarySystemGroupedBackground
-
- tableView.reloadData()
- }
-
public func setup(serverUrl: String, fileNamePath: String, fileName: String) {
if serverUrl == NCUtilityFileSystem.shared.getHomeServer(account: appDelegate.account) {
@@ -240,7 +224,7 @@ class NCCreateFormUploadVoiceNote: XLFormViewController, NCSelectDelegate, AVAud
fileNameSave = (name as! NSString).deletingPathExtension + ".m4a"
}
- let metadataForUpload = NCManageDatabase.shared.createMetadata(account: self.appDelegate.account, user: self.appDelegate.user, userId: self.appDelegate.userId, fileName: fileNameSave, fileNameView: fileNameSave, ocId: UUID().uuidString, serverUrl: self.serverUrl, urlBase: self.appDelegate.urlBase, url: "", contentType: "", livePhoto: false)
+ let metadataForUpload = NCManageDatabase.shared.createMetadata(account: self.appDelegate.account, user: self.appDelegate.user, userId: self.appDelegate.userId, fileName: fileNameSave, fileNameView: fileNameSave, ocId: UUID().uuidString, serverUrl: self.serverUrl, urlBase: self.appDelegate.urlBase, url: "", contentType: "")
metadataForUpload.session = NCNetworking.shared.sessionIdentifierBackground
metadataForUpload.sessionSelector = NCGlobal.shared.selectorUploadFile
diff --git a/iOSClient/Main/NCCellProtocol.swift b/iOSClient/Main/NCCellProtocol.swift
index 21f2fa7f9..df85bced7 100644
--- a/iOSClient/Main/NCCellProtocol.swift
+++ b/iOSClient/Main/NCCellProtocol.swift
@@ -24,8 +24,94 @@
import UIKit
protocol NCCellProtocol {
+
var fileAvatarImageView: UIImageView? { get }
- var fileObjectId: String? { get }
- var filePreviewImageView: UIImageView? { get }
- var fileUser: String? { get }
+ var fileObjectId: String? { get set }
+ var filePreviewImageView: UIImageView? { get set }
+ var fileUser: String? { get set }
+ var fileTitleLabel: UILabel? { get set }
+ var fileInfoLabel: UILabel? { get set }
+ var fileProgressView: UIProgressView? { get set }
+ var fileSelectImage: UIImageView? { get set }
+ var fileStatusImage: UIImageView? { get set }
+ var fileLocalImage: UIImageView? { get set }
+ var fileFavoriteImage: UIImageView? { get set }
+ var fileSharedImage: UIImageView? { get set }
+ var fileMoreImage: UIImageView? { get set }
+ var cellSeparatorView: UIView? { get set }
+
+ func titleInfoTrailingDefault()
+ func titleInfoTrailingFull()
+ func writeInfoDateSize(date: NSDate, size: Int64)
+ func setButtonMore(named: String, image: UIImage)
+ func hideButtonShare(_ status: Bool)
+ func hideButtonMore(_ status: Bool)
+ func selectMode(_ status: Bool)
+ func selected(_ status: Bool)
+ func setAccessibility(label: String, value: String)
+}
+
+extension NCCellProtocol {
+
+ var fileAvatarImageView: UIImageView? {
+ return nil
+ }
+ var fileObjectId: String? {
+ get { return nil }
+ set {}
+ }
+ var filePreviewImageView: UIImageView? {
+ get { return nil }
+ set {}
+ }
+ var fileTitleLabel: UILabel? {
+ get { return nil }
+ set {}
+ }
+ var fileInfoLabel: UILabel? {
+ get { return nil }
+ set { }
+ }
+ var fileProgressView: UIProgressView? {
+ get { return nil }
+ set {}
+ }
+ var fileSelectImage: UIImageView? {
+ get { return nil }
+ set {}
+ }
+ var fileStatusImage: UIImageView? {
+ get { return nil }
+ set {}
+ }
+ var fileLocalImage: UIImageView? {
+ get { return nil }
+ set {}
+ }
+ var fileFavoriteImage: UIImageView? {
+ get { return nil }
+ set {}
+ }
+ var fileSharedImage: UIImageView? {
+ get { return nil }
+ set {}
+ }
+ var fileMoreImage: UIImageView? {
+ get { return nil }
+ set {}
+ }
+ var cellSeparatorView: UIView? {
+ get { return nil }
+ set {}
+ }
+
+ func titleInfoTrailingDefault() {}
+ func titleInfoTrailingFull() {}
+ func writeInfoDateSize(date: NSDate, size: Int64) {}
+ func setButtonMore(named: String, image: UIImage) {}
+ func hideButtonShare(_ status: Bool) {}
+ func hideButtonMore(_ status: Bool) {}
+ func selectMode(_ status: Bool) {}
+ func selected(_ status: Bool) {}
+ func setAccessibility(label: String, value: String) {}
}
diff --git a/iOSClient/Main/NCFunctionCenter.swift b/iOSClient/Main/NCFunctionCenter.swift
index 52e62224f..f9ed5fa79 100644
--- a/iOSClient/Main/NCFunctionCenter.swift
+++ b/iOSClient/Main/NCFunctionCenter.swift
@@ -26,6 +26,7 @@ import NCCommunication
import Queuer
import JGProgressHUD
import SVGKit
+import Photos
@objc class NCFunctionCenter: NSObject, UIDocumentInteractionControllerDelegate, NCSelectDelegate {
@objc public static let shared: NCFunctionCenter = {
@@ -48,25 +49,26 @@ import SVGKit
let selector = userInfo["selector"] as? String,
let errorCode = userInfo["errorCode"] as? Int,
let errorDescription = userInfo["errorDescription"] as? String,
- let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId),
- metadata.account == appDelegate.account
+ let account = userInfo["account"] as? String,
+ account == appDelegate.account
else { return }
guard errorCode == 0 else {
// File do not exists on server, remove in local
if errorCode == NCGlobal.shared.errorResourceNotFound || errorCode == NCGlobal.shared.errorBadServerResponse {
do {
- try FileManager.default.removeItem(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
+ try FileManager.default.removeItem(atPath: CCUtility.getDirectoryProviderStorageOcId(ocId))
} catch { }
- NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
- NCManageDatabase.shared.deleteLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
+ NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocId))
+ NCManageDatabase.shared.deleteLocalFile(predicate: NSPredicate(format: "ocId == %@", ocId))
} else {
NCContentPresenter.shared.messageNotification("_download_file_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode, priority: .max)
}
return
}
-
+ guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return }
+
switch selector {
case NCGlobal.shared.selectorLoadFileQuickLook:
let fileNamePath = NSTemporaryDirectory() + metadata.fileNameView
@@ -107,10 +109,7 @@ import SVGKit
case NCGlobal.shared.selectorSaveAlbum:
saveAlbum(metadata: metadata)
-
- case NCGlobal.shared.selectorSaveBackground:
- saveBackground(metadata: metadata)
-
+
case NCGlobal.shared.selectorSaveAlbumLivePhotoIMG, NCGlobal.shared.selectorSaveAlbumLivePhotoMOV:
var metadata = metadata
@@ -163,17 +162,15 @@ import SVGKit
@objc func uploadedFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["ocId"] as? String, let errorCode = userInfo["errorCode"] as? Int, let errorDescription = userInfo["errorDescription"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let errorCode = userInfo["errorCode"] as? Int,
+ let errorDescription = userInfo["errorDescription"] as? String,
+ let account = userInfo["account"] as? String,
+ account == appDelegate.account
+ else { return }
- if metadata.account == appDelegate.account {
- if errorCode != 0 {
- if errorCode != -999 && errorDescription != "" {
- NCContentPresenter.shared.messageNotification("_upload_file_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode, priority: .max)
- }
- }
- }
- }
+ if errorCode != 0, errorCode != -999, errorDescription != "" {
+ NCContentPresenter.shared.messageNotification("_upload_file_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode, priority: .max)
}
}
@@ -181,14 +178,21 @@ import SVGKit
func openShare(viewController: UIViewController, metadata: tableMetadata, indexPage: NCGlobal.NCSharePagingIndex) {
- let shareNavigationController = UIStoryboard(name: "NCShare", bundle: nil).instantiateInitialViewController() as! UINavigationController
- let shareViewController = shareNavigationController.topViewController as! NCSharePaging
+ let serverUrlFileName = metadata.serverUrl + "/" + metadata.fileName
+ NCActivityIndicator.shared.start(backgroundView: viewController.view)
+ NCNetworking.shared.readFile(serverUrlFileName: serverUrlFileName, queue: .main) { account, metadata, errorCode, errorDescription in
+ NCActivityIndicator.shared.stop()
+ if let metadata = metadata, errorCode == 0 {
+ let shareNavigationController = UIStoryboard(name: "NCShare", bundle: nil).instantiateInitialViewController() as! UINavigationController
+ let shareViewController = shareNavigationController.topViewController as! NCSharePaging
- shareViewController.metadata = metadata
- shareViewController.indexPage = indexPage
+ shareViewController.metadata = metadata
+ shareViewController.indexPage = indexPage
- shareNavigationController.modalPresentationStyle = .formSheet
- viewController.present(shareNavigationController, animated: true, completion: nil)
+ shareNavigationController.modalPresentationStyle = .formSheet
+ viewController.present(shareNavigationController, animated: true, completion: nil)
+ }
+ }
}
// MARK: -
@@ -197,7 +201,7 @@ import SVGKit
if CCUtility.fileProviderStorageExists(metadata) {
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadedFile, userInfo: ["ocId": metadata.ocId, "selector": selector, "errorCode": 0, "errorDescription": "" ])
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadedFile, userInfo: ["ocId": metadata.ocId, "selector": selector, "errorCode": 0, "errorDescription": "", "account": metadata.account])
} else {
@@ -383,25 +387,6 @@ import SVGKit
})
}
- func saveBackground(metadata: tableMetadata) {
-
- let fileNamePath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
- let destination = CCUtility.getDirectoryGroup().appendingPathComponent(NCGlobal.shared.appBackground).path + "/" + metadata.fileNameView
-
- if NCUtilityFileSystem.shared.copyFile(atPath: fileNamePath, toPath: destination) {
-
- if appDelegate.activeViewController is NCCollectionViewCommon {
- let viewController: NCCollectionViewCommon = appDelegate.activeViewController as! NCCollectionViewCommon
- let layoutKey = viewController.layoutKey
- let serverUrl = viewController.serverUrl
- if serverUrl == metadata.serverUrl {
- NCUtility.shared.setBackgroundImageForView(key: layoutKey, serverUrl: serverUrl, imageBackgroud: metadata.fileNameView, imageBackgroudContentMode: "")
- viewController.changeTheming()
- }
- }
- }
- }
-
// MARK: - Copy & Paste
func copyPasteboard(pasteboardOcIds: [String], hudView: UIView) {
@@ -476,49 +461,58 @@ import SVGKit
// MARK: -
- func openFileViewInFolder(serverUrl: String, fileName: String) {
-
- let viewController = UIStoryboard(name: "NCFileViewInFolder", bundle: nil).instantiateInitialViewController() as! NCFileViewInFolder
- let navigationController = UINavigationController(rootViewController: viewController)
+ func openFileViewInFolder(serverUrl: String, fileNameBlink: String?) {
- let topViewController = viewController
- var listViewController = [NCFileViewInFolder]()
- var serverUrl = serverUrl
- let homeUrl = NCUtilityFileSystem.shared.getHomeServer(account: appDelegate.account)
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
+ var topNavigationController: UINavigationController?
+ var pushServerUrl = NCUtilityFileSystem.shared.getHomeServer(account: self.appDelegate.account)
+ var mostViewController = UIApplication.shared.keyWindow!.rootViewController!.topMostViewController()
- while true {
+ if mostViewController.isModal {
+ mostViewController.dismiss(animated: false)
+ mostViewController = UIApplication.shared.keyWindow!.rootViewController!.topMostViewController()
+ }
+ mostViewController.navigationController?.popToRootViewController(animated: false)
- var viewController: NCFileViewInFolder?
- if serverUrl != homeUrl {
- viewController = UIStoryboard(name: "NCFileViewInFolder", bundle: nil).instantiateInitialViewController() as? NCFileViewInFolder
- if viewController == nil {
- return
+ if let tabBarController = self.appDelegate.window?.rootViewController as? UITabBarController {
+ tabBarController.selectedIndex = 0
+ if let navigationController = tabBarController.viewControllers?.first as? UINavigationController {
+ navigationController.popToRootViewController(animated: false)
+ topNavigationController = navigationController
}
- viewController!.titleCurrentFolder = (serverUrl as NSString).lastPathComponent
- } else {
- viewController = topViewController
}
- guard let vc = viewController else { return }
+ if pushServerUrl == serverUrl {
+ let viewController = topNavigationController?.topViewController as? NCFiles
+ viewController?.blinkCell(fileName: fileNameBlink)
+ return
+ }
+ guard let topNavigationController = topNavigationController else { return }
- vc.serverUrl = serverUrl
- vc.fileName = fileName
+ let diffDirectory = serverUrl.replacingOccurrences(of: pushServerUrl, with: "")
+ var subDirs = diffDirectory.split(separator: "/")
- vc.navigationItem.backButtonTitle = vc.titleCurrentFolder
- listViewController.insert(vc, at: 0)
+ while pushServerUrl != serverUrl, subDirs.count > 0 {
- if serverUrl != homeUrl {
- serverUrl = NCUtilityFileSystem.shared.deletingLastPathComponent(account: appDelegate.account, serverUrl: serverUrl)
- } else {
- break
- }
- }
+ guard let dir = subDirs.first, let viewController = UIStoryboard(name: "NCFiles", bundle: nil).instantiateInitialViewController() as? NCFiles else { return }
+ pushServerUrl = pushServerUrl + "/" + dir
- navigationController.setViewControllers(listViewController, animated: false)
- navigationController.modalPresentationStyle = .formSheet
+ viewController.serverUrl = pushServerUrl
+ viewController.isRoot = false
+ viewController.titleCurrentFolder = String(dir)
+ if pushServerUrl == serverUrl {
+ viewController.fileNameBlink = fileNameBlink
+ }
+ self.appDelegate.listFilesVC[serverUrl] = viewController
- appDelegate.window?.rootViewController?.present(navigationController, animated: true, completion: nil)
+ viewController.navigationItem.backButtonTitle = viewController.titleCurrentFolder
+ topNavigationController.pushViewController(viewController, animated: false)
+
+ subDirs.remove(at: 0)
+ }
+ }
}
+
// MARK: - NCSelect + Delegate
func dismissSelect(serverUrl: String?, metadata: tableMetadata?, type: String, items: [Any], overwrite: Bool, copy: Bool, move: Bool) {
@@ -624,7 +618,7 @@ import SVGKit
let copyPath = UIAction(title: NSLocalizedString("_copy_path_", comment: ""), image: UIImage(systemName: "doc.on.clipboard")) { _ in
let board = UIPasteboard.general
- board.string = NCUtilityFileSystem.shared.getPath(metadata: metadata)
+ board.string = NCUtilityFileSystem.shared.getPath(metadata: metadata, withFileName: true)
NCContentPresenter.shared.messageNotification("", description: "_copied_path_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorNoError)
}
@@ -654,16 +648,8 @@ import SVGKit
}
}
- let saveBackground = UIAction(title: NSLocalizedString("_use_as_background_", comment: ""), image: UIImage(systemName: "text.below.photo")) { _ in
- if CCUtility.fileProviderStorageExists(metadata) {
- self.saveBackground(metadata: metadata)
- } else {
- NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorSaveBackground)
- }
- }
-
let viewInFolder = UIAction(title: NSLocalizedString("_view_in_folder_", comment: ""), image: UIImage(systemName: "arrow.forward.square")) { _ in
- self.openFileViewInFolder(serverUrl: metadata.serverUrl, fileName: metadata.fileName)
+ self.openFileViewInFolder(serverUrl: metadata.serverUrl, fileNameBlink: metadata.fileName)
}
let openIn = UIAction(title: NSLocalizedString("_open_in_", comment: ""), image: UIImage(systemName: "square.and.arrow.up") ) { _ in
@@ -781,14 +767,6 @@ import SVGKit
children.insert(modify, at: children.count - 1)
}
- if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && viewController is NCCollectionViewCommon && !NCBrandOptions.shared.disable_background_image {
- let viewController: NCCollectionViewCommon = viewController as! NCCollectionViewCommon
- let layoutKey = viewController.layoutKey
- if layoutKey == NCGlobal.shared.layoutViewFiles {
- children.insert(saveBackground, at: children.count - 1)
- }
- }
-
let submenu = UIMenu(title: "", options: .displayInline, children: children)
guard appDelegate.disableSharesView == false else { return submenu }
return UIMenu(title: "", children: [detail, submenu])
diff --git a/iOSClient/Main/NCMainNavigationController.swift b/iOSClient/Main/NCMainNavigationController.swift
index 91b426fbc..f95d9b7ac 100644
--- a/iOSClient/Main/NCMainNavigationController.swift
+++ b/iOSClient/Main/NCMainNavigationController.swift
@@ -30,25 +30,6 @@ class NCMainNavigationController: UINavigationController {
required init?(coder: NSCoder) {
super.init(coder: coder)
- NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil)
-
- changeTheming()
- }
-
- override func viewDidLayoutSubviews() {
- super.viewDidLayoutSubviews()
- }
-
- override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
- super.traitCollectionDidChange(previousTraitCollection)
-
- changeTheming()
- }
-
- // MARK: - Theming
-
- @objc func changeTheming() {
-
if #available(iOS 13.0, *) {
let appearance = UINavigationBarAppearance()
@@ -72,6 +53,5 @@ class NCMainNavigationController: UINavigationController {
}
navigationBar.tintColor = .systemBlue
- navigationBar.setNeedsLayout()
}
}
diff --git a/iOSClient/Main/NCMainTabBar.swift b/iOSClient/Main/NCMainTabBar.swift
index ecdc124d5..7342efd54 100644
--- a/iOSClient/Main/NCMainTabBar.swift
+++ b/iOSClient/Main/NCMainTabBar.swift
@@ -28,7 +28,7 @@ class NCMainTabBar: UITabBar {
private var fillColor: UIColor!
private var shapeLayer: CALayer?
private let appDelegate = UIApplication.shared.delegate as! AppDelegate
- private var timer: Timer?
+ private let centerButtonY: CGFloat = -28
public var menuRect: CGRect {
get {
@@ -45,10 +45,10 @@ class NCMainTabBar: UITabBar {
super.init(coder: coder)
appDelegate.mainTabBar = self
- timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: (#selector(updateBadgeNumber)), userInfo: nil, repeats: true)
NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil)
- NotificationCenter.default.addObserver(self, selector: #selector(updateBadgeNumber), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUpdateBadgeNumber), object: nil)
+
+ NotificationCenter.default.addObserver(self, selector: #selector(updateBadgeNumber(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUpdateBadgeNumber), object: nil)
barTintColor = NCBrandColor.shared.secondarySystemBackground
backgroundColor = NCBrandColor.shared.secondarySystemBackground
@@ -174,9 +174,8 @@ class NCMainTabBar: UITabBar {
if let centerButton = self.viewWithTag(99) {
centerButton.removeFromSuperview()
}
- let centerButtonHeight: CGFloat = 57
- let centerButtonY: CGFloat = -28
+ let centerButtonHeight: CGFloat = 57
let centerButton = UIButton(frame: CGRect(x: (self.bounds.width / 2)-(centerButtonHeight/2), y: centerButtonY, width: centerButtonHeight, height: centerButtonHeight))
centerButton.setTitle("", for: .normal)
@@ -208,19 +207,16 @@ class NCMainTabBar: UITabBar {
self.addSubview(centerButton)
}
- @objc func updateBadgeNumber() {
-
- if appDelegate.account == "" { return }
+ @objc func updateBadgeNumber(_ notification: NSNotification) {
- let counterDownload = NCOperationQueue.shared.downloadCount()
- let counterUpload = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "status == %d OR status == %d OR status == %d", NCGlobal.shared.metadataStatusWaitUpload, NCGlobal.shared.metadataStatusInUpload, NCGlobal.shared.metadataStatusUploading)).count
- let total = counterDownload + counterUpload
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let counter = userInfo["counter"] as? Int
+ else { return }
- UIApplication.shared.applicationIconBadgeNumber = total
-
- if let item = items?[0] {
- if total > 0 {
- item.badgeValue = String(total)
+ UIApplication.shared.applicationIconBadgeNumber = counter
+ if let item = self.items?[0] {
+ if counter > 0 {
+ item.badgeValue = String(counter)
} else {
item.badgeValue = nil
}
@@ -234,4 +230,8 @@ class NCMainTabBar: UITabBar {
return nil
}
}
+
+ func getHight() -> CGFloat {
+ return (frame.size.height - centerButtonY)
+ }
}
diff --git a/iOSClient/Main/NCPickerViewController.swift b/iOSClient/Main/NCPickerViewController.swift
index a4fddfa01..83631cb69 100644
--- a/iOSClient/Main/NCPickerViewController.swift
+++ b/iOSClient/Main/NCPickerViewController.swift
@@ -24,6 +24,7 @@
import UIKit
import TLPhotoPicker
import MobileCoreServices
+import Photos
// MARK: - Photo Picker
@@ -150,7 +151,7 @@ class NCDocumentPickerViewController: NSObject, UIDocumentPickerDelegate {
if NCUtilityFileSystem.shared.copyFile(atPath: atPath, toPath: toPath) {
- let metadataForUpload = NCManageDatabase.shared.createMetadata(account: appDelegate.account, user: appDelegate.user, userId: appDelegate.userId, fileName: fileName, fileNameView: fileName, ocId: ocId, serverUrl: serverUrl, urlBase: appDelegate.urlBase, url: "", contentType: "", livePhoto: false)
+ let metadataForUpload = NCManageDatabase.shared.createMetadata(account: appDelegate.account, user: appDelegate.user, userId: appDelegate.userId, fileName: fileName, fileNameView: fileName, ocId: ocId, serverUrl: serverUrl, urlBase: appDelegate.urlBase, url: "", contentType: "")
metadataForUpload.session = NCNetworking.shared.sessionIdentifierBackground
metadataForUpload.sessionSelector = NCGlobal.shared.selectorUploadFile
diff --git a/iOSClient/Main/Section Header Footer/NCSectionFooter.xib b/iOSClient/Main/Section Header Footer/NCSectionFooter.xib
index 10dd9db5b..86d9bb416 100644
--- a/iOSClient/Main/Section Header Footer/NCSectionFooter.xib
+++ b/iOSClient/Main/Section Header Footer/NCSectionFooter.xib
@@ -1,37 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
- <device id="retina4_7" orientation="portrait">
- <adaptation id="fullscreen"/>
- </device>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+ <device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
+ <capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<collectionReusableView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" reuseIdentifier="sectionFooter" id="Vin-9E-7nW" customClass="NCSectionFooter" customModule="Nextcloud" customModuleProvider="target">
- <rect key="frame" x="0.0" y="0.0" width="375" height="50"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="103"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="TK1-KX-Qe0">
+ <rect key="frame" x="10" y="0.0" width="355" height="30"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="30" id="Qvv-k4-hfY"/>
+ </constraints>
+ <fontDescription key="fontDescription" type="system" pointSize="13"/>
+ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <state key="normal" title="Button">
+ <color key="titleColor" systemColor="linkColor"/>
+ </state>
+ <connections>
+ <action selector="touchUpInsideButton:" destination="Vin-9E-7nW" eventType="touchUpInside" id="XSh-0v-WHJ"/>
+ </connections>
+ </button>
+ <activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="qWG-SR-Qly">
+ <rect key="frame" x="177.5" y="5" width="20" height="20"/>
+ </activityIndicatorView>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="s2m-yO-4x0" userLabel="separator">
+ <rect key="frame" x="10" y="30" width="365" height="1"/>
+ <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="1" id="FYD-Pc-spZ"/>
+ </constraints>
+ </view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gzy-cT-Gjn" userLabel="LabelFooter">
- <rect key="frame" x="10" y="17" width="355" height="16"/>
+ <rect key="frame" x="10" y="43.5" width="355" height="16"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
+ <viewLayoutGuide key="safeArea" id="EFn-SN-cxu"/>
<constraints>
+ <constraint firstItem="qWG-SR-Qly" firstAttribute="centerX" secondItem="EFn-SN-cxu" secondAttribute="centerX" id="18M-RP-YIn"/>
+ <constraint firstItem="EFn-SN-cxu" firstAttribute="trailing" secondItem="TK1-KX-Qe0" secondAttribute="trailing" constant="10" id="PoY-CD-99O"/>
<constraint firstAttribute="trailing" secondItem="gzy-cT-Gjn" secondAttribute="trailing" constant="10" id="QzY-ac-CRO"/>
+ <constraint firstItem="EFn-SN-cxu" firstAttribute="leading" secondItem="s2m-yO-4x0" secondAttribute="leading" constant="-10" id="ai4-Qy-YWi"/>
<constraint firstItem="gzy-cT-Gjn" firstAttribute="centerY" secondItem="Vin-9E-7nW" secondAttribute="centerY" id="avP-sX-JB5"/>
+ <constraint firstItem="qWG-SR-Qly" firstAttribute="centerY" secondItem="TK1-KX-Qe0" secondAttribute="centerY" id="baS-g9-E8a"/>
+ <constraint firstItem="EFn-SN-cxu" firstAttribute="trailing" secondItem="s2m-yO-4x0" secondAttribute="trailing" id="dWj-wQ-cfb"/>
+ <constraint firstItem="TK1-KX-Qe0" firstAttribute="bottom" secondItem="s2m-yO-4x0" secondAttribute="bottom" constant="-1" id="ekM-Ii-N58"/>
<constraint firstItem="gzy-cT-Gjn" firstAttribute="leading" secondItem="Vin-9E-7nW" secondAttribute="leading" constant="10" id="hZz-MT-pHg"/>
+ <constraint firstItem="TK1-KX-Qe0" firstAttribute="top" secondItem="EFn-SN-cxu" secondAttribute="top" id="qRR-61-ojt"/>
+ <constraint firstItem="TK1-KX-Qe0" firstAttribute="leading" secondItem="EFn-SN-cxu" secondAttribute="leading" constant="10" id="xqA-FX-AlG"/>
</constraints>
- <viewLayoutGuide key="safeArea" id="EFn-SN-cxu"/>
<connections>
+ <outlet property="activityIndicatorSection" destination="qWG-SR-Qly" id="t9x-qH-lxP"/>
+ <outlet property="buttonSection" destination="TK1-KX-Qe0" id="Y2u-vO-1c4"/>
+ <outlet property="buttonSectionHeightConstraint" destination="Qvv-k4-hfY" id="kif-9a-gD8"/>
<outlet property="labelSection" destination="gzy-cT-Gjn" id="hhG-DH-GJc"/>
+ <outlet property="separator" destination="s2m-yO-4x0" id="iBM-eM-d33"/>
+ <outlet property="separatorHeightConstraint" destination="FYD-Pc-spZ" id="MBt-D9-VxE"/>
</connections>
+ <point key="canvasLocation" x="136.80000000000001" y="113.79310344827587"/>
</collectionReusableView>
</objects>
+ <resources>
+ <systemColor name="linkColor">
+ <color red="0.0" green="0.47843137254901963" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ </systemColor>
+ </resources>
</document>
diff --git a/iOSClient/Trash/Section/NCTrashSectionFooter.xib b/iOSClient/Main/Section Header Footer/NCSectionHeader.xib
index ab2020e97..b0421bf81 100644
--- a/iOSClient/Trash/Section/NCTrashSectionFooter.xib
+++ b/iOSClient/Main/Section Header Footer/NCSectionHeader.xib
@@ -1,37 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
- <device id="retina4_7" orientation="portrait">
- <adaptation id="fullscreen"/>
- </device>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+ <device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
- <collectionReusableView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" reuseIdentifier="sectionFooter" id="Vin-9E-7nW" customClass="NCTrashSectionFooter" customModule="Nextcloud" customModuleProvider="target">
- <rect key="frame" x="0.0" y="0.0" width="375" height="50"/>
+ <collectionReusableView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" reuseIdentifier="sectionHeader" id="Vin-9E-7nW" customClass="NCSectionHeader" customModule="Nextcloud" customModuleProvider="target">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="20"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gzy-cT-Gjn" userLabel="LabelFooter">
- <rect key="frame" x="10" y="17" width="355" height="16"/>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gzy-cT-Gjn">
+ <rect key="frame" x="10" y="2" width="355" height="18"/>
+ <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
+ <viewLayoutGuide key="safeArea" id="EFn-SN-cxu"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="gzy-cT-Gjn" secondAttribute="trailing" constant="10" id="QzY-ac-CRO"/>
- <constraint firstItem="gzy-cT-Gjn" firstAttribute="centerY" secondItem="Vin-9E-7nW" secondAttribute="centerY" id="avP-sX-JB5"/>
<constraint firstItem="gzy-cT-Gjn" firstAttribute="leading" secondItem="Vin-9E-7nW" secondAttribute="leading" constant="10" id="hZz-MT-pHg"/>
+ <constraint firstItem="EFn-SN-cxu" firstAttribute="bottom" secondItem="gzy-cT-Gjn" secondAttribute="bottom" id="sqa-zO-ySm"/>
</constraints>
- <viewLayoutGuide key="safeArea" id="EFn-SN-cxu"/>
<connections>
- <outlet property="labelFooter" destination="gzy-cT-Gjn" id="rIA-Pk-tZ6"/>
+ <outlet property="labelSection" destination="gzy-cT-Gjn" id="gfz-ks-qSP"/>
</connections>
+ <point key="canvasLocation" x="138" y="154"/>
</collectionReusableView>
</objects>
</document>
diff --git a/iOSClient/Main/Section Header Footer/NCSectionHeaderFooter.swift b/iOSClient/Main/Section Header Footer/NCSectionHeaderFooter.swift
index 53d37e134..c285aa357 100644
--- a/iOSClient/Main/Section Header Footer/NCSectionHeaderFooter.swift
+++ b/iOSClient/Main/Section Header Footer/NCSectionHeaderFooter.swift
@@ -26,15 +26,28 @@ import MarkdownKit
class NCSectionHeaderMenu: UICollectionReusableView, UIGestureRecognizerDelegate {
- @IBOutlet weak var buttonMore: UIButton!
@IBOutlet weak var buttonSwitch: UIButton!
@IBOutlet weak var buttonOrder: UIButton!
- @IBOutlet weak var buttonOrderWidthConstraint: NSLayoutConstraint!
+ @IBOutlet weak var buttonMore: UIButton!
+
+ @IBOutlet weak var button1: UIButton!
+ @IBOutlet weak var button2: UIButton!
+ @IBOutlet weak var button3: UIButton!
+
+ @IBOutlet weak var viewButtonsCommand: UIView!
+ @IBOutlet weak var viewButtonsView: UIView!
+ @IBOutlet weak var viewSeparator: UIView!
@IBOutlet weak var viewRichWorkspace: UIView!
+ @IBOutlet weak var viewSection: UIView!
+
+ @IBOutlet weak var viewButtonsCommandHeightConstraint: NSLayoutConstraint!
+ @IBOutlet weak var viewButtonsViewHeightConstraint: NSLayoutConstraint!
+ @IBOutlet weak var viewSeparatorHeightConstraint: NSLayoutConstraint!
@IBOutlet weak var viewRichWorkspaceHeightConstraint: NSLayoutConstraint!
+ @IBOutlet weak var viewSectionHeightConstraint: NSLayoutConstraint!
+
@IBOutlet weak var textViewRichWorkspace: UITextView!
- @IBOutlet weak var separator: UIView!
- @IBOutlet weak var separatorHeightConstraint: NSLayoutConstraint!
+ @IBOutlet weak var labelSection: UILabel!
weak var delegate: NCSectionHeaderMenuDelegate?
@@ -48,24 +61,47 @@ class NCSectionHeaderMenu: UICollectionReusableView, UIGestureRecognizerDelegate
backgroundColor = .clear
- buttonSwitch.setImage(UIImage(named: "switchList")!.image(color: NCBrandColor.shared.gray, size: 25), for: .normal)
+ buttonSwitch.setImage(UIImage(named: "switchList")!.image(color: NCBrandColor.shared.systemGray1, size: 25), for: .normal)
buttonOrder.setTitle("", for: .normal)
buttonOrder.setTitleColor(.systemBlue, for: .normal)
- buttonMore.setImage(UIImage(named: "more")!.image(color: NCBrandColor.shared.gray, size: 25), for: .normal)
+ buttonMore.setImage(UIImage(named: "more")!.image(color: NCBrandColor.shared.systemGray1, size: 25), for: .normal)
+
+ button1.setImage(nil, for: .normal)
+ button1.isHidden = true
+ button1.backgroundColor = .clear
+ button1.setTitleColor(.systemBlue, for: .normal)
+ button1.layer.borderColor = NCBrandColor.shared.systemGray1.cgColor
+ button1.layer.borderWidth = 0.3
+ button1.layer.cornerRadius = 3
+
+ button2.setImage(nil, for: .normal)
+ button2.isHidden = true
+ button2.backgroundColor = .clear
+ button2.setTitleColor(.systemBlue, for: .normal)
+ button2.layer.borderColor = NCBrandColor.shared.systemGray1.cgColor
+ button2.layer.borderWidth = 0.3
+ button2.layer.cornerRadius = 3
+
+ button3.setImage(nil, for: .normal)
+ button3.isHidden = true
+ button3.backgroundColor = .clear
+ button3.setTitleColor(.systemBlue, for: .normal)
+ button3.layer.borderColor = NCBrandColor.shared.systemGray1.cgColor
+ button3.layer.borderWidth = 0.3
+ button3.layer.cornerRadius = 3
// Gradient
gradient.startPoint = CGPoint(x: 0, y: 0.50)
gradient.endPoint = CGPoint(x: 0, y: 1)
viewRichWorkspace.layer.addSublayer(gradient)
- setGradientColor()
let tap = UITapGestureRecognizer(target: self, action: #selector(touchUpInsideViewRichWorkspace(_:)))
tap.delegate = self
viewRichWorkspace?.addGestureRecognizer(tap)
- separator.backgroundColor = NCBrandColor.shared.separator
- separatorHeightConstraint.constant = 0.5
+ viewSeparatorHeightConstraint.constant = 0.5
+ viewSeparator.backgroundColor = NCBrandColor.shared.separator
markdownParser = MarkdownParser(font: UIFont.systemFont(ofSize: 15), color: NCBrandColor.shared.label)
markdownParser.header.font = UIFont.systemFont(ofSize: 25)
@@ -73,97 +109,237 @@ class NCSectionHeaderMenu: UICollectionReusableView, UIGestureRecognizerDelegate
textViewRichWorkspace.attributedText = markdownParser.parse(richWorkspaceText)
}
textViewColor = NCBrandColor.shared.label
+
+ labelSection.text = ""
+ viewSectionHeightConstraint.constant = 0
}
override func layoutSublayers(of layer: CALayer) {
super.layoutSublayers(of: layer)
+
gradient.frame = viewRichWorkspace.bounds
+ setInterfaceColor()
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
- setGradientColor()
+
+ setInterfaceColor()
}
- func setGradientColor() {
- if traitCollection.userInterfaceStyle == .dark {
- gradient.colors = [UIColor(white: 0, alpha: 0).cgColor, UIColor.black.cgColor]
+ //MARK: - Command
+
+ func setStatusButtonsCommand(enable: Bool) {
+
+ button1.isEnabled = enable
+ button2.isEnabled = enable
+ button3.isEnabled = enable
+ }
+
+ func setButtonsCommand(heigt :CGFloat, imageButton1: UIImage? = nil, titleButton1: String? = nil, imageButton2: UIImage? = nil, titleButton2: String? = nil, imageButton3: UIImage? = nil, titleButton3: String? = nil) {
+
+ viewButtonsCommandHeightConstraint.constant = heigt
+ if heigt == 0 {
+ viewButtonsView.isHidden = true
+ button1.isHidden = true
+ button2.isHidden = true
+ button3.isHidden = true
} else {
- gradient.colors = [UIColor(white: 1, alpha: 0).cgColor, UIColor.white.cgColor]
+ viewButtonsView.isHidden = false
+ if var image = imageButton1, let title = titleButton1 {
+ image = image.image(color: NCBrandColor.shared.systemGray1, size: 25)
+ button1.setImage(image, for: .normal)
+ button1.isHidden = false
+ button1.setTitle(title.firstUppercased, for: .normal)
+ }
+ if var image = imageButton2, let title = titleButton2 {
+ image = image.image(color: NCBrandColor.shared.systemGray1, size: 25)
+ button2.setImage(image, for: .normal)
+ button2.isHidden = false
+ button2.setTitle(title.firstUppercased, for: .normal)
+ }
+ if var image = imageButton3, let title = titleButton3 {
+ image = image.image(color: NCBrandColor.shared.systemGray1, size: 25)
+ button3.setImage(image, for: .normal)
+ button3.isHidden = false
+ button3.setTitle(title.firstUppercased, for: .normal)
+ }
+ }
+ }
+
+ //MARK: - View
+
+ func setStatusButtonsView(enable: Bool) {
+
+ buttonSwitch.isEnabled = enable
+ buttonOrder.isEnabled = enable
+ buttonMore.isEnabled = enable
+ }
+
+ func buttonMoreIsHidden(_ isHidden: Bool) {
+
+ buttonMore.isHidden = isHidden
+ }
+
+ func setImageSwitchList() {
+
+ buttonSwitch.setImage(UIImage(named: "switchList")!.image(color: NCBrandColor.shared.systemGray1, size: 50), for: .normal)
+ }
+
+ func setImageSwitchGrid() {
+
+ buttonSwitch.setImage(UIImage(named: "switchGrid")!.image(color: NCBrandColor.shared.systemGray1, size: 50), for: .normal)
+ }
+
+ func setButtonsView(heigt :CGFloat) {
+
+ viewButtonsViewHeightConstraint.constant = heigt
+ if heigt == 0 {
+ viewButtonsView.isHidden = true
+ } else {
+ viewButtonsView.isHidden = false
}
}
- func setTitleSorted(datasourceTitleButton: String) {
+ func setSortedTitle(_ title: String) {
- let title = NSLocalizedString(datasourceTitleButton, comment: "")
- let size = title.size(withAttributes: [.font: buttonOrder.titleLabel?.font as Any])
+ let title = NSLocalizedString(title, comment: "")
+ //let size = title.size(withAttributes: [.font: buttonOrder.titleLabel?.font as Any])
buttonOrder.setTitle(title, for: .normal)
- buttonOrderWidthConstraint.constant = size.width + 5
}
- func setStatusButton(count: Int) {
+ //MARK: - RichWorkspace
+
+ func setRichWorkspaceHeight(_ size: CGFloat) {
- if count == 0 {
- buttonSwitch.isEnabled = false
- buttonOrder.isEnabled = false
- buttonMore.isEnabled = false
+ viewRichWorkspaceHeightConstraint.constant = size
+ if size == 0 {
+ viewRichWorkspace.isHidden = true
} else {
- buttonSwitch.isEnabled = true
- buttonOrder.isEnabled = true
- buttonMore.isEnabled = true
+ viewRichWorkspace.isHidden = false
}
}
- func setRichWorkspaceText(richWorkspaceText: String?) {
- guard let richWorkspaceText = richWorkspaceText else { return }
- if richWorkspaceText != self.richWorkspaceText {
- textViewRichWorkspace.attributedText = markdownParser.parse(richWorkspaceText)
- self.richWorkspaceText = richWorkspaceText
+ func setInterfaceColor() {
+
+ if traitCollection.userInterfaceStyle == .dark {
+ gradient.colors = [UIColor(white: 0, alpha: 0).cgColor, UIColor.black.cgColor]
+ } else {
+ gradient.colors = [UIColor(white: 1, alpha: 0).cgColor, UIColor.white.cgColor]
}
}
- @IBAction func touchUpInsideMore(_ sender: Any) {
- delegate?.tapMoreHeader(sender: sender)
+ func setRichWorkspaceText(_ text: String?) {
+ guard let text = text else { return }
+
+ if text != self.richWorkspaceText {
+ textViewRichWorkspace.attributedText = markdownParser.parse(text)
+ self.richWorkspaceText = text
+ }
+ }
+
+ //MARK: - Section
+
+ func setSectionHeight(_ size:CGFloat) {
+
+ viewSectionHeightConstraint.constant = size
+ if size == 0 {
+ viewSection.isHidden = true
+ } else {
+ viewSection.isHidden = false
+ }
}
+ // MARK: - Action
+
@IBAction func touchUpInsideSwitch(_ sender: Any) {
- delegate?.tapSwitchHeader(sender: sender)
+ delegate?.tapButtonSwitch(sender)
}
@IBAction func touchUpInsideOrder(_ sender: Any) {
- delegate?.tapOrderHeader(sender: sender)
+ delegate?.tapButtonOrder(sender)
+ }
+
+ @IBAction func touchUpInsideMore(_ sender: Any) {
+ delegate?.tapButtonMore(sender)
+ }
+
+ @IBAction func touchUpInsideButton1(_ sender: Any) {
+ delegate?.tapButton1(sender)
+ }
+
+ @IBAction func touchUpInsideButton2(_ sender: Any) {
+ delegate?.tapButton2(sender)
+ }
+
+ @IBAction func touchUpInsideButton3(_ sender: Any) {
+ delegate?.tapButton3(sender)
}
@objc func touchUpInsideViewRichWorkspace(_ sender: Any) {
- delegate?.tapRichWorkspace(sender: sender)
+ delegate?.tapRichWorkspace(sender)
}
}
protocol NCSectionHeaderMenuDelegate: AnyObject {
- func tapSwitchHeader(sender: Any)
- func tapMoreHeader(sender: Any)
- func tapOrderHeader(sender: Any)
- func tapRichWorkspace(sender: Any)
+ func tapButtonSwitch(_ sender: Any)
+ func tapButtonOrder(_ sender: Any)
+ func tapButtonMore(_ sender: Any)
+ func tapButton1(_ sender: Any)
+ func tapButton2(_ sender: Any)
+ func tapButton3(_ sender: Any)
+ func tapRichWorkspace(_ sender: Any)
}
// optional func
extension NCSectionHeaderMenuDelegate {
- func tapSwitchHeader(sender: Any) {}
- func tapMoreHeader(sender: Any) {}
- func tapOrderHeader(sender: Any) {}
- func tapRichWorkspace(sender: Any) {}
+ func tapButtonSwitch(_ sender: Any) {}
+ func tapButtonOrder(_ sender: Any) {}
+ func tapButtonMore(_ sender: Any) {}
+ func tapButton1(_ sender: Any) {}
+ func tapButton2(_ sender: Any) {}
+ func tapButton3(_ sender: Any) {}
+ func tapRichWorkspace(_ sender: Any) {}
+}
+
+class NCSectionHeader: UICollectionReusableView {
+
+ @IBOutlet weak var labelSection: UILabel!
+
+ override func awakeFromNib() {
+ super.awakeFromNib()
+
+ self.backgroundColor = UIColor.clear
+ self.labelSection.text = ""
+ }
}
-class NCSectionFooter: UICollectionReusableView {
+class NCSectionFooter: UICollectionReusableView, NCSectionFooterDelegate {
+ @IBOutlet weak var buttonSection: UIButton!
+ @IBOutlet weak var activityIndicatorSection: UIActivityIndicatorView!
@IBOutlet weak var labelSection: UILabel!
+ @IBOutlet weak var separator: UIView!
+ @IBOutlet weak var separatorHeightConstraint: NSLayoutConstraint!
+ @IBOutlet weak var buttonSectionHeightConstraint: NSLayoutConstraint!
+
+ weak var delegate: NCSectionFooterDelegate?
+ var metadataForSection: NCMetadataForSection?
override func awakeFromNib() {
super.awakeFromNib()
self.backgroundColor = UIColor.clear
labelSection.textColor = NCBrandColor.shared.gray
+ labelSection.text = ""
+
+ separator.backgroundColor = NCBrandColor.shared.separator
+ separatorHeightConstraint.constant = 0.5
+
+ buttonIsHidden(true)
+ activityIndicatorSection.isHidden = true
+ activityIndicatorSection.color = NCBrandColor.shared.label
}
func setTitleLabel(directories: Int, files: Int, size: Int64) {
@@ -191,4 +367,59 @@ class NCSectionFooter: UICollectionReusableView {
labelSection.text = foldersText + ", " + filesText
}
}
+
+ func setTitleLabel(_ text: String) {
+
+ labelSection.text = text
+ }
+
+ func setButtonText(_ text: String) {
+
+ buttonSection.setTitle(text, for: .normal)
+ }
+
+ func separatorIsHidden(_ isHidden: Bool) {
+
+ separator.isHidden = isHidden
+ }
+
+ func buttonIsHidden(_ isHidden: Bool) {
+
+ buttonSection.isHidden = isHidden
+ if isHidden {
+ buttonSectionHeightConstraint.constant = 0
+ } else {
+ buttonSectionHeightConstraint.constant = NCGlobal.shared.heightFooterButton
+ }
+ }
+
+ func showActivityIndicatorSection() {
+
+ buttonSection.isHidden = true
+ buttonSectionHeightConstraint.constant = NCGlobal.shared.heightFooterButton
+
+ activityIndicatorSection.isHidden = false
+ activityIndicatorSection.startAnimating()
+ }
+
+ func hideActivityIndicatorSection() {
+
+ activityIndicatorSection.stopAnimating()
+ activityIndicatorSection.isHidden = true
+ }
+
+ // MARK: - Action
+
+ @IBAction func touchUpInsideButton(_ sender: Any) {
+ delegate?.tapButtonSection(sender, metadataForSection: metadataForSection)
+ }
+}
+
+protocol NCSectionFooterDelegate: AnyObject {
+ func tapButtonSection(_ sender: Any, metadataForSection: NCMetadataForSection?)
+}
+
+// optional func
+extension NCSectionFooterDelegate {
+ func tapButtonSection(_ sender: Any, metadataForSection: NCMetadataForSection?) {}
}
diff --git a/iOSClient/Main/Section Header Footer/NCSectionHeaderMenu.xib b/iOSClient/Main/Section Header Footer/NCSectionHeaderMenu.xib
index 7f839f659..cecf77dfa 100644
--- a/iOSClient/Main/Section Header Footer/NCSectionHeaderMenu.xib
+++ b/iOSClient/Main/Section Header Footer/NCSectionHeaderMenu.xib
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@@ -12,14 +12,67 @@
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<collectionReusableView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" reuseIdentifier="sectionHeaderMenu" id="tys-A2-nDX" customClass="NCSectionHeaderMenu" customModule="Nextcloud" customModuleProvider="target">
- <rect key="frame" x="0.0" y="0.0" width="375" height="163"/>
+ <rect key="frame" x="0.0" y="0.0" width="551" height="211"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
- <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="QBu-GJ-Y52">
- <rect key="frame" x="0.0" y="0.0" width="375" height="113"/>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4m9-yf-RbB">
+ <rect key="frame" x="0.0" y="0.0" width="551" height="50"/>
<subviews>
- <button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1LD-cd-zhc" userLabel="buttonSwitch">
- <rect key="frame" x="12" y="44" width="25" height="25"/>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Hie-dN-B9L">
+ <rect key="frame" x="10" y="11" width="74" height="40"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="40" id="X1Q-Rt-PQI"/>
+ </constraints>
+ <fontDescription key="fontDescription" type="system" pointSize="13"/>
+ <inset key="contentEdgeInsets" minX="16" minY="0.0" maxX="8" maxY="0.0"/>
+ <inset key="imageEdgeInsets" minX="-8" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <state key="normal" title="Button 1"/>
+ <connections>
+ <action selector="touchUpInsideButton1:" destination="tys-A2-nDX" eventType="touchUpInside" id="n7r-8n-gT3"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="cjh-je-E6h">
+ <rect key="frame" x="94" y="11" width="76" height="40"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="40" id="Zjv-nS-ufy"/>
+ </constraints>
+ <fontDescription key="fontDescription" type="system" pointSize="13"/>
+ <inset key="contentEdgeInsets" minX="16" minY="0.0" maxX="8" maxY="0.0"/>
+ <inset key="imageEdgeInsets" minX="-8" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <state key="normal" title="Button 2"/>
+ <connections>
+ <action selector="touchUpInsideButton2:" destination="tys-A2-nDX" eventType="touchUpInside" id="hek-Xq-Lh2"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Zta-tv-COt">
+ <rect key="frame" x="180" y="11" width="76" height="40"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="40" id="Dm7-86-DVq"/>
+ </constraints>
+ <fontDescription key="fontDescription" type="system" pointSize="13"/>
+ <inset key="contentEdgeInsets" minX="16" minY="0.0" maxX="8" maxY="0.0"/>
+ <inset key="imageEdgeInsets" minX="-8" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <state key="normal" title="Button 3"/>
+ <connections>
+ <action selector="touchUpInsideButton3:" destination="tys-A2-nDX" eventType="touchUpInside" id="Krk-cP-Iq5"/>
+ </connections>
+ </button>
+ </subviews>
+ <constraints>
+ <constraint firstItem="cjh-je-E6h" firstAttribute="leading" secondItem="Hie-dN-B9L" secondAttribute="trailing" constant="10" id="5aP-yP-Qrg"/>
+ <constraint firstItem="Hie-dN-B9L" firstAttribute="top" secondItem="4m9-yf-RbB" secondAttribute="top" constant="11" id="6dq-TK-VJe"/>
+ <constraint firstItem="Zta-tv-COt" firstAttribute="leading" secondItem="cjh-je-E6h" secondAttribute="trailing" constant="10" id="6hB-av-smB"/>
+ <constraint firstItem="Zta-tv-COt" firstAttribute="centerY" secondItem="cjh-je-E6h" secondAttribute="centerY" id="Fcu-ai-2K5"/>
+ <constraint firstItem="Hie-dN-B9L" firstAttribute="leading" secondItem="4m9-yf-RbB" secondAttribute="leading" constant="10" id="GNB-In-2UC"/>
+ <constraint firstItem="cjh-je-E6h" firstAttribute="centerY" secondItem="Hie-dN-B9L" secondAttribute="centerY" id="Wan-Qr-mdA"/>
+ <constraint firstAttribute="height" constant="50" id="aJx-Rv-Dc0"/>
+ </constraints>
+ </view>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="s4I-Jo-yCE">
+ <rect key="frame" x="0.0" y="50" width="551" height="50"/>
+ <subviews>
+ <button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1LD-cd-zhc">
+ <rect key="frame" x="10" y="12.5" width="25" height="25"/>
<constraints>
<constraint firstAttribute="width" constant="25" id="D76-X9-Tw9"/>
<constraint firstAttribute="height" constant="25" id="izT-Ru-XYG"/>
@@ -29,11 +82,8 @@
<action selector="touchUpInsideSwitch:" destination="tys-A2-nDX" eventType="touchUpInside" id="iT8-1j-fib"/>
</connections>
</button>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0bo-yl-t5k" userLabel="buttonOrder">
- <rect key="frame" x="55" y="42.5" width="230" height="28"/>
- <constraints>
- <constraint firstAttribute="width" constant="230" id="jvv-Ug-l3I"/>
- </constraints>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0bo-yl-t5k">
+ <rect key="frame" x="45" y="11" width="163" height="28"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<state key="normal" title="Sort by name (from A to Z)">
<color key="titleColor" systemColor="darkTextColor"/>
@@ -42,8 +92,8 @@
<action selector="touchUpInsideOrder:" destination="tys-A2-nDX" eventType="touchUpInside" id="oiL-3O-hMQ"/>
</connections>
</button>
- <button hidden="YES" opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="D0O-wK-14O" userLabel="buttonSwitch">
- <rect key="frame" x="338" y="44" width="25" height="25"/>
+ <button hidden="YES" opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="D0O-wK-14O">
+ <rect key="frame" x="516" y="12.5" width="25" height="25"/>
<constraints>
<constraint firstAttribute="width" constant="25" id="aEr-j8-JDO"/>
<constraint firstAttribute="height" constant="25" id="bvx-Uh-NWD"/>
@@ -53,32 +103,30 @@
<action selector="touchUpInsideMore:" destination="tys-A2-nDX" eventType="touchUpInside" id="Jyu-Mx-nWq"/>
</connections>
</button>
- <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LZu-Te-clJ" userLabel="Separator">
- <rect key="frame" x="0.0" y="112" width="375" height="1"/>
- <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- <color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- <constraints>
- <constraint firstAttribute="height" constant="1" id="VuP-sT-hUI"/>
- </constraints>
- </view>
</subviews>
<constraints>
- <constraint firstItem="1LD-cd-zhc" firstAttribute="leading" secondItem="QBu-GJ-Y52" secondAttribute="leading" constant="12" id="3bI-Ld-Ddl"/>
- <constraint firstAttribute="trailing" secondItem="LZu-Te-clJ" secondAttribute="trailing" id="4Ue-ug-B6K"/>
- <constraint firstItem="1LD-cd-zhc" firstAttribute="centerY" secondItem="QBu-GJ-Y52" secondAttribute="centerY" id="AJf-bs-tiq"/>
- <constraint firstAttribute="bottom" secondItem="LZu-Te-clJ" secondAttribute="bottom" id="DDK-aB-wEh"/>
- <constraint firstItem="LZu-Te-clJ" firstAttribute="leading" secondItem="QBu-GJ-Y52" secondAttribute="leading" id="c4q-XY-3mD"/>
- <constraint firstItem="D0O-wK-14O" firstAttribute="centerY" secondItem="QBu-GJ-Y52" secondAttribute="centerY" id="d0X-sZ-v5c"/>
- <constraint firstItem="0bo-yl-t5k" firstAttribute="centerY" secondItem="QBu-GJ-Y52" secondAttribute="centerY" id="d2r-aK-x8q"/>
- <constraint firstAttribute="trailing" secondItem="D0O-wK-14O" secondAttribute="trailing" constant="12" id="qZw-Ob-In1"/>
- <constraint firstItem="0bo-yl-t5k" firstAttribute="leading" secondItem="1LD-cd-zhc" secondAttribute="trailing" constant="18" id="tBF-23-TJ4"/>
+ <constraint firstItem="1LD-cd-zhc" firstAttribute="centerY" secondItem="s4I-Jo-yCE" secondAttribute="centerY" id="9mz-E0-K4B"/>
+ <constraint firstItem="0bo-yl-t5k" firstAttribute="centerY" secondItem="1LD-cd-zhc" secondAttribute="centerY" id="URP-Ct-vPP"/>
+ <constraint firstItem="D0O-wK-14O" firstAttribute="centerY" secondItem="1LD-cd-zhc" secondAttribute="centerY" id="UUF-sF-n6M"/>
+ <constraint firstItem="0bo-yl-t5k" firstAttribute="leading" secondItem="1LD-cd-zhc" secondAttribute="trailing" constant="10" id="VBJ-H7-cJ3"/>
+ <constraint firstAttribute="trailing" secondItem="D0O-wK-14O" secondAttribute="trailing" constant="10" id="WZh-iW-MXC"/>
+ <constraint firstItem="1LD-cd-zhc" firstAttribute="leading" secondItem="s4I-Jo-yCE" secondAttribute="leading" constant="10" id="dGi-5z-MEh"/>
+ <constraint firstAttribute="height" constant="50" id="vvG-dH-6c1"/>
</constraints>
</view>
- <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NC1-5C-E5z" userLabel="ViewRichWorkspace">
- <rect key="frame" x="0.0" y="113" width="375" height="50"/>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LZu-Te-clJ">
+ <rect key="frame" x="0.0" y="99" width="551" height="1"/>
+ <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="1" id="VuP-sT-hUI"/>
+ </constraints>
+ </view>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NC1-5C-E5z" userLabel="View RichWorkspace">
+ <rect key="frame" x="0.0" y="141" width="551" height="50"/>
<subviews>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" userInteractionEnabled="NO" contentMode="scaleToFill" editable="NO" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="pYo-pF-MGv">
- <rect key="frame" x="5" y="0.0" width="365" height="50"/>
+ <rect key="frame" x="5" y="0.0" width="541" height="50"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="textColor" systemColor="labelColor"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
@@ -93,29 +141,63 @@
<constraint firstAttribute="bottom" secondItem="pYo-pF-MGv" secondAttribute="bottom" id="t4r-dA-VyW"/>
</constraints>
</view>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="f9U-NY-4OS">
+ <rect key="frame" x="0.0" y="191" width="551" height="20"/>
+ <subviews>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mB5-5n-AL9">
+ <rect key="frame" x="10" y="2" width="531" height="18"/>
+ <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ <constraints>
+ <constraint firstAttribute="trailing" secondItem="mB5-5n-AL9" secondAttribute="trailing" constant="10" id="Cct-8N-ghQ"/>
+ <constraint firstAttribute="height" constant="20" id="ZcL-Wd-xhN"/>
+ <constraint firstItem="mB5-5n-AL9" firstAttribute="leading" secondItem="f9U-NY-4OS" secondAttribute="leading" constant="10" id="xQp-zk-G00"/>
+ <constraint firstAttribute="bottom" secondItem="mB5-5n-AL9" secondAttribute="bottom" id="ySZ-Z1-BQ1"/>
+ </constraints>
+ </view>
</subviews>
<viewLayoutGuide key="safeArea" id="pm7-uW-mZE"/>
<constraints>
- <constraint firstItem="QBu-GJ-Y52" firstAttribute="leading" secondItem="pm7-uW-mZE" secondAttribute="leading" id="2Jt-JT-Jbi"/>
- <constraint firstItem="pm7-uW-mZE" firstAttribute="bottom" secondItem="NC1-5C-E5z" secondAttribute="bottom" id="35N-28-6Fp"/>
- <constraint firstItem="NC1-5C-E5z" firstAttribute="top" secondItem="QBu-GJ-Y52" secondAttribute="bottom" id="B4d-JR-jzS"/>
- <constraint firstItem="pm7-uW-mZE" firstAttribute="trailing" secondItem="QBu-GJ-Y52" secondAttribute="trailing" id="Km2-dk-R7v"/>
+ <constraint firstItem="f9U-NY-4OS" firstAttribute="leading" secondItem="pm7-uW-mZE" secondAttribute="leading" id="7kv-IL-kwZ"/>
+ <constraint firstItem="s4I-Jo-yCE" firstAttribute="leading" secondItem="pm7-uW-mZE" secondAttribute="leading" id="CaM-Eb-nHq"/>
+ <constraint firstItem="LZu-Te-clJ" firstAttribute="leading" secondItem="pm7-uW-mZE" secondAttribute="leading" id="CyS-jg-0vc"/>
+ <constraint firstItem="pm7-uW-mZE" firstAttribute="trailing" secondItem="f9U-NY-4OS" secondAttribute="trailing" id="GbG-un-mCe"/>
+ <constraint firstItem="pm7-uW-mZE" firstAttribute="trailing" secondItem="LZu-Te-clJ" secondAttribute="trailing" id="NiW-2m-3HS"/>
<constraint firstItem="NC1-5C-E5z" firstAttribute="leading" secondItem="pm7-uW-mZE" secondAttribute="leading" id="QpF-nE-s7J"/>
+ <constraint firstItem="s4I-Jo-yCE" firstAttribute="top" secondItem="4m9-yf-RbB" secondAttribute="bottom" id="TpE-MD-W1E"/>
<constraint firstItem="pm7-uW-mZE" firstAttribute="trailing" secondItem="NC1-5C-E5z" secondAttribute="trailing" id="UH6-8N-JUD"/>
- <constraint firstItem="QBu-GJ-Y52" firstAttribute="top" secondItem="pm7-uW-mZE" secondAttribute="top" id="auA-nX-bqB"/>
+ <constraint firstItem="4m9-yf-RbB" firstAttribute="leading" secondItem="pm7-uW-mZE" secondAttribute="leading" id="VkE-Yd-ZEU"/>
+ <constraint firstItem="pm7-uW-mZE" firstAttribute="trailing" secondItem="4m9-yf-RbB" secondAttribute="trailing" id="cQo-N7-86S"/>
+ <constraint firstItem="LZu-Te-clJ" firstAttribute="top" secondItem="s4I-Jo-yCE" secondAttribute="bottom" constant="-1" id="ede-24-v8F"/>
+ <constraint firstItem="pm7-uW-mZE" firstAttribute="bottom" secondItem="f9U-NY-4OS" secondAttribute="bottom" id="eyu-CE-rTX"/>
+ <constraint firstItem="pm7-uW-mZE" firstAttribute="trailing" secondItem="s4I-Jo-yCE" secondAttribute="trailing" id="oCg-UW-8TQ"/>
+ <constraint firstItem="4m9-yf-RbB" firstAttribute="top" secondItem="pm7-uW-mZE" secondAttribute="top" id="oKs-0n-Lan"/>
+ <constraint firstItem="NC1-5C-E5z" firstAttribute="bottom" secondItem="f9U-NY-4OS" secondAttribute="top" id="pmY-5s-Pv2"/>
</constraints>
<connections>
+ <outlet property="button1" destination="Hie-dN-B9L" id="kzL-vK-FCu"/>
+ <outlet property="button2" destination="cjh-je-E6h" id="jUf-rf-F2d"/>
+ <outlet property="button3" destination="Zta-tv-COt" id="jk9-MY-ylh"/>
<outlet property="buttonMore" destination="D0O-wK-14O" id="eEx-3R-zCS"/>
<outlet property="buttonOrder" destination="0bo-yl-t5k" id="Kbw-BG-73C"/>
- <outlet property="buttonOrderWidthConstraint" destination="jvv-Ug-l3I" id="E6N-z6-2VC"/>
<outlet property="buttonSwitch" destination="1LD-cd-zhc" id="Ec2-cM-CoY"/>
- <outlet property="separator" destination="LZu-Te-clJ" id="EwO-za-LxT"/>
- <outlet property="separatorHeightConstraint" destination="VuP-sT-hUI" id="5wS-ww-yKo"/>
+ <outlet property="labelSection" destination="mB5-5n-AL9" id="uxf-bN-nZA"/>
<outlet property="textViewRichWorkspace" destination="pYo-pF-MGv" id="2h4-LP-T1z"/>
+ <outlet property="viewButtonsCommand" destination="4m9-yf-RbB" id="d1a-Pc-ujo"/>
+ <outlet property="viewButtonsCommandHeightConstraint" destination="aJx-Rv-Dc0" id="58a-bd-5ri"/>
+ <outlet property="viewButtonsView" destination="s4I-Jo-yCE" id="FOI-ZK-1oj"/>
+ <outlet property="viewButtonsViewHeightConstraint" destination="vvG-dH-6c1" id="SEQ-Tn-EE0"/>
<outlet property="viewRichWorkspace" destination="NC1-5C-E5z" id="NyN-tr-sJl"/>
<outlet property="viewRichWorkspaceHeightConstraint" destination="eT3-4m-mJ6" id="agb-tE-jhw"/>
+ <outlet property="viewSection" destination="f9U-NY-4OS" id="idM-C9-2nP"/>
+ <outlet property="viewSectionHeightConstraint" destination="ZcL-Wd-xhN" id="RDs-yy-I6W"/>
+ <outlet property="viewSeparator" destination="LZu-Te-clJ" id="rz1-2Q-vEK"/>
+ <outlet property="viewSeparatorHeightConstraint" destination="VuP-sT-hUI" id="QHV-oY-E5w"/>
</connections>
- <point key="canvasLocation" x="138.40000000000001" y="194.75262368815595"/>
+ <point key="canvasLocation" x="349.60000000000002" y="55.322338830584712"/>
</collectionReusableView>
</objects>
<resources>
diff --git a/iOSClient/Media/Cell/NCGridMediaCell.swift b/iOSClient/Media/Cell/NCGridMediaCell.swift
index eb2c9a4a8..0dc99c439 100644
--- a/iOSClient/Media/Cell/NCGridMediaCell.swift
+++ b/iOSClient/Media/Cell/NCGridMediaCell.swift
@@ -36,30 +36,16 @@ class NCGridMediaCell: UICollectionViewCell, NCCellProtocol {
var date: Date?
var filePreviewImageView: UIImageView? {
- get {
- return imageItem
- }
- }
- var fileAvatarImageView: UIImageView? {
- get {
- return nil
- }
+ get { return imageItem }
+ set {}
}
var fileObjectId: String? {
- get {
- return objectId
- }
- set {
- objectId = newValue ?? ""
- }
+ get { return objectId }
+ set { objectId = newValue ?? "" }
}
var fileUser: String? {
- get {
- return user
- }
- set {
- user = newValue ?? ""
- }
+ get { return user }
+ set { user = newValue ?? "" }
}
override func awakeFromNib() {
diff --git a/iOSClient/Media/NCMedia.swift b/iOSClient/Media/NCMedia.swift
index c26d26385..509d9ddc5 100644
--- a/iOSClient/Media/NCMedia.swift
+++ b/iOSClient/Media/NCMedia.swift
@@ -71,8 +71,6 @@ class NCMedia: UIViewController, NCEmptyDataSetDelegate, NCSelectDelegate {
override func viewDidLoad() {
super.viewDidLoad()
- appDelegate.activeMedia = self
-
view.backgroundColor = NCBrandColor.shared.systemBackground
collectionView.register(UINib(nibName: "NCGridMediaCell", bundle: nil), forCellWithReuseIdentifier: "gridCell")
@@ -175,79 +173,61 @@ class NCMedia: UIViewController, NCEmptyDataSetDelegate, NCSelectDelegate {
@objc func deleteFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["ocId"] as? String {
-
- let indexes = self.metadatas.indices.filter { self.metadatas[$0].ocId == ocId }
- let metadatas = self.metadatas.filter { $0.ocId != ocId }
- self.metadatas = metadatas
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String
+ else { return }
- if self.metadatas.count == 0 {
- collectionView?.reloadData()
- } else if let row = indexes.first {
- let indexPath = IndexPath(row: row, section: 0)
- collectionView?.deleteItems(at: [indexPath])
- }
+ let indexes = self.metadatas.indices.filter { self.metadatas[$0].ocId == ocId }
+ let metadatas = self.metadatas.filter { $0.ocId != ocId }
+ self.metadatas = metadatas
- self.updateMediaControlVisibility()
- }
+ if self.metadatas.count == 0 {
+ collectionView?.reloadData()
+ } else if let row = indexes.first {
+ let indexPath = IndexPath(row: row, section: 0)
+ collectionView?.deleteItems(at: [indexPath])
}
+
+ self.updateMediaControlVisibility()
}
@objc func moveFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["ocId"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
-
- if metadata.account == appDelegate.account {
-
- let indexes = self.metadatas.indices.filter { self.metadatas[$0].ocId == metadata.ocId }
- let metadatas = self.metadatas.filter { $0.ocId != metadata.ocId }
- self.metadatas = metadatas
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let account = userInfo["account"] as? String,
+ account == appDelegate.account
+ else { return }
- if self.metadatas.count == 0 {
- collectionView?.reloadData()
- } else if let row = indexes.first {
- let indexPath = IndexPath(row: row, section: 0)
- collectionView?.deleteItems(at: [indexPath])
- }
-
- self.updateMediaControlVisibility()
- }
- }
- }
+ self.reloadDataSourceWithCompletion { _ in }
}
@objc func renameFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["ocId"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let account = userInfo["account"] as? String,
+ account == appDelegate.account
+ else { return }
- if metadata.account == appDelegate.account {
- self.reloadDataSourceWithCompletion { _ in }
- }
- }
- }
+ self.reloadDataSourceWithCompletion { _ in }
}
@objc func uploadedFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["ocId"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId), let errorCode = userInfo["errorCode"] as? Int {
- if errorCode == 0 && metadata.account == appDelegate.account {
- self.reloadDataSourceWithCompletion { _ in }
- }
- }
- }
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let errorCode = userInfo["errorCode"] as? Int, errorCode == 0 ,
+ let account = userInfo["account"] as? String,
+ account == appDelegate.account
+ else { return }
+
+ self.reloadDataSourceWithCompletion { _ in }
}
// MARK: - Command
func mediaCommandTitle() {
- mediaCommandView?.title.text = ""
+ mediaCommandView?.title.text = ""
if let visibleCells = self.collectionView?.indexPathsForVisibleItems.sorted(by: { $0.row < $1.row }).compactMap({ self.collectionView?.cellForItem(at: $0) }) {
-
if let cell = visibleCells.first as? NCGridMediaCell {
if cell.date != nil {
mediaCommandView?.title.text = CCUtility.getTitleSectionDate(cell.date)
@@ -257,6 +237,7 @@ class NCMedia: UIViewController, NCEmptyDataSetDelegate, NCSelectDelegate {
}
@objc func zoomOutGrid() {
+
UIView.animate(withDuration: 0.0, animations: {
if self.gridLayout.itemForLine + 1 < self.maxImageGrid {
self.gridLayout.itemForLine += 1
@@ -272,6 +253,7 @@ class NCMedia: UIViewController, NCEmptyDataSetDelegate, NCSelectDelegate {
}
@objc func zoomInGrid() {
+
UIView.animate(withDuration: 0.0, animations: {
if self.gridLayout.itemForLine - 1 > 0 {
self.gridLayout.itemForLine -= 1
@@ -287,18 +269,19 @@ class NCMedia: UIViewController, NCEmptyDataSetDelegate, NCSelectDelegate {
}
@objc func openMenuButtonMore(_ sender: Any) {
+
toggleMenu()
}
// MARK: Select Path
func dismissSelect(serverUrl: String?, metadata: tableMetadata?, type: String, items: [Any], overwrite: Bool, copy: Bool, move: Bool) {
- if serverUrl != nil {
- let path = CCUtility.returnPathfromServerUrl(serverUrl, urlBase: appDelegate.urlBase, account: appDelegate.account) ?? ""
+
+ guard let serverUrl = serverUrl else { return }
+ let path = CCUtility.returnPathfromServerUrl(serverUrl, urlBase: appDelegate.urlBase, account: appDelegate.account) ?? ""
NCManageDatabase.shared.setAccountMediaPath(path, account: appDelegate.account)
- reloadDataSourceWithCompletion { _ in
- self.searchNewMedia()
- }
+ reloadDataSourceWithCompletion { _ in
+ self.searchNewMedia()
}
}
@@ -323,7 +306,6 @@ extension NCMedia: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let metadata = metadatas[indexPath.row]
-
if isEditMode {
if let index = selectOcId.firstIndex(of: metadata.ocId) {
selectOcId.remove(at: index)
@@ -333,9 +315,7 @@ extension NCMedia: UICollectionViewDelegate {
if indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section) {
collectionView.reloadItems(at: [indexPath])
}
-
} else {
-
// ACTIVE SERVERURL
appDelegate.activeServerUrl = metadata.serverUrl
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as? NCGridMediaCell
@@ -346,29 +326,21 @@ extension NCMedia: UICollectionViewDelegate {
@available(iOS 13.0, *)
func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
+ guard let cell = collectionView.cellForItem(at: indexPath) as? NCGridMediaCell else { return nil }
let metadata = metadatas[indexPath.row]
let identifier = indexPath as NSCopying
- if let cell = collectionView.cellForItem(at: indexPath) as? NCGridMediaCell {
-
- let image = cell.imageItem.image
-
- return UIContextMenuConfiguration(identifier: identifier, previewProvider: {
+ let image = cell.imageItem.image
- return NCViewerProviderContextMenu(metadata: metadata, image: image)
-
- }, actionProvider: { _ in
-
- return NCFunctionCenter.shared.contextMenuConfiguration(ocId: metadata.ocId, viewController: self, enableDeleteLocal: false, enableViewInFolder: true, image: image)
- })
- } else {
- return nil
- }
+ return UIContextMenuConfiguration(identifier: identifier, previewProvider: {
+ return NCViewerProviderContextMenu(metadata: metadata, image: image)
+ }, actionProvider: { _ in
+ return NCFunctionCenter.shared.contextMenuConfiguration(ocId: metadata.ocId, viewController: self, enableDeleteLocal: false, enableViewInFolder: true, image: image)
+ })
}
@available(iOS 13.0, *)
func collectionView(_ collectionView: UICollectionView, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating) {
animator.addCompletion {
-
if let indexPath = configuration.identifier as? IndexPath {
self.collectionView(collectionView, didSelectItemAt: indexPath)
}
@@ -397,15 +369,13 @@ extension NCMedia: UICollectionViewDataSource {
}
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
- if indexPath.row < self.metadatas.count {
- let metadata = self.metadatas[indexPath.row]
-
- if FileManager().fileExists(atPath: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) {
- (cell as! NCGridMediaCell).imageItem.backgroundColor = nil
- (cell as! NCGridMediaCell).imageItem.image = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag))
- } else {
- NCOperationQueue.shared.downloadThumbnail(metadata: metadata, placeholder: false, cell: cell, view: collectionView)
- }
+ guard let cell = (cell as? NCGridMediaCell), indexPath.row < self.metadatas.count else { return }
+ let metadata = self.metadatas[indexPath.row]
+ if FileManager().fileExists(atPath: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) {
+ cell.imageItem.backgroundColor = nil
+ cell.imageItem.image = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag))
+ } else {
+ NCOperationQueue.shared.downloadThumbnail(metadata: metadata, placeholder: false, cell: cell, view: collectionView)
}
}
@@ -472,7 +442,7 @@ extension NCMedia {
@objc func reloadDataSourceWithCompletion(_ completion: @escaping (_ metadatas: [tableMetadata]) -> Void) {
- if appDelegate.account == "" { return }
+ guard !appDelegate.account.isEmpty else { return }
if account != appDelegate.account {
self.metadatas = []
@@ -517,6 +487,7 @@ extension NCMedia {
}
func updateMediaControlVisibility() {
+
if self.metadatas.count == 0 {
if !self.filterClassTypeImage && !self.filterClassTypeVideo {
self.mediaCommandView?.toggleEmptyView(isEmpty: true)
@@ -552,13 +523,16 @@ extension NCMedia {
greaterDate = Calendar.current.date(byAdding: .day, value: value, to: lessDate)!
}
- let height = self.tabBarController?.tabBar.frame.size.height ?? 0
- NCUtility.shared.startActivityIndicator(backgroundView: self.view, blurEffect: false, bottom: height + 50, style: .gray)
+ var bottom: CGFloat = 0
+ if let mainTabBar = self.tabBarController?.tabBar as? NCMainTabBar {
+ bottom = -mainTabBar.getHight()
+ }
+ NCActivityIndicator.shared.start(backgroundView: self.view, bottom: bottom-5, style: .gray)
- NCCommunication.shared.searchMedia(path: mediaPath, lessDate: lessDate, greaterDate: greaterDate, elementDate: "d:getlastmodified/", limit: limit, showHiddenFiles: CCUtility.getShowHiddenFiles(), timeout: 120) { account, files, errorCode, errorDescription in
+ NCCommunication.shared.searchMedia(path: mediaPath, lessDate: lessDate, greaterDate: greaterDate, elementDate: "d:getlastmodified/", limit: limit, showHiddenFiles: CCUtility.getShowHiddenFiles(), timeout: 300) { account, files, errorCode, errorDescription in
self.oldInProgress = false
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
self.collectionView.reloadData()
if errorCode == 0 && account == self.appDelegate.account {
@@ -601,6 +575,7 @@ extension NCMedia {
}
@objc func searchNewMediaTimer() {
+
self.searchNewMedia()
}
@@ -633,7 +608,7 @@ extension NCMedia {
reloadDataThenPerform {
- NCCommunication.shared.searchMedia(path: self.mediaPath, lessDate: lessDate, greaterDate: greaterDate, elementDate: "d:getlastmodified/", limit: limit, showHiddenFiles: CCUtility.getShowHiddenFiles(), timeout: 120) { account, files, errorCode, errorDescription in
+ NCCommunication.shared.searchMedia(path: self.mediaPath, lessDate: lessDate, greaterDate: greaterDate, elementDate: "d:getlastmodified/", limit: limit, showHiddenFiles: CCUtility.getShowHiddenFiles(), timeout: 300) { account, files, errorCode, errorDescription in
self.newInProgress = false
self.mediaCommandView?.activityIndicator.stopAnimating()
@@ -672,6 +647,7 @@ extension NCMedia: UIScrollViewDelegate {
}
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
+
mediaCommandView?.collapseControlButtonView(true)
}
@@ -688,6 +664,7 @@ extension NCMedia: UIScrollViewDelegate {
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
+
timerSearchNewMedia?.invalidate()
timerSearchNewMedia = Timer.scheduledTimer(timeInterval: timeIntervalSearchNewMedia, target: self, selector: #selector(searchNewMediaTimer), userInfo: nil, repeats: false)
@@ -697,6 +674,7 @@ extension NCMedia: UIScrollViewDelegate {
}
func scrollViewDidScrollToTop(_ scrollView: UIScrollView) {
+
let y = view.safeAreaInsets.top
scrollView.contentOffset.y = -(insetsTop + y)
}
diff --git a/iOSClient/Menu/NCCollectionViewCommon+Menu.swift b/iOSClient/Menu/NCCollectionViewCommon+Menu.swift
index fda43661f..9339cd17c 100644
--- a/iOSClient/Menu/NCCollectionViewCommon+Menu.swift
+++ b/iOSClient/Menu/NCCollectionViewCommon+Menu.swift
@@ -158,7 +158,9 @@ extension NCCollectionViewCommon {
// OFFLINE
//
if !isFolderEncrypted {
- actions.append(.setAvailableOfflineAction(selectedMetadatas: [metadata], isAnyOffline: isOffline, viewController: self, completion: self.reloadDataSource))
+ actions.append(.setAvailableOfflineAction(selectedMetadatas: [metadata], isAnyOffline: isOffline, viewController: self, completion: {
+ self.reloadDataSource()
+ }))
}
//
@@ -269,52 +271,43 @@ extension NCCollectionViewCommon {
actions.append(.copyAction(selectOcId: [metadata.ocId], hudView: self.view))
}
- /*
//
- // USE AS BACKGROUND
+ // MODIFY
//
if #available(iOS 13.0, *) {
- if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && self.layoutKey == NCGlobal.shared.layoutViewFiles && !NCBrandOptions.shared.disable_background_image {
+ if !isFolderEncrypted && metadata.contentType != "image/gif" && metadata.contentType != "image/svg+xml" && (metadata.contentType == "com.adobe.pdf" || metadata.contentType == "application/pdf" || metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue) {
actions.append(
NCMenuAction(
- title: NSLocalizedString("_use_as_background_", comment: ""),
- icon: NCUtility.shared.loadImage(named: "text.below.photo"),
+ title: NSLocalizedString("_modify_", comment: ""),
+ icon: NCUtility.shared.loadImage(named: "pencil.tip.crop.circle"),
action: { menuAction in
- if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) {
- NCFunctionCenter.shared.saveBackground(metadata: metadata)
- } else {
- NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorSaveBackground)
- }
+ NCFunctionCenter.shared.openDownload(metadata: metadata, selector: NCGlobal.shared.selectorLoadFileQuickLook)
}
)
)
}
}
- */
//
- // MODIFY
+ // COLOR FOLDER
//
- if #available(iOS 13.0, *) {
- if !isFolderEncrypted && metadata.contentType != "image/gif" && metadata.contentType != "image/svg+xml" && (metadata.contentType == "com.adobe.pdf" || metadata.contentType == "application/pdf" || metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue) {
- actions.append(
- NCMenuAction(
- title: NSLocalizedString("_modify_", comment: ""),
- icon: NCUtility.shared.loadImage(named: "pencil.tip.crop.circle"),
- action: { menuAction in
- if self is NCFileViewInFolder {
- self.dismiss(animated: true) {
- NCFunctionCenter.shared.openDownload(metadata: metadata, selector: NCGlobal.shared.selectorLoadFileQuickLook)
- }
- } else {
- NCFunctionCenter.shared.openDownload(metadata: metadata, selector: NCGlobal.shared.selectorLoadFileQuickLook)
- }
+ if self is NCFiles, metadata.directory {
+ actions.append(
+ NCMenuAction(
+ title: NSLocalizedString("_change_color_", comment: ""),
+ icon: NCUtility.shared.loadImage(named: "palette"),
+ action: { _ in
+ if let picker = UIStoryboard(name: "NCColorPicker", bundle: nil).instantiateInitialViewController() as? NCColorPicker {
+ picker.metadata = metadata
+ let popup = NCPopupViewController(contentController: picker, popupWidth: 200, popupHeight: 320)
+ popup.backgroundAlpha = 0
+ self.present(popup, animated: true)
}
- )
+ }
)
- }
+ )
}
-
+
//
// DELETE
//
@@ -323,7 +316,7 @@ extension NCCollectionViewCommon {
//
// SET FOLDER E2EE
//
- if !metadata.e2eEncrypted && metadata.directory && CCUtility.isEnd(toEndEnabled: appDelegate.account) && metadata.serverUrl == serverUrlHome {
+ if !metadata.e2eEncrypted && metadata.directory && CCUtility.isEnd(toEndEnabled: appDelegate.account) && metadata.serverUrl == serverUrlHome && metadata.size == 0 {
actions.append(
NCMenuAction(
title: NSLocalizedString("_e2e_set_folder_encrypted_", comment: ""),
@@ -348,7 +341,7 @@ extension NCCollectionViewCommon {
//
// UNSET FOLDER E2EE
//
- if metadata.e2eEncrypted && metadata.directory && CCUtility.isEnd(toEndEnabled: appDelegate.account) && metadata.serverUrl == serverUrlHome {
+ if metadata.e2eEncrypted && metadata.directory && CCUtility.isEnd(toEndEnabled: appDelegate.account) && metadata.serverUrl == serverUrlHome && metadata.size == 0 {
actions.append(
NCMenuAction(
title: NSLocalizedString("_e2e_remove_folder_encrypted_", comment: ""),
diff --git a/iOSClient/Menu/NCMedia+Menu.swift b/iOSClient/Menu/NCMedia+Menu.swift
index 629107aff..a963d3302 100644
--- a/iOSClient/Menu/NCMedia+Menu.swift
+++ b/iOSClient/Menu/NCMedia+Menu.swift
@@ -53,7 +53,7 @@ extension NCMedia {
actions.append(
NCMenuAction(
- title: NSLocalizedString(filterClassTypeImage ? "_media_viewimage_show_" : "_media_viewimage_hide_", comment: ""),
+ title: NSLocalizedString("_media_viewimage_hide_", comment: ""),
icon: NCUtility.shared.loadImage(named: "photo"),
selected: filterClassTypeImage,
on: true,
@@ -67,7 +67,7 @@ extension NCMedia {
actions.append(
NCMenuAction(
- title: NSLocalizedString(filterClassTypeVideo ? "_media_viewvideo_show_" : "_media_viewvideo_hide_", comment: ""),
+ title: NSLocalizedString("_media_viewvideo_hide_", comment: ""),
icon: NCUtility.shared.loadImage(named: "video"),
selected: filterClassTypeVideo,
on: true,
diff --git a/iOSClient/Menu/NCMenuAction.swift b/iOSClient/Menu/NCMenuAction.swift
index 6aff1a224..66543d53e 100644
--- a/iOSClient/Menu/NCMenuAction.swift
+++ b/iOSClient/Menu/NCMenuAction.swift
@@ -154,13 +154,7 @@ extension NCMenuAction {
title: NSLocalizedString("_open_in_", comment: ""),
icon: NCUtility.shared.loadImage(named: "square.and.arrow.up"),
action: { _ in
- if viewController is NCFileViewInFolder {
- viewController.dismiss(animated: true) {
- NCFunctionCenter.shared.openActivityViewController(selectedMetadata: selectedMetadatas)
- }
- } else {
- NCFunctionCenter.shared.openActivityViewController(selectedMetadata: selectedMetadatas)
- }
+ NCFunctionCenter.shared.openActivityViewController(selectedMetadata: selectedMetadatas)
completion?()
}
)
diff --git a/iOSClient/Menu/NCViewer+Menu.swift b/iOSClient/Menu/NCViewer+Menu.swift
index 5b18d6a6f..160d9fef1 100644
--- a/iOSClient/Menu/NCViewer+Menu.swift
+++ b/iOSClient/Menu/NCViewer+Menu.swift
@@ -192,7 +192,7 @@ extension NCViewer {
title: NSLocalizedString("_view_in_folder_", comment: ""),
icon: NCUtility.shared.loadImage(named: "arrow.forward.square"),
action: { menuAction in
- NCFunctionCenter.shared.openFileViewInFolder(serverUrl: metadata.serverUrl, fileName: metadata.fileName)
+ NCFunctionCenter.shared.openFileViewInFolder(serverUrl: metadata.serverUrl, fileNameBlink: metadata.fileName)
}
)
)
diff --git a/iOSClient/Menu/UIViewController+Menu.swift b/iOSClient/Menu/UIViewController+Menu.swift
index d2463553d..e30a16263 100644
--- a/iOSClient/Menu/UIViewController+Menu.swift
+++ b/iOSClient/Menu/UIViewController+Menu.swift
@@ -27,7 +27,7 @@ import NCCommunication
import UIKit
extension UIViewController {
- fileprivate func handleProfileAction(_ action: NCHovercard.Action, for userId: String) {
+ fileprivate func handleProfileAction(_ action: NCCHovercard.Action, for userId: String) {
switch action.appId {
case "email":
guard
diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift
index af5f23ab2..1527247e5 100644
--- a/iOSClient/NCGlobal.swift
+++ b/iOSClient/NCGlobal.swift
@@ -79,19 +79,16 @@ class NCGlobal: NSObject {
var directoryOnTop: Bool
var titleButtonHeader: String
var itemForLine: Int
- var imageBackgroud: String
- var imageBackgroudContentMode: String
}
// Directory on Group
//
- @objc let appDatabaseNextcloud = "Library/Application Support/Nextcloud"
+ @objc let directoryProviderStorage = "File Provider Storage"
@objc let appApplicationSupport = "Library/Application Support"
- @objc let appUserData = "Library/Application Support/UserData"
@objc let appCertificates = "Library/Application Support/Certificates"
+ @objc let appDatabaseNextcloud = "Library/Application Support/Nextcloud"
@objc let appScan = "Library/Application Support/Scan"
- @objc let appBackground = "Library/Application Support/Background"
- @objc let directoryProviderStorage = "File Provider Storage"
+ @objc let appUserData = "Library/Application Support/UserData"
// Service
//
@@ -100,6 +97,10 @@ class NCGlobal: NSObject {
let refreshTask = "com.nextcloud.refreshTask"
let processingTask = "com.nextcloud.processingTask"
+ // Name
+ //
+ @objc let appName = "files"
+
// Nextcloud version
//
let nextcloudVersion12: Int = 12
@@ -112,7 +113,7 @@ class NCGlobal: NSObject {
// Database Realm
//
let databaseDefault = "nextcloud.realm"
- let databaseSchemaVersion: UInt64 = 222
+ let databaseSchemaVersion: UInt64 = 237
// Intro selector
//
@@ -178,6 +179,15 @@ class NCGlobal: NSObject {
let buttonMoreStop = "stop"
let buttonMoreLock = "moreLock"
+ // Standard height sections header/footer
+ //
+ let heightButtonsCommand: CGFloat = 50
+ let heightButtonsView: CGFloat = 50
+ let heightSection: CGFloat = 30
+ let heightFooter: CGFloat = 1
+ let heightFooterButton: CGFloat = 30
+ let endHeightFooter: CGFloat = 85
+
// Text - OnlyOffice - Collabora - QuickLook
//
let editorText = "text"
@@ -200,6 +210,7 @@ class NCGlobal: NSObject {
let fileNameRichWorkspace = "Readme.md"
// Extension
+ //
@objc let extensionPreview = "ico"
// ContentPresenter
@@ -279,9 +290,9 @@ class NCGlobal: NSObject {
let selectorUploadAutoUpload = "uploadAutoUpload"
let selectorUploadAutoUploadAll = "uploadAutoUploadAll"
let selectorUploadFile = "uploadFile"
+ let selectorUploadFileNODelete = "UploadFileNODelete"
let selectorUploadFileShareExtension = "uploadFileShareExtension"
let selectorSaveAlbum = "saveAlbum"
- let selectorSaveBackground = "saveBackground"
let selectorSaveAlbumLivePhotoIMG = "saveAlbumLivePhotoIMG"
let selectorSaveAlbumLivePhotoMOV = "saveAlbumLivePhotoMOV"
let selectorSaveAsScan = "saveAsScan"
@@ -313,36 +324,36 @@ class NCGlobal: NSObject {
let notificationCenterApplicationDidBecomeActive = "applicationDidBecomeActive"
let notificationCenterApplicationWillResignActive = "applicationWillResignActive"
- @objc let notificationCenterInitialize = "initialize"
+ @objc let notificationCenterInitialize = "initialize" // userInfo?: atStart
@objc let notificationCenterChangeTheming = "changeTheming"
let notificationCenterRichdocumentGrabFocus = "richdocumentGrabFocus"
let notificationCenterReloadDataNCShare = "reloadDataNCShare"
let notificationCenterCloseRichWorkspaceWebView = "closeRichWorkspaceWebView"
- let notificationCenterUpdateBadgeNumber = "updateBadgeNumber"
+ let notificationCenterUpdateBadgeNumber = "updateBadgeNumber" // userInfo: counter
let notificationCenterReloadAvatar = "reloadAvatar"
- let notificationCenterOpenFileViewInFolder = "openFileViewInFolder" // userInfo: serverUrl, fileName
- @objc let notificationCenterReloadDataSource = "reloadDataSource" // userInfo: ocId?, serverUrl?
+ @objc let notificationCenterReloadDataSource = "reloadDataSource" // userInfo: serverUrl?
+ let notificationCenterReloadDataSourceNetwork = "reloadDataSourceNetwork" // userInfo: serverUrl?
let notificationCenterReloadDataSourceNetworkForced = "reloadDataSourceNetworkForced" // userInfo: serverUrl?
let notificationCenterChangeStatusFolderE2EE = "changeStatusFolderE2EE" // userInfo: serverUrl
- let notificationCenterDownloadStartFile = "downloadStartFile" // userInfo: ocId
- let notificationCenterDownloadedFile = "downloadedFile" // userInfo: ocId, selector, errorCode, errorDescription
- let notificationCenterDownloadCancelFile = "downloadCancelFile" // userInfo: ocId
+ let notificationCenterDownloadStartFile = "downloadStartFile" // userInfo: ocId, serverUrl, account
+ let notificationCenterDownloadedFile = "downloadedFile" // userInfo: ocId, serverUrl, account, selector, errorCode, errorDescription
+ let notificationCenterDownloadCancelFile = "downloadCancelFile" // userInfo: ocId, serverUrl, account
- let notificationCenterUploadStartFile = "uploadStartFile" // userInfo: ocId
- @objc let notificationCenterUploadedFile = "uploadedFile" // userInfo: ocId, ocIdTemp, errorCode, errorDescription
+ let notificationCenterUploadStartFile = "uploadStartFile" // userInfo: ocId, serverUrl, account, fileName, sessionSelector
+ @objc let notificationCenterUploadedFile = "uploadedFile" // userInfo: ocId, serverUrl, account, fileName, ocIdTemp, errorCode, errorDescription
let notificationCenterUploadCancelFile = "uploadCancelFile" // userInfo: ocId, serverUrl, account
let notificationCenterProgressTask = "progressTask" // userInfo: account, ocId, serverUrl, status, progress, totalBytes, totalBytesExpected
- let notificationCenterCreateFolder = "createFolder" // userInfo: ocId
- let notificationCenterDeleteFile = "deleteFile" // userInfo: ocId, fileNameView, classFile, onlyLocalCache
- let notificationCenterRenameFile = "renameFile" // userInfo: ocId, errorCode, errorDescription
- let notificationCenterMoveFile = "moveFile" // userInfo: ocId, serverUrlTo
- let notificationCenterCopyFile = "copyFile" // userInfo: ocId, serverUrlFrom
- let notificationCenterFavoriteFile = "favoriteFile" // userInfo: ocId
+ let notificationCenterCreateFolder = "createFolder" // userInfo: ocId, serverUrl, account
+ let notificationCenterDeleteFile = "deleteFile" // userInfo: ocId, fileNameView, serverUrl, account, classFile, onlyLocalCache
+ let notificationCenterRenameFile = "renameFile" // userInfo: ocId, account
+ let notificationCenterMoveFile = "moveFile" // userInfo: ocId, account, serverUrlFrom
+ let notificationCenterCopyFile = "copyFile" // userInfo: ocId, serverUrlTo
+ let notificationCenterFavoriteFile = "favoriteFile" // userInfo: ocId, serverUrl
let notificationCenterMenuSearchTextPDF = "menuSearchTextPDF"
let notificationCenterMenuGotToPageInPDF = "menuGotToPageInPDF"
@@ -361,7 +372,10 @@ class NCGlobal: NSObject {
let notificationCenterPlayMedia = "playMedia"
let notificationCenterPauseMedia = "pauseMedia"
- // Tip
+ // TIP
//
let tipNCViewerPDFThumbnail = "tipncviewerpdfthumbnail"
+ let tipNCCollectionViewCommonAccountRequest = "tipnccollectionviewcommonaccountrequest"
+ let tipNCScanAddImage = "tipncscanaddimage"
+ let tipNCViewerMediaDetailView = "tipncviewermediadetailview"
}
diff --git a/iOSClient/Networking/NCAutoUpload.swift b/iOSClient/Networking/NCAutoUpload.swift
index 2e080974c..856c3f792 100644
--- a/iOSClient/Networking/NCAutoUpload.swift
+++ b/iOSClient/Networking/NCAutoUpload.swift
@@ -24,6 +24,7 @@
import UIKit
import CoreLocation
import NCCommunication
+import Photos
class NCAutoUpload: NSObject {
@objc static let shared: NCAutoUpload = {
@@ -37,74 +38,63 @@ class NCAutoUpload: NSObject {
// MARK: -
@objc func initAutoUpload(viewController: UIViewController?, completion: @escaping (_ items: Int) -> Void) {
- if let activeAccount = NCManageDatabase.shared.getActiveAccount() {
- if activeAccount.autoUpload {
- NCAskAuthorization.shared.askAuthorizationPhotoLibrary(viewController: viewController) { hasPermission in
- if hasPermission {
- self.uploadAssetsNewAndFull(viewController: viewController, selector: NCGlobal.shared.selectorUploadAutoUpload, log: "Init Auto Upload") { items in
- if items > 0 {
- self.appDelegate.networkingProcessUpload?.startProcess()
- }
- completion(items)
- }
+ guard let activeAccount = NCManageDatabase.shared.getActiveAccount(), activeAccount.autoUpload else {
+ completion(0)
+ return
+ }
- } else {
- NCManageDatabase.shared.setAccountAutoUploadProperty("autoUpload", state: false)
- completion(0)
- }
- }
- } else {
+ NCAskAuthorization.shared.askAuthorizationPhotoLibrary(viewController: viewController) { hasPermission in
+ guard hasPermission else {
+ NCManageDatabase.shared.setAccountAutoUploadProperty("autoUpload", state: false)
completion(0)
+ return
+ }
+
+ self.uploadAssetsNewAndFull(viewController: viewController, selector: NCGlobal.shared.selectorUploadAutoUpload, log: "Init Auto Upload") { items in
+ completion(items)
}
- } else {
- completion(0)
}
}
@objc func autoUploadFullPhotos(viewController: UIViewController?, log: String) {
+
NCAskAuthorization.shared.askAuthorizationPhotoLibrary(viewController: appDelegate.window?.rootViewController) { hasPermission in
- if hasPermission {
- NCContentPresenter.shared.messageNotification("_attention_", description: "_create_full_upload_", delay: NCGlobal.shared.dismissAfterSecondLong, type: .info, errorCode: NCGlobal.shared.errorNoError, priority: .max)
- NCUtility.shared.startActivityIndicator(backgroundView: nil, blurEffect: true)
- self.uploadAssetsNewAndFull(viewController: viewController, selector: NCGlobal.shared.selectorUploadAutoUploadAll, log: log) { _ in
- NCUtility.shared.stopActivityIndicator()
- }
+ guard hasPermission else { return }
+
+ NCContentPresenter.shared.messageNotification("_attention_", description: "_create_full_upload_", delay: NCGlobal.shared.dismissAfterSecondLong, type: .info, errorCode: NCGlobal.shared.errorNoError, priority: .max)
+ NCActivityIndicator.shared.start()
+ self.uploadAssetsNewAndFull(viewController: viewController, selector: NCGlobal.shared.selectorUploadAutoUploadAll, log: log) { _ in
+ NCActivityIndicator.shared.stop()
}
}
}
private func uploadAssetsNewAndFull(viewController: UIViewController?, selector: String, log: String, completion: @escaping (_ items: Int) -> Void) {
-
- if appDelegate.account == "" { return }
-
+ guard !appDelegate.account.isEmpty else {
+ completion(0)
+ return
+ }
guard let account = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", appDelegate.account)) else { return }
- let autoUploadPath = NCManageDatabase.shared.getAccountAutoUploadPath(urlBase: account.urlBase, account: account.account)
- var counterLivePhoto: Int = 0
- var metadataFull: [tableMetadata] = []
- var counterItemsUpload: Int = 0
+
DispatchQueue.global(qos: .background).async {
- self.getCameraRollAssets(viewController: viewController, account: account, selector: selector, alignPhotoLibrary: false) { assets in
+ let autoUploadPath = NCManageDatabase.shared.getAccountAutoUploadPath(urlBase: account.urlBase, account: account.account)
+ var metadatas: [tableMetadata] = []
- if assets == nil || assets?.count == 0 {
+ self.getCameraRollAssets(viewController: viewController, account: account, selector: selector, alignPhotoLibrary: false) { assets in
+ guard let assets = assets, !assets.isEmpty else {
NCCommunicationCommon.shared.writeLog("Automatic upload, no new assets found [" + log + "]")
- DispatchQueue.main.async {
- completion(counterItemsUpload)
- }
+ completion(0)
return
- } else {
- NCCommunicationCommon.shared.writeLog("Automatic upload, new \(assets?.count ?? 0) assets found [" + log + "]")
}
- guard let assets = assets else { return }
+ NCCommunicationCommon.shared.writeLog("Automatic upload, new \(assets.count) assets found [" + log + "]")
// Create the folder for auto upload & if request the subfolders
if !NCNetworking.shared.createFolder(assets: assets, selector: selector, useSubFolder: account.autoUploadCreateSubfolder, account: account.account, urlBase: account.urlBase) {
- DispatchQueue.main.async {
- if selector == NCGlobal.shared.selectorUploadAutoUploadAll {
- NCContentPresenter.shared.messageNotification("_error_", description: "_error_createsubfolders_upload_", delay: NCGlobal.shared.dismissAfterSecond, type: .error, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
- }
- return completion(counterItemsUpload)
+ if selector == NCGlobal.shared.selectorUploadAutoUploadAll {
+ NCContentPresenter.shared.messageNotification("_error_", description: "_error_createsubfolders_upload_", delay: NCGlobal.shared.dismissAfterSecond, type: .error, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
}
+ return completion(0)
}
self.endForAssetToUpload = false
@@ -115,10 +105,13 @@ class NCAutoUpload: NSObject {
var session: String = ""
guard let assetDate = asset.creationDate else { continue }
let assetMediaType = asset.mediaType
- let formatter = DateFormatter()
var serverUrl: String = ""
-
let fileName = CCUtility.createFileName(asset.value(forKey: "filename") as? String, fileDate: assetDate, fileType: assetMediaType, keyFileName: NCGlobal.shared.keyFileNameAutoUploadMask, keyFileNameType: NCGlobal.shared.keyFileNameAutoUploadType, keyFileNameOriginal: NCGlobal.shared.keyFileNameOriginalAutoUpload, forcedNewFileName: false)!
+ let formatter = DateFormatter()
+ formatter.dateFormat = "yyyy"
+ let yearString = formatter.string(from: assetDate)
+ formatter.dateFormat = "MM"
+ let monthString = formatter.string(from: assetDate)
if asset.mediaSubtypes.contains(.photoLive) && CCUtility.getLivePhoto() {
livePhoto = true
@@ -138,11 +131,6 @@ class NCAutoUpload: NSObject {
} else { session = NCNetworking.shared.sessionIdentifierBackground }
}
- formatter.dateFormat = "yyyy"
- let yearString = formatter.string(from: assetDate)
- formatter.dateFormat = "MM"
- let monthString = formatter.string(from: assetDate)
-
if account.autoUploadCreateSubfolder {
serverUrl = autoUploadPath + "/" + yearString + "/" + monthString
} else {
@@ -155,86 +143,36 @@ class NCAutoUpload: NSObject {
if ext == "HEIC" && CCUtility.getFormatCompatibility() {
fileNameSearchMetadata = (fileNameSearchMetadata as NSString).deletingPathExtension + ".jpg"
}
-
if NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileNameView == %@", account.account, serverUrl, fileNameSearchMetadata)) != nil {
-
if selector == NCGlobal.shared.selectorUploadAutoUpload {
NCManageDatabase.shared.addPhotoLibrary([asset], account: account.account)
}
-
} else {
-
- /* INSERT METADATA FOR UPLOAD */
- let metadataForUpload = NCManageDatabase.shared.createMetadata(account: account.account, user: account.user, userId: account.userId, fileName: fileName, fileNameView: fileName, ocId: NSUUID().uuidString, serverUrl: serverUrl, urlBase: account.urlBase, url: "", contentType: "", livePhoto: livePhoto)
- metadataForUpload.assetLocalIdentifier = asset.localIdentifier
- metadataForUpload.session = session
- metadataForUpload.sessionSelector = selector
- metadataForUpload.status = NCGlobal.shared.metadataStatusWaitUpload
+ let metadata = NCManageDatabase.shared.createMetadata(account: account.account, user: account.user, userId: account.userId, fileName: fileName, fileNameView: fileName, ocId: NSUUID().uuidString, serverUrl: serverUrl, urlBase: account.urlBase, url: "", contentType: "", isLivePhoto: livePhoto)
+ metadata.assetLocalIdentifier = asset.localIdentifier
+ metadata.session = session
+ metadata.sessionSelector = selector
+ metadata.status = NCGlobal.shared.metadataStatusWaitUpload
if assetMediaType == PHAssetMediaType.video {
- metadataForUpload.classFile = NCCommunicationCommon.typeClassFile.video.rawValue
+ metadata.classFile = NCCommunicationCommon.typeClassFile.video.rawValue
} else if assetMediaType == PHAssetMediaType.image {
- metadataForUpload.classFile = NCCommunicationCommon.typeClassFile.image.rawValue
+ metadata.classFile = NCCommunicationCommon.typeClassFile.image.rawValue
}
-
if selector == NCGlobal.shared.selectorUploadAutoUpload {
- NCCommunicationCommon.shared.writeLog("Automatic upload added \(metadataForUpload.fileNameView) with Identifier \(metadataForUpload.assetLocalIdentifier)")
- self.appDelegate.networkingProcessUpload?.createProcessUploads(metadatas: [metadataForUpload], verifyAlreadyExists: true)
+ NCCommunicationCommon.shared.writeLog("Automatic upload added \(metadata.fileNameView) with Identifier \(metadata.assetLocalIdentifier)")
NCManageDatabase.shared.addPhotoLibrary([asset], account: account.account)
- } else if selector == NCGlobal.shared.selectorUploadAutoUploadAll {
- metadataFull.append(metadataForUpload)
- }
- counterItemsUpload += 1
-
- /* INSERT METADATA MOV LIVE PHOTO FOR UPLOAD */
- if livePhoto {
-
- counterLivePhoto += 1
- let fileName = (fileName as NSString).deletingPathExtension + ".mov"
- let ocId = NSUUID().uuidString
- let filePath = CCUtility.getDirectoryProviderStorageOcId(ocId, fileNameView: fileName)!
-
- CCUtility.extractLivePhotoAsset(asset, filePath: filePath) { url in
- if url != nil {
- let metadataForUpload = NCManageDatabase.shared.createMetadata(account: account.account, user: account.user, userId: account.userId, fileName: fileName, fileNameView: fileName, ocId: ocId, serverUrl: serverUrl, urlBase: account.urlBase, url: "", contentType: "", livePhoto: livePhoto)
- metadataForUpload.session = session
- metadataForUpload.sessionSelector = selector
- metadataForUpload.size = NCUtilityFileSystem.shared.getFileSize(filePath: filePath)
- metadataForUpload.status = NCGlobal.shared.metadataStatusWaitUpload
- metadataForUpload.classFile = NCCommunicationCommon.typeClassFile.video.rawValue
-
- if selector == NCGlobal.shared.selectorUploadAutoUpload {
- NCCommunicationCommon.shared.writeLog("Automatic upload added Live Photo \(metadataForUpload.fileNameView) with Identifier \(metadataForUpload.assetLocalIdentifier)")
- self.appDelegate.networkingProcessUpload?.createProcessUploads(metadatas: [metadataForUpload], verifyAlreadyExists: true)
-
- } else if selector == NCGlobal.shared.selectorUploadAutoUploadAll {
- metadataFull.append(metadataForUpload)
- }
- counterItemsUpload += 1
- }
- counterLivePhoto -= 1
- if counterLivePhoto == 0 && self.endForAssetToUpload {
- DispatchQueue.main.async {
- if selector == NCGlobal.shared.selectorUploadAutoUploadAll {
- self.appDelegate.networkingProcessUpload?.createProcessUploads(metadatas: metadataFull)
- }
- completion(counterItemsUpload)
- }
- }
- }
}
+ metadatas.append(metadata)
}
}
self.endForAssetToUpload = true
-
- if counterLivePhoto == 0 {
- DispatchQueue.main.async {
- if selector == NCGlobal.shared.selectorUploadAutoUploadAll {
- self.appDelegate.networkingProcessUpload?.createProcessUploads(metadatas: metadataFull)
- }
- completion(counterItemsUpload)
- }
+ if selector == NCGlobal.shared.selectorUploadAutoUploadAll {
+ self.appDelegate.networkingProcessUpload?.createProcessUploads(metadatas: metadatas)
+ } else {
+ self.appDelegate.networkingProcessUpload?.createProcessUploads(metadatas: metadatas, verifyAlreadyExists: true)
}
+ completion(metadatas.count)
}
}
}
@@ -242,66 +180,66 @@ class NCAutoUpload: NSObject {
// MARK: -
@objc func alignPhotoLibrary(viewController: UIViewController?) {
- if let activeAccount = NCManageDatabase.shared.getActiveAccount() {
- getCameraRollAssets(viewController: viewController, account: activeAccount, selector: NCGlobal.shared.selectorUploadAutoUploadAll, alignPhotoLibrary: true) { assets in
- NCManageDatabase.shared.clearTable(tablePhotoLibrary.self, account: activeAccount.account)
- if let assets = assets {
- NCManageDatabase.shared.addPhotoLibrary(assets, account: activeAccount.account)
- NCCommunicationCommon.shared.writeLog("Align Photo Library \(assets.count)")
- }
- }
+ guard let activeAccount = NCManageDatabase.shared.getActiveAccount() else { return }
+
+ getCameraRollAssets(viewController: viewController, account: activeAccount, selector: NCGlobal.shared.selectorUploadAutoUploadAll, alignPhotoLibrary: true) { assets in
+ NCManageDatabase.shared.clearTable(tablePhotoLibrary.self, account: activeAccount.account)
+ guard let assets = assets else { return }
+
+ NCManageDatabase.shared.addPhotoLibrary(assets, account: activeAccount.account)
+ NCCommunicationCommon.shared.writeLog("Align Photo Library \(assets.count)")
}
}
private func getCameraRollAssets(viewController: UIViewController?, account: tableAccount, selector: String, alignPhotoLibrary: Bool, completion: @escaping (_ assets: [PHAsset]?) -> Void) {
NCAskAuthorization.shared.askAuthorizationPhotoLibrary(viewController: viewController) { hasPermission in
- if hasPermission {
- let assetCollection = PHAssetCollection.fetchAssetCollections(with: PHAssetCollectionType.smartAlbum, subtype: PHAssetCollectionSubtype.smartAlbumUserLibrary, options: nil)
- if assetCollection.count > 0 {
-
- let predicateImage = NSPredicate(format: "mediaType == %i", PHAssetMediaType.image.rawValue)
- let predicateVideo = NSPredicate(format: "mediaType == %i", PHAssetMediaType.video.rawValue)
- var predicate: NSPredicate?
- let fetchOptions = PHFetchOptions()
- var newAssets: [PHAsset] = []
-
- if alignPhotoLibrary || (account.autoUploadImage && account.autoUploadVideo) {
- predicate = NSCompoundPredicate(orPredicateWithSubpredicates: [predicateImage, predicateVideo])
- } else if account.autoUploadImage {
- predicate = predicateImage
- } else if account.autoUploadVideo {
- predicate = predicateVideo
- } else {
- return completion(nil)
- }
+ guard hasPermission else {
+ completion(nil)
+ return
+ }
+ let assetCollection = PHAssetCollection.fetchAssetCollections(with: PHAssetCollectionType.smartAlbum, subtype: PHAssetCollectionSubtype.smartAlbumUserLibrary, options: nil)
+ if assetCollection.count == 0 {
+ completion(nil)
+ return
+ }
- fetchOptions.predicate = predicate
- let assets: PHFetchResult<PHAsset> = PHAsset.fetchAssets(in: assetCollection.firstObject!, options: fetchOptions)
-
- if selector == NCGlobal.shared.selectorUploadAutoUpload {
- var creationDate = ""
- var idAsset = ""
- let idsAsset = NCManageDatabase.shared.getPhotoLibraryIdAsset(image: account.autoUploadImage, video: account.autoUploadVideo, account: account.account)
- assets.enumerateObjects { asset, _, _ in
- if asset.creationDate != nil { creationDate = String(describing: asset.creationDate!) }
- idAsset = account.account + asset.localIdentifier + creationDate
- if !(idsAsset?.contains(idAsset) ?? false) {
- newAssets.append(asset)
- }
- }
- } else {
- assets.enumerateObjects { asset, _, _ in
- newAssets.append(asset)
- }
+ let predicateImage = NSPredicate(format: "mediaType == %i", PHAssetMediaType.image.rawValue)
+ let predicateVideo = NSPredicate(format: "mediaType == %i", PHAssetMediaType.video.rawValue)
+ var predicate: NSPredicate?
+ let fetchOptions = PHFetchOptions()
+ var newAssets: [PHAsset] = []
+
+ if alignPhotoLibrary || (account.autoUploadImage && account.autoUploadVideo) {
+ predicate = NSCompoundPredicate(orPredicateWithSubpredicates: [predicateImage, predicateVideo])
+ } else if account.autoUploadImage {
+ predicate = predicateImage
+ } else if account.autoUploadVideo {
+ predicate = predicateVideo
+ } else {
+ return completion(nil)
+ }
+
+ fetchOptions.predicate = predicate
+ let assets: PHFetchResult<PHAsset> = PHAsset.fetchAssets(in: assetCollection.firstObject!, options: fetchOptions)
+
+ if selector == NCGlobal.shared.selectorUploadAutoUpload {
+ var creationDate = ""
+ var idAsset = ""
+ let idsAsset = NCManageDatabase.shared.getPhotoLibraryIdAsset(image: account.autoUploadImage, video: account.autoUploadVideo, account: account.account)
+ assets.enumerateObjects { asset, _, _ in
+ if asset.creationDate != nil { creationDate = String(describing: asset.creationDate!) }
+ idAsset = account.account + asset.localIdentifier + creationDate
+ if !(idsAsset?.contains(idAsset) ?? false) {
+ newAssets.append(asset)
}
- completion(newAssets)
- } else {
- completion(nil)
}
} else {
- completion(nil)
+ assets.enumerateObjects { asset, _, _ in
+ newAssets.append(asset)
+ }
}
+ completion(newAssets)
}
}
}
diff --git a/iOSClient/Networking/NCNetworking.swift b/iOSClient/Networking/NCNetworking.swift
index 84c074ac9..299c0e34e 100644
--- a/iOSClient/Networking/NCNetworking.swift
+++ b/iOSClient/Networking/NCNetworking.swift
@@ -26,6 +26,7 @@ import OpenSSL
import NCCommunication
import Alamofire
import Queuer
+import Photos
@objc public protocol NCNetworkingDelegate {
@objc optional func downloadProgress(_ progress: Float, totalBytes: Int64, totalBytesExpected: Int64, fileName: String, serverUrl: String, session: URLSession, task: URLSessionTask)
@@ -44,9 +45,9 @@ import Queuer
var lastReachability: Bool = true
var networkReachability: NCCommunicationCommon.typeReachability?
- var downloadRequest: [String: DownloadRequest] = [:]
- var uploadRequest: [String: UploadRequest] = [:]
- var uploadMetadataInBackground: [String: tableMetadata] = [:]
+ let downloadRequest = ThreadSafeDictionary<String,DownloadRequest>()
+ let uploadRequest = ThreadSafeDictionary<String,UploadRequest>()
+ let uploadMetadataInBackground = ThreadSafeDictionary<String,tableMetadata>()
@objc public let sessionMaximumConnectionsPerHost = 5
@objc public let sessionIdentifierBackground: String = "com.nextcloud.session.upload.background"
@@ -89,6 +90,11 @@ import Queuer
}()
#endif
+ // REQUESTS
+
+ var requestsUnifiedSearch: [DataRequest] = []
+
+
// MARK: - init
override init() {
@@ -106,22 +112,18 @@ import Queuer
func networkReachabilityObserver(_ typeReachability: NCCommunicationCommon.typeReachability) {
- #if !EXTENSION
+#if !EXTENSION
if typeReachability == NCCommunicationCommon.typeReachability.reachableCellular || typeReachability == NCCommunicationCommon.typeReachability.reachableEthernetOrWiFi {
-
if !lastReachability {
NCService.shared.startRequestServicesServer()
}
lastReachability = true
-
} else {
-
if lastReachability {
NCContentPresenter.shared.messageNotification("_network_not_available_", description: nil, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: -1009)
}
lastReachability = false
}
-
networkReachability = typeReachability
#endif
}
@@ -227,7 +229,6 @@ import Queuer
if x509cert == nil {
print("[LOG] OpenSSL couldn't parse X509 Certificate")
} else {
-
// save details
if FileManager.default.fileExists(atPath: certNamePathTXT) {
do {
@@ -241,7 +242,6 @@ import Queuer
BIO_free(output)
}
fclose(fileCertInfo)
-
X509_free(x509cert)
}
@@ -249,29 +249,26 @@ import Queuer
}
func checkPushNotificationServerProxyCertificateUntrusted(viewController: UIViewController?, completion: @escaping (_ errorCode: Int) -> Void) {
-
guard let host = URL(string: NCBrandOptions.shared.pushNotificationServerProxy)?.host else { return }
NCCommunication.shared.checkServer(serverUrl: NCBrandOptions.shared.pushNotificationServerProxy) { errorCode, _ in
+ guard errorCode == 0 else {
+ completion(0)
+ return
+ }
if errorCode == 0 {
-
NCNetworking.shared.writeCertificate(host: host)
completion(errorCode)
-
} else if errorCode == NSURLErrorServerCertificateUntrusted {
-
let alertController = UIAlertController(title: NSLocalizedString("_ssl_certificate_untrusted_", comment: ""), message: NSLocalizedString("_connect_server_anyway_", comment: ""), preferredStyle: .alert)
-
alertController.addAction(UIAlertAction(title: NSLocalizedString("_yes_", comment: ""), style: .default, handler: { _ in
NCNetworking.shared.writeCertificate(host: host)
completion(0)
}))
-
alertController.addAction(UIAlertAction(title: NSLocalizedString("_no_", comment: ""), style: .default, handler: { _ in
completion(errorCode)
}))
-
alertController.addAction(UIAlertAction(title: NSLocalizedString("_certificate_details_", comment: ""), style: .default, handler: { _ in
if let navigationController = UIStoryboard(name: "NCViewCertificateDetails", bundle: nil).instantiateInitialViewController() as? UINavigationController {
let vcCertificateDetails = navigationController.topViewController as! NCViewCertificateDetails
@@ -279,12 +276,7 @@ import Queuer
viewController?.present(navigationController, animated: true)
}
}))
-
viewController?.present(alertController, animated: true)
-
- } else {
-
- completion(0)
}
}
}
@@ -309,21 +301,13 @@ import Queuer
@objc func cancelDownload(ocId: String, serverUrl: String, fileNameView: String) {
- #if !EXTENSION
- // removed progress ocid
- DispatchQueue.main.async { (UIApplication.shared.delegate as! AppDelegate).listProgress[ocId] = nil }
- #endif
-
guard let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(ocId, fileNameView: fileNameView) else { return }
if let request = downloadRequest[fileNameLocalPath] {
request.cancel()
- } else {
- if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
-
- NCManageDatabase.shared.setMetadataSession(ocId: ocId, session: "", sessionError: "", sessionSelector: "", sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusNormal)
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadCancelFile, userInfo: ["ocId": metadata.ocId])
- }
+ } else if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
+ NCManageDatabase.shared.setMetadataSession(ocId: ocId, session: "", sessionError: "", sessionSelector: "", sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusNormal)
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadCancelFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account])
}
}
@@ -343,155 +327,90 @@ import Queuer
NCCommunication.shared.download(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, queue: NCCommunicationCommon.shared.backgroundQueue, requestHandler: { request in
self.downloadRequest[fileNameLocalPath] = request
+ self.downloadRequest.removeValue(forKey: fileNameLocalPath)
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusDownloading)
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadStartFile, userInfo: ["ocId":metadata.ocId])
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadStartFile, userInfo: ["ocId":metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account])
}, taskHandler: { (_) in
}, progressHandler: { (progress) in
if notificationCenterProgressTask {
- #if !EXTENSION
- // add progress ocid
- let progressType = NCGlobal.progressType(progress: Float(progress.fractionCompleted), totalBytes: progress.totalUnitCount, totalBytesExpected: progress.completedUnitCount)
- DispatchQueue.main.async { (UIApplication.shared.delegate as! AppDelegate).listProgress[metadata.ocId] = progressType }
- #endif
-
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterProgressTask, object: nil, userInfo: ["account":metadata.account, "ocId":metadata.ocId, "fileName":metadata.fileName, "serverUrl":metadata.serverUrl, "status":NSNumber(value: NCGlobal.shared.metadataStatusInDownload), "progress":NSNumber(value: progress.fractionCompleted), "totalBytes":NSNumber(value: progress.totalUnitCount), "totalBytesExpected":NSNumber(value: progress.completedUnitCount)])
}
-
progressHandler(progress)
}) { (account, etag, date, _, allHeaderFields, error, errorCode, errorDescription) in
-
+
+ self.downloadRequest.removeValue(forKey:fileNameLocalPath)
+
if error?.isExplicitlyCancelledError ?? false {
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: "", sessionError: "", sessionSelector: selector, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusNormal)
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadCancelFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account])
} else if errorCode == 0 {
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: "", sessionError: "", sessionSelector: selector, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusNormal, etag: etag)
NCManageDatabase.shared.addLocalFile(metadata: metadata)
-
#if !EXTENSION
if let result = NCManageDatabase.shared.getE2eEncryption(predicate: NSPredicate(format: "fileNameIdentifier == %@ AND serverUrl == %@", metadata.fileName, metadata.serverUrl)) {
-
NCEndToEndEncryption.sharedManager()?.decryptFileName(metadata.fileName, fileNameView: metadata.fileNameView, ocId: metadata.ocId, key: result.key, initializationVector: result.initializationVector, authenticationTag: result.authenticationTag)
}
CCUtility.setExif(metadata) { _, _, _, _, _ in }
#endif
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "selector": selector, "errorCode": 0, "errorDescription": ""])
} else {
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: "", sessionError: errorDescription, sessionSelector: selector, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusDownloadError)
-
#if !EXTENSION
if errorCode == 401 || errorCode == 403 {
NCNetworkingCheckRemoteUser.shared.checkRemoteUser(account: metadata.account, errorCode: errorCode, errorDescription: errorDescription)
}
#endif
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "selector": selector, "errorCode": errorCode, "errorDescription": errorDescription])
}
- self.downloadRequest[fileNameLocalPath] = nil
- #if !EXTENSION
- DispatchQueue.main.async { (UIApplication.shared.delegate as! AppDelegate).listProgress[metadata.ocId] = nil }
- #endif
-
- if error?.isExplicitlyCancelledError ?? false {
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadCancelFile, userInfo: ["ocId": metadata.ocId])
- } else {
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadedFile, userInfo: ["ocId": metadata.ocId, "selector": selector, "errorCode": errorCode, "errorDescription": errorDescription])
- }
-
- completion(errorCode)
+ DispatchQueue.main.async { completion(errorCode) }
}
}
// MARK: - Upload
- @objc func upload(metadata: tableMetadata, start: @escaping () -> Void, completion: @escaping (_ errorCode: Int, _ errorDescription: String) -> Void) {
-
- func uploadMetadata(_ metadata: tableMetadata) {
-
- // DETECT IF CHUNCK
- let chunckSize = CCUtility.getChunkSize() * 1000000
- if chunckSize > 0 && metadata.size > chunckSize {
- metadata.chunk = true
- metadata.session = NCCommunicationCommon.shared.sessionIdentifierUpload
- }
-
- // DETECT IF E2EE
- if CCUtility.isFolderEncrypted(metadata.serverUrl, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase) {
- metadata.e2eEncrypted = true
- }
-
- NCManageDatabase.shared.addMetadata(metadata)
- let metadata = tableMetadata.init(value: metadata)
+ @objc func upload(metadata: tableMetadata,
+ start: @escaping () -> () = { },
+ completion: @escaping (_ errorCode: Int, _ errorDescription: String) -> () = { errorCode, errorDescription in }) {
- NCCommunicationCommon.shared.writeLog("Upload file \(metadata.fileNameView) with Identifier \(metadata.assetLocalIdentifier) with size \(metadata.size) [CHUNCK \(metadata.chunk), E2EE \(metadata.e2eEncrypted)]")
+ let metadata = tableMetadata.init(value: metadata)
+ NCCommunicationCommon.shared.writeLog("Upload file \(metadata.fileNameView) with Identifier \(metadata.assetLocalIdentifier) with size \(metadata.size) [CHUNCK \(metadata.chunk), E2EE \(metadata.e2eEncrypted)]")
- if metadata.e2eEncrypted {
-#if !EXTENSION_FILE_PROVIDER_EXTENSION
- NCNetworkingE2EE.shared.upload(metadata: metadata, start: start) { errorCode, errorDescription in
- DispatchQueue.main.async {
- completion(errorCode, errorDescription)
- }
- }
-#endif
- } else if metadata.chunk {
- uploadChunkedFile(metadata: metadata, start: start) { errorCode, errorDescription in
- DispatchQueue.main.async {
- completion(errorCode, errorDescription)
- }
- }
- } else if metadata.session == NCCommunicationCommon.shared.sessionIdentifierUpload {
- uploadFile(metadata: metadata, start: start) { errorCode, errorDescription in
- DispatchQueue.main.async {
- completion(errorCode, errorDescription)
- }
- }
- } else {
- uploadFileInBackground(metadata: metadata, start: start) { errorCode, errorDescription in
- DispatchQueue.main.async {
- completion(errorCode, errorDescription)
- }
+ if metadata.e2eEncrypted {
+ #if !EXTENSION_FILE_PROVIDER_EXTENSION
+ NCNetworkingE2EE.shared.upload(metadata: metadata, start: start) { errorCode, errorDescription in
+ DispatchQueue.main.async {
+ completion(errorCode, errorDescription)
}
}
- }
-
- let metadata = tableMetadata.init(value: metadata)
-
- if metadata.assetLocalIdentifier.isEmpty {
-
- let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
- let results = NCCommunicationCommon.shared.getInternalType(fileName: metadata.fileNameView, mimeType: metadata.contentType, directory: false)
- metadata.contentType = results.mimeType
- metadata.iconName = results.iconName
- metadata.classFile = results.classFile
- if let date = NCUtilityFileSystem.shared.getFileCreationDate(filePath: fileNameLocalPath) {
- metadata.creationDate = date
+ #endif
+ } else if metadata.chunk {
+ uploadChunkedFile(metadata: metadata, start: start) { errorCode, errorDescription in
+ DispatchQueue.main.async {
+ completion(errorCode, errorDescription)
+ }
}
- if let date = NCUtilityFileSystem.shared.getFileModificationDate(filePath: fileNameLocalPath) {
- metadata.date = date
+ } else if metadata.session == NCCommunicationCommon.shared.sessionIdentifierUpload {
+ uploadFile(metadata: metadata, start: start) { errorCode, errorDescription in
+ DispatchQueue.main.async {
+ completion(errorCode, errorDescription)
+ }
}
- metadata.size = NCUtilityFileSystem.shared.getFileSize(filePath: fileNameLocalPath)
-
- uploadMetadata(metadata)
-
} else {
-
- CCUtility.extractImageVideoFromAssetLocalIdentifier(forUpload: metadata) { extractMetadata, fileNamePath in
-
- guard let metadata = extractMetadata else {
- NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
- return completion(NCGlobal.shared.errorInternalError, "Internal error")
+ uploadFileInBackground(metadata: metadata, start: start) { errorCode, errorDescription in
+ DispatchQueue.main.async {
+ completion(errorCode, errorDescription)
}
-
- let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
- NCUtilityFileSystem.shared.moveFileInBackground(atPath: fileNamePath!, toPath: fileNameLocalPath)
-
- uploadMetadata(metadata)
}
}
}
@@ -511,17 +430,11 @@ import Queuer
uploadTask = task
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, sessionError: "", sessionTaskIdentifier: task.taskIdentifier, status: NCGlobal.shared.metadataStatusUploading)
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadStartFile, userInfo: ["ocId": metadata.ocId])
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadStartFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "sessionSelector": metadata.sessionSelector])
start()
}, progressHandler: { progress in
- #if !EXTENSION
- // add progress ocid
- let progressType = NCGlobal.progressType(progress: Float(progress.fractionCompleted), totalBytes: progress.totalUnitCount, totalBytesExpected: progress.completedUnitCount)
- DispatchQueue.main.async { (UIApplication.shared.delegate as! AppDelegate).listProgress[metadata.ocId] = progressType }
- #endif
-
NotificationCenter.default.postOnMainThread(
name: NCGlobal.shared.notificationCenterProgressTask,
userInfo: [
@@ -536,7 +449,7 @@ import Queuer
}) { _, ocId, etag, date, size, _, _, errorCode, errorDescription in
- self.uploadRequest[fileNameLocalPath] = nil
+ self.uploadRequest.removeValue(forKey: fileNameLocalPath)
if let uploadTask = uploadTask {
self.uploadComplete(fileName: metadata.fileName, serverUrl: metadata.serverUrl, ocId: ocId, etag: etag, date: date, size: size, description: description, task: uploadTask, errorCode: errorCode, errorDescription: errorDescription)
}
@@ -563,7 +476,6 @@ import Queuer
if NCUtilityFileSystem.shared.getFileSize(filePath: fileNameLocalPath) == 0 && metadata.size != 0 {
NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
-
completion(NCGlobal.shared.errorResourceNotFound, NSLocalizedString("_error_not_found_", value: "The requested resource could not be found", comment: ""))
} else {
@@ -571,9 +483,7 @@ import Queuer
if let task = NCCommunicationBackground.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, dateCreationFile: metadata.creationDate as Date, dateModificationFile: metadata.date as Date, description: metadata.ocId, session: session!) {
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, sessionError: "", sessionTaskIdentifier: task.taskIdentifier, status: NCGlobal.shared.metadataStatusUploading)
-
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadStartFile, userInfo: ["ocId": metadata.ocId])
-
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadStartFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "sessionSelector": metadata.sessionSelector])
completion(0, "")
} else {
@@ -585,125 +495,110 @@ import Queuer
}
func uploadComplete(fileName: String, serverUrl: String, ocId: String?, etag: String?, date: NSDate?, size: Int64, description: String?, task: URLSessionTask, errorCode: Int, errorDescription: String) {
- guard delegate == nil else {
- delegate?.uploadComplete?(fileName: fileName, serverUrl: serverUrl, ocId: ocId, etag: etag, date: date, size: size, description: description, task: task, errorCode: errorCode, errorDescription: errorDescription)
- return
- }
+ DispatchQueue.global().async {
+ guard self.delegate == nil, let metadata = NCManageDatabase.shared.getMetadataFromOcId(description) else {
+ self.delegate?.uploadComplete?(fileName: fileName, serverUrl: serverUrl, ocId: ocId, etag: etag, date: date, size: size, description: description, task: task, errorCode: errorCode, errorDescription: errorDescription)
+ return
+ }
+ let ocIdTemp = metadata.ocId
+ var errorDescription = errorDescription
+ let selector = metadata.sessionSelector
- guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(description) else { return }
- let ocIdTemp = metadata.ocId
- var errorDescription = errorDescription
+ if errorCode == 0, let ocId = ocId, size == metadata.size {
- if errorCode == 0, let ocId = ocId, size == metadata.size {
+ let metadata = tableMetadata.init(value: metadata)
- let metadata = tableMetadata.init(value: metadata)
+ metadata.uploadDate = date ?? NSDate()
+ metadata.etag = etag ?? ""
+ metadata.ocId = ocId
- NCUtilityFileSystem.shared.moveFileInBackground(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId), toPath: CCUtility.getDirectoryProviderStorageOcId(ocId))
+ if let fileId = NCUtility.shared.ocIdToFileId(ocId: ocId) {
+ metadata.fileId = fileId
+ }
- metadata.uploadDate = date ?? NSDate()
- metadata.etag = etag ?? ""
- metadata.ocId = ocId
+ metadata.session = ""
+ metadata.sessionError = ""
+ metadata.sessionTaskIdentifier = 0
+ metadata.status = NCGlobal.shared.metadataStatusNormal
- if let fileId = NCUtility.shared.ocIdToFileId(ocId: ocId) {
- metadata.fileId = fileId
- }
+ // Delete Asset on Photos album
+ if CCUtility.getRemovePhotoCameraRoll() && !metadata.assetLocalIdentifier.isEmpty {
+ metadata.deleteAssetLocalIdentifier = true
+ }
- metadata.session = ""
- metadata.sessionError = ""
- metadata.sessionTaskIdentifier = 0
- metadata.status = NCGlobal.shared.metadataStatusNormal
+ NCManageDatabase.shared.addMetadata(metadata)
+ NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp))
- // Delete Asset on Photos album
- if CCUtility.getRemovePhotoCameraRoll() && !metadata.assetLocalIdentifier.isEmpty {
- metadata.deleteAssetLocalIdentifier = true
- }
+ if selector == NCGlobal.shared.selectorUploadFileNODelete {
+ NCUtilityFileSystem.shared.moveFile(atPath: CCUtility.getDirectoryProviderStorageOcId(ocIdTemp), toPath: CCUtility.getDirectoryProviderStorageOcId(ocId))
+ NCManageDatabase.shared.addLocalFile(metadata: metadata)
+ } else {
+ NCUtilityFileSystem.shared.deleteFile(filePath: CCUtility.getDirectoryProviderStorageOcId(ocIdTemp))
+ }
- if CCUtility.getDisableLocalCacheAfterUpload() {
- CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
+ NCCommunicationCommon.shared.writeLog("Upload complete " + serverUrl + "/" + fileName + ", result: success(\(size) bytes)")
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
} else {
- NCManageDatabase.shared.addLocalFile(metadata: metadata)
- }
- NCManageDatabase.shared.addMetadata(metadata)
- NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp))
-
-#if !EXTENSION
- self.getOcIdInBackgroundSession { listOcId in
- if listOcId.count == 0 && self.uploadRequest.count == 0 {
- let appDelegate = UIApplication.shared.delegate as! AppDelegate
- appDelegate.networkingProcessUpload?.startProcess()
- }
- }
- CCUtility.setExif(metadata) { _, _, _, _, _ in }
-#endif
+ if errorCode == NSURLErrorCancelled || errorCode == NCGlobal.shared.errorRequestExplicityCancelled {
- NCCommunicationCommon.shared.writeLog("Upload complete " + serverUrl + "/" + fileName + ", result: success(\(size) bytes)")
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
- } else {
- if errorCode == NSURLErrorCancelled || errorCode == NCGlobal.shared.errorRequestExplicityCancelled {
+ CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
+ NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadCancelFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account])
- CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
- NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
+ } else if errorCode == 401 || errorCode == 403 {
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadCancelFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account])
+ #if !EXTENSION
+ NCNetworkingCheckRemoteUser.shared.checkRemoteUser(account: metadata.account, errorCode: errorCode, errorDescription: errorDescription)
+ #endif
+ NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
- } else if errorCode == 401 || errorCode == 403 {
-#if !EXTENSION
- NCNetworkingCheckRemoteUser.shared.checkRemoteUser(account: metadata.account, errorCode: errorCode, errorDescription: errorDescription)
-#endif
- NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
- } else {
- if size == 0 {
- errorDescription = "File length 0"
- NCCommunicationCommon.shared.writeLog("Upload error 0 length " + serverUrl + "/" + fileName + ", result: success(\(size) bytes)")
+ } else {
+ if size == 0 {
+ errorDescription = "File length 0"
+ NCCommunicationCommon.shared.writeLog("Upload error 0 length " + serverUrl + "/" + fileName + ", result: success(\(size) bytes)")
+ }
+ NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
}
- NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
}
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
- }
-#if !EXTENSION
- DispatchQueue.main.async { (UIApplication.shared.delegate as! AppDelegate).listProgress[metadata.ocId] = nil }
-#endif
- // Delete
- self.uploadMetadataInBackground[fileName + serverUrl] = nil
+ self.uploadMetadataInBackground.removeValue(forKey: fileName + serverUrl)
+ self.delegate?.uploadComplete?(fileName: fileName, serverUrl: serverUrl, ocId: ocId, etag: etag, date: date, size: size, description: description, task: task, errorCode: errorCode, errorDescription: errorDescription)
+ }
}
func uploadProgress(_ progress: Float, totalBytes: Int64, totalBytesExpected: Int64, fileName: String, serverUrl: String, session: URLSession, task: URLSessionTask) {
- delegate?.uploadProgress?(progress, totalBytes: totalBytes, totalBytesExpected: totalBytesExpected, fileName: fileName, serverUrl: serverUrl, session: session, task: task)
-
- var metadata: tableMetadata?
- let description: String = task.taskDescription ?? ""
-
- if let metadataTmp = self.uploadMetadataInBackground[fileName+serverUrl] {
- metadata = metadataTmp
- } else if let metadataTmp = NCManageDatabase.shared.getMetadataFromOcId(description) {
- self.uploadMetadataInBackground[fileName+serverUrl] = metadataTmp
- metadata = metadataTmp
- }
+ DispatchQueue.global().async {
+ self.delegate?.uploadProgress?(progress, totalBytes: totalBytes, totalBytesExpected: totalBytesExpected, fileName: fileName, serverUrl: serverUrl, session: session, task: task)
- if let metadata = metadata {
+ var metadata: tableMetadata?
+ let description: String = task.taskDescription ?? ""
- #if !EXTENSION
- // add progress ocid
- let progressType = NCGlobal.progressType(progress: progress, totalBytes: totalBytes, totalBytesExpected: totalBytesExpected)
- DispatchQueue.main.async { (UIApplication.shared.delegate as! AppDelegate).listProgress[metadata.ocId] = progressType }
- #endif
+ if let metadataTmp = self.uploadMetadataInBackground[fileName+serverUrl] {
+ metadata = metadataTmp
+ } else if let metadataTmp = NCManageDatabase.shared.getMetadataFromOcId(description) {
+ self.uploadMetadataInBackground[fileName+serverUrl] = metadataTmp
+ metadata = metadataTmp
+ }
- NotificationCenter.default.postOnMainThread(
- name: NCGlobal.shared.notificationCenterProgressTask,
- userInfo: [
- "account": metadata.account,
- "ocId": metadata.ocId,
- "fileName": metadata.fileName,
- "serverUrl": serverUrl,
- "status": NSNumber(value: NCGlobal.shared.metadataStatusInUpload),
- "progress": NSNumber(value: progress),
- "totalBytes": NSNumber(value: totalBytes),
- "totalBytesExpected": NSNumber(value: totalBytesExpected)])
+ if let metadata = metadata {
+ NotificationCenter.default.postOnMainThread(
+ name: NCGlobal.shared.notificationCenterProgressTask,
+ userInfo: [
+ "account": metadata.account,
+ "ocId": metadata.ocId,
+ "fileName": metadata.fileName,
+ "serverUrl": serverUrl,
+ "status": NSNumber(value: NCGlobal.shared.metadataStatusInUpload),
+ "progress": NSNumber(value: progress),
+ "totalBytes": NSNumber(value: totalBytes),
+ "totalBytesExpected": NSNumber(value: totalBytesExpected)])
+ }
}
}
- func getOcIdInBackgroundSession(completion: @escaping (_ listOcId: [String]) -> Void) {
+ func getOcIdInBackgroundSession(queue: DispatchQueue = .main, completion: @escaping (_ listOcId: [String]) -> Void) {
var listOcId: [String] = []
@@ -715,7 +610,7 @@ import Queuer
for task in tasks {
listOcId.append(task.description)
}
- completion(listOcId)
+ queue.async { completion(listOcId) }
})
})
}
@@ -725,12 +620,7 @@ import Queuer
@objc func cancelTransferMetadata(_ metadata: tableMetadata, completion: @escaping () -> Void) {
let metadata = tableMetadata.init(value: metadata)
-
- #if !EXTENSION
- // removed progress ocid
- DispatchQueue.main.async { (UIApplication.shared.delegate as! AppDelegate).listProgress[metadata.ocId] = nil }
- #endif
-
+
if metadata.session.count == 0 {
NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
return completion()
@@ -742,7 +632,7 @@ import Queuer
return completion()
}
- if metadata.session == NCCommunicationCommon.shared.sessionIdentifierUpload {
+ if metadata.session == NCCommunicationCommon.shared.sessionIdentifierUpload || metadata.chunk {
guard let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView) else { return }
@@ -800,14 +690,10 @@ import Queuer
var counter = 0
for metadata in metadatas {
counter += 1
-
if metadata.status == NCGlobal.shared.metadataStatusWaitDownload || metadata.status == NCGlobal.shared.metadataStatusDownloadError {
-
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: "", sessionError: "", sessionSelector: "", sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusNormal)
}
-
if metadata.status == NCGlobal.shared.metadataStatusDownloading || metadata.status == NCGlobal.shared.metadataStatusUploading {
-
self.cancelTransferMetadata(metadata) {
if counter == metadatas.count {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
@@ -826,14 +712,10 @@ import Queuer
func cancelAllDownloadTransfer() {
let metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "status != %d", NCGlobal.shared.metadataStatusNormal))
-
for metadata in metadatas {
-
if metadata.status == NCGlobal.shared.metadataStatusWaitDownload || metadata.status == NCGlobal.shared.metadataStatusDownloadError {
-
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: "", sessionError: "", sessionSelector: "", sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusNormal)
}
-
if metadata.status == NCGlobal.shared.metadataStatusDownloading && metadata.session == NCCommunicationCommon.shared.sessionIdentifierDownload {
cancelDownload(ocId: metadata.ocId, serverUrl: metadata.serverUrl, fileNameView: metadata.fileNameView)
}
@@ -849,83 +731,224 @@ import Queuer
@objc func readFolder(serverUrl: String, account: String, completion: @escaping (_ account: String, _ metadataFolder: tableMetadata?, _ metadatas: [tableMetadata]?, _ metadatasUpdate: [tableMetadata]?, _ metadatasLocalUpdate: [tableMetadata]?, _ metadatasDelete: [tableMetadata]?, _ errorCode: Int, _ errorDescription: String) -> Void) {
NCCommunication.shared.readFileOrFolder(serverUrlFileName: serverUrl, depth: "1", showHiddenFiles: CCUtility.getShowHiddenFiles(), queue: NCCommunicationCommon.shared.backgroundQueue) { account, files, _, errorCode, errorDescription in
+ guard errorCode == 0 else {
+ completion(account, nil, nil, nil, nil, nil, errorCode, errorDescription)
+ return
+ }
- if errorCode == 0 {
-
- NCManageDatabase.shared.convertNCCommunicationFilesToMetadatas(files, useMetadataFolder: true, account: account) { metadataFolder, metadatasFolder, metadatas in
-
- // Add metadata folder
- NCManageDatabase.shared.addMetadata(tableMetadata.init(value: metadataFolder))
-
- // Update directory
- NCManageDatabase.shared.addDirectory(encrypted: metadataFolder.e2eEncrypted, favorite: metadataFolder.favorite, ocId: metadataFolder.ocId, fileId: metadataFolder.fileId, etag: metadataFolder.etag, permissions: metadataFolder.permissions, serverUrl: serverUrl, account: metadataFolder.account)
- NCManageDatabase.shared.setDirectory(richWorkspace: metadataFolder.richWorkspace, serverUrl: serverUrl, account: metadataFolder.account)
+ NCManageDatabase.shared.convertNCCommunicationFilesToMetadatas(files, useMetadataFolder: true, account: account) { metadataFolder, metadatasFolder, metadatas in
- // Update sub directories NO Update richWorkspace
- for metadata in metadatasFolder {
- let serverUrl = metadata.serverUrl + "/" + metadata.fileName
- NCManageDatabase.shared.addDirectory(encrypted: metadata.e2eEncrypted, favorite: metadata.favorite, ocId: metadata.ocId, fileId: metadata.fileId, etag: nil, permissions: metadata.permissions, serverUrl: serverUrl, account: account)
- }
+ // Add metadata folder
+ NCManageDatabase.shared.addMetadata(tableMetadata.init(value: metadataFolder))
- let metadatasResult = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND status == %d", account, serverUrl, NCGlobal.shared.metadataStatusNormal))
- let metadatasChanged = NCManageDatabase.shared.updateMetadatas(metadatas, metadatasResult: metadatasResult, addCompareEtagLocal: true)
+ // Update directory
+ NCManageDatabase.shared.addDirectory(encrypted: metadataFolder.e2eEncrypted, favorite: metadataFolder.favorite, ocId: metadataFolder.ocId, fileId: metadataFolder.fileId, etag: metadataFolder.etag, permissions: metadataFolder.permissions, serverUrl: serverUrl, account: metadataFolder.account)
+ NCManageDatabase.shared.setDirectory(serverUrl: serverUrl, richWorkspace: metadataFolder.richWorkspace, account: metadataFolder.account)
- completion(account, metadataFolder, metadatas, metadatasChanged.metadatasUpdate, metadatasChanged.metadatasLocalUpdate, metadatasChanged.metadatasDelete, errorCode, "")
+ // Update sub directories NO Update richWorkspace
+ for metadata in metadatasFolder {
+ let serverUrl = metadata.serverUrl + "/" + metadata.fileName
+ NCManageDatabase.shared.addDirectory(encrypted: metadata.e2eEncrypted, favorite: metadata.favorite, ocId: metadata.ocId, fileId: metadata.fileId, etag: nil, permissions: metadata.permissions, serverUrl: serverUrl, account: account)
}
- } else {
+ let metadatasResult = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND status == %d", account, serverUrl, NCGlobal.shared.metadataStatusNormal))
+ let metadatasChanged = NCManageDatabase.shared.updateMetadatas(metadatas, metadatasResult: metadatasResult, addCompareEtagLocal: true)
- completion(account, nil, nil, nil, nil, nil, errorCode, errorDescription)
+ completion(account, metadataFolder, metadatas, metadatasChanged.metadatasUpdate, metadatasChanged.metadatasLocalUpdate, metadatasChanged.metadatasDelete, errorCode, "")
}
}
}
- @objc func readFile(serverUrlFileName: String, account: String, queue: DispatchQueue = NCCommunicationCommon.shared.backgroundQueue, completion: @escaping (_ account: String, _ metadata: tableMetadata?, _ errorCode: Int, _ errorDescription: String) -> Void) {
+ @objc func readFile(serverUrlFileName: String, showHiddenFiles: Bool = CCUtility.getShowHiddenFiles(), queue: DispatchQueue = NCCommunicationCommon.shared.backgroundQueue, completion: @escaping (_ account: String, _ metadata: tableMetadata?, _ errorCode: Int, _ errorDescription: String) -> Void) {
+
+ NCCommunication.shared.readFileOrFolder(serverUrlFileName: serverUrlFileName, depth: "0", showHiddenFiles: showHiddenFiles, queue: queue) { account, files, _, errorCode, errorDescription in
+ guard errorCode == 0, files.count == 1, let file = files.first else {
+ completion(account, nil, errorCode, errorDescription)
+ return
+ }
- NCCommunication.shared.readFileOrFolder(serverUrlFileName: serverUrlFileName, depth: "0", showHiddenFiles: CCUtility.getShowHiddenFiles(), queue: queue) { account, files, _, errorCode, errorDescription in
+ let isEncrypted = CCUtility.isFolderEncrypted(file.serverUrl, e2eEncrypted: file.e2eEncrypted, account: account, urlBase: file.urlBase)
+ let metadata = NCManageDatabase.shared.convertNCFileToMetadata(file, isEncrypted: isEncrypted, account: account)
- if errorCode == 0 && files.count == 1 {
+ completion(account, metadata, errorCode, errorDescription)
+ }
+ }
+
+ //MARK: - Search
+
+ /// WebDAV search
+ @objc func searchFiles(urlBase: NCUserBaseUrl, literal: String, completion: @escaping (_ metadatas: [tableMetadata]?, _ errorCode: Int, _ errorDescription: String) -> ()) {
- let file = files[0]
- let isEncrypted = CCUtility.isFolderEncrypted(file.serverUrl, e2eEncrypted: file.e2eEncrypted, account: account, urlBase: file.urlBase)
- let metadata = NCManageDatabase.shared.convertNCFileToMetadata(file, isEncrypted: isEncrypted, account: account)
+ NCCommunication.shared.searchLiteral(serverUrl: urlBase.urlBase, depth: "infinity", literal: literal, showHiddenFiles: CCUtility.getShowHiddenFiles(), queue: NCCommunicationCommon.shared.backgroundQueue) { (account, files, errorCode, errorDescription) in
+ guard errorCode == 0 else {
+ return completion(nil, errorCode, errorDescription)
+ }
- completion(account, metadata, errorCode, errorDescription)
+ NCManageDatabase.shared.convertNCCommunicationFilesToMetadatas(files, useMetadataFolder: false, account: account) { _, metadatasFolder, metadatas in
- } else {
+ // Update sub directories
+ for folder in metadatasFolder {
+ let serverUrl = folder.serverUrl + "/" + folder.fileName
+ NCManageDatabase.shared.addDirectory(encrypted: folder.e2eEncrypted, favorite: folder.favorite, ocId: folder.ocId, fileId: folder.fileId, etag: nil, permissions: folder.permissions, serverUrl: serverUrl, account: account)
+ }
- completion(account, nil, errorCode, errorDescription)
+ NCManageDatabase.shared.addMetadatas(metadatas)
+ let metadatas = Array(metadatas.map(tableMetadata.init))
+ completion(metadatas, errorCode, errorDescription)
}
}
}
- // MARK: - WebDav Search
+ /// Unified Search (NC>=20)
+ ///
+ func unifiedSearchFiles(urlBase: NCUserBaseUrl, literal: String, providers: @escaping ([NCCSearchProvider]?) -> Void, update: @escaping (_ id: String, NCCSearchResult?, [tableMetadata]?) -> Void, completion: @escaping (_ errorCode: Int, _ errorDescription: String) -> ()) {
- @objc func searchFiles(urlBase: String, user: String, literal: String, completion: @escaping (_ account: String, _ metadatas: [tableMetadata]?, _ errorCode: Int, _ errorDescription: String) -> Void) {
-
- NCCommunication.shared.searchLiteral(serverUrl: urlBase, depth: "infinity", literal: literal, showHiddenFiles: CCUtility.getShowHiddenFiles(), queue: NCCommunicationCommon.shared.backgroundQueue) { account, files, errorCode, errorDescription in
+ var errorCode = 0
+ var errorDescription = ""
+ let dispatchGroup = DispatchGroup()
+ dispatchGroup.enter()
+ dispatchGroup.notify(queue: .main) {
+ completion(errorCode, errorDescription)
+ }
- if errorCode == 0 {
+ NCCommunication.shared.unifiedSearch(term: literal, timeout: 30, timeoutProvider: 90) { provider in
+ // example filter
+ // ["calendar", "files", "fulltextsearch"].contains(provider.id)
+ return true
+ } request: { request in
+ if let request = request {
+ self.requestsUnifiedSearch.append(request)
+ }
+ } providers: { allProviders in
+ providers(allProviders)
+ } update: { partialResult, provider, errorCode, errorDescription in
+ guard let partialResult = partialResult else { return }
+ var metadatas: [tableMetadata] = []
+
+ switch provider.id {
+ case "files":
+ partialResult.entries.forEach({ entry in
+ if let fileId = entry.fileId,
+ let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ && fileId == %@", urlBase.userAccount, String(fileId))) {
+ metadatas.append(metadata)
+ } else if let filePath = entry.filePath {
+ let semaphore = Semaphore()
+ self.loadMetadata(urlBase: urlBase, filePath: filePath, dispatchGroup: dispatchGroup) { account, metadata, errorCode, errorDescription in
+ metadatas.append(metadata)
+ semaphore.continue()
+ }
+ semaphore.wait()
+ } else { print(#function, "[ERROR]: File search entry has no path: \(entry)") }
+ })
+ break
+ case "fulltextsearch":
+ // NOTE: FTS could also return attributes like files
+ // https://github.com/nextcloud/files_fulltextsearch/issues/143
+ partialResult.entries.forEach({ entry in
+ let url = URLComponents(string: entry.resourceURL)
+ guard let dir = url?.queryItems?["dir"]?.value, let filename = url?.queryItems?["scrollto"]?.value else { return }
+ if let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(
+ format: "account == %@ && path == %@ && fileName == %@",
+ urlBase.userAccount,
+ "/remote.php/dav/files/" + urlBase.user + dir,
+ filename)) {
+ metadatas.append(metadata)
+ } else {
+ let semaphore = Semaphore()
+ self.loadMetadata(urlBase: urlBase, filePath: dir + filename, dispatchGroup: dispatchGroup) { account, metadata, errorCode, errorDescription in
+ metadatas.append(metadata)
+ semaphore.continue()
+ }
+ semaphore.wait()
+ }
+ })
+ default:
+ partialResult.entries.forEach({ entry in
+ let metadata = NCManageDatabase.shared.createMetadata(account: urlBase.account, user: urlBase.user, userId: urlBase.userId, fileName: entry.title, fileNameView: entry.title, ocId: NSUUID().uuidString, serverUrl: urlBase.urlBase, urlBase: urlBase.urlBase, url: entry.resourceURL, contentType: "", isUrl: true, name: partialResult.name.lowercased(), subline: entry.subline, iconName: entry.icon, iconUrl: entry.thumbnailURL)
+ metadatas.append(metadata)
+ })
+ }
+ update(provider.id, partialResult, metadatas)
+ } completion: { err, description in
+ self.requestsUnifiedSearch.removeAll()
+ errorCode = err
+ errorDescription = description
+ dispatchGroup.leave()
+ }
+ }
- NCManageDatabase.shared.convertNCCommunicationFilesToMetadatas(files, useMetadataFolder: false, account: account) { _, metadatasFolder, metadatas in
+ func unifiedSearchFilesProvider(urlBase: NCUserBaseUrl, id: String, term: String, limit: Int, cursor: Int, completion: @escaping (NCCSearchResult?, _ metadatas: [tableMetadata]?, _ errorCode: Int, _ errorDescription: String) -> ()) {
- // Update sub directories
- for metadata in metadatasFolder {
- let serverUrl = metadata.serverUrl + "/" + metadata.fileName
- NCManageDatabase.shared.addDirectory(encrypted: metadata.e2eEncrypted, favorite: metadata.favorite, ocId: metadata.ocId, fileId: metadata.fileId, etag: nil, permissions: metadata.permissions, serverUrl: serverUrl, account: account)
- }
+ var metadatas: [tableMetadata] = []
- NCManageDatabase.shared.addMetadatas(metadatas)
+ let request = NCCommunication.shared.searchProvider(id, term: term, limit: limit, cursor: cursor, timeout: 60) { searchResult, errorCode, errorDescription in
+ guard let searchResult = searchResult else {
+ completion(nil, metadatas, errorCode, errorDescription)
+ return
+ }
- let metadatas = Array(metadatas.map { tableMetadata.init(value: $0) })
+ switch id {
+ case "files":
+ searchResult.entries.forEach({ entry in
+ if let fileId = entry.fileId, let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ && fileId == %@", urlBase.userAccount, String(fileId))) {
+ metadatas.append(metadata)
+ } else if let filePath = entry.filePath {
+ let semaphore = Semaphore()
+ self.loadMetadata(urlBase: urlBase, filePath: filePath, dispatchGroup: nil) { account, metadata, errorCode, errorDescription in
+ metadatas.append(metadata)
+ semaphore.continue()
+ }
+ semaphore.wait()
+ } else { print(#function, "[ERROR]: File search entry has no path: \(entry)") }
+ })
+ break
+ case "fulltextsearch":
+ // NOTE: FTS could also return attributes like files
+ // https://github.com/nextcloud/files_fulltextsearch/issues/143
+ searchResult.entries.forEach({ entry in
+ let url = URLComponents(string: entry.resourceURL)
+ guard let dir = url?.queryItems?["dir"]?.value, let filename = url?.queryItems?["scrollto"]?.value else { return }
+ if let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ && path == %@ && fileName == %@", urlBase.userAccount, "/remote.php/dav/files/" + urlBase.user + dir, filename)) {
+ metadatas.append(metadata)
+ } else {
+ let semaphore = Semaphore()
+ self.loadMetadata(urlBase: urlBase, filePath: dir + filename, dispatchGroup: nil) { account, metadata, errorCode, errorDescription in
+ metadatas.append(metadata)
+ semaphore.continue()
+ }
+ semaphore.wait()
+ }
+ })
+ default:
+ searchResult.entries.forEach({ entry in
+ let newMetadata = NCManageDatabase.shared.createMetadata(account: urlBase.account, user: urlBase.user, userId: urlBase.userId, fileName: entry.title, fileNameView: entry.title, ocId: NSUUID().uuidString, serverUrl: urlBase.urlBase, urlBase: urlBase.urlBase, url: entry.resourceURL, contentType: "", isUrl: true, name: searchResult.name.lowercased(), subline: entry.subline, iconName: entry.icon, iconUrl: entry.thumbnailURL)
+ metadatas.append(newMetadata)
+ })
+ }
- completion(account, metadatas, errorCode, errorDescription)
- }
+ completion(searchResult, metadatas, errorCode, errorDescription)
+ }
+ if let request = request {
+ requestsUnifiedSearch.append(request)
+ }
+ }
- } else {
+ func cancelUnifiedSearchFiles() {
+ for request in requestsUnifiedSearch {
+ request.cancel()
+ }
+ requestsUnifiedSearch.removeAll()
+ }
- completion(account, nil, errorCode, errorDescription)
- }
+ private func loadMetadata(urlBase: NCUserBaseUrl, filePath: String, dispatchGroup: DispatchGroup? = nil, completion: @escaping (String, tableMetadata, Int, String) -> Void) {
+ let urlPath = urlBase.urlBase + "/remote.php/dav/files/" + urlBase.user + filePath
+ dispatchGroup?.enter()
+ self.readFile(serverUrlFileName: urlPath) { account, metadata, errorCode, errorDescription in
+ defer { dispatchGroup?.leave() }
+ guard let metadata = metadata else { return }
+ let returnMetadata = tableMetadata.init(value: metadata)
+ NCManageDatabase.shared.addMetadata(metadata)
+ completion(account, returnMetadata, errorCode, errorDescription)
}
}
@@ -934,7 +957,6 @@ import Queuer
@objc func createFolder(fileName: String, serverUrl: String, account: String, urlBase: String, overwrite: Bool = false, completion: @escaping (_ errorCode: Int, _ errorDescription: String) -> Void) {
let isDirectoryEncrypted = CCUtility.isFolderEncrypted(serverUrl, e2eEncrypted: false, account: account, urlBase: urlBase)
-
let fileName = fileName.trimmingCharacters(in: .whitespacesAndNewlines)
if isDirectoryEncrypted {
@@ -959,33 +981,26 @@ import Queuer
let fileNameFolderUrl = serverUrl + "/" + fileNameFolder
NCCommunication.shared.createFolder(fileNameFolderUrl) { account, ocId, _, errorCode, errorDescription in
-
- if errorCode == 0 {
-
- self.readFile(serverUrlFileName: fileNameFolderUrl, account: account) { account, metadataFolder, errorCode, errorDescription in
-
- if errorCode == 0 {
-
- if let metadata = metadataFolder {
-
- NCManageDatabase.shared.addMetadata(metadata)
- NCManageDatabase.shared.addDirectory(encrypted: metadata.e2eEncrypted, favorite: metadata.favorite, ocId: metadata.ocId, fileId: metadata.fileId, etag: nil, permissions: metadata.permissions, serverUrl: fileNameFolderUrl, account: account)
- }
-
- if let metadata = NCManageDatabase.shared.getMetadataFromOcId(metadataFolder?.ocId) {
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterCreateFolder, userInfo: ["ocId": metadata.ocId])
- }
- }
-
+ guard errorCode == 0 else {
+ if errorCode == 405 && overwrite {
+ completion(0, "")
+ } else {
completion(errorCode, errorDescription)
}
+ return
+ }
- } else if errorCode == 405 && overwrite {
-
- completion(0, "")
-
- } else {
+ self.readFile(serverUrlFileName: fileNameFolderUrl) { (account, metadataFolder, errorCode, errorDescription) in
+ if errorCode == 0 {
+ if let metadata = metadataFolder {
+ NCManageDatabase.shared.addMetadata(metadata)
+ NCManageDatabase.shared.addDirectory(encrypted: metadata.e2eEncrypted, favorite: metadata.favorite, ocId: metadata.ocId, fileId: metadata.fileId, etag: nil, permissions: metadata.permissions, serverUrl: fileNameFolderUrl, account: account)
+ }
+ if let metadata = NCManageDatabase.shared.getMetadataFromOcId(metadataFolder?.ocId) {
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterCreateFolder, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account])
+ }
+ }
completion(errorCode, errorDescription)
}
}
@@ -1048,7 +1063,7 @@ import Queuer
NCUtilityFileSystem.shared.deleteFile(filePath: CCUtility.getDirectoryProviderStorageOcId(metadataLivePhoto.ocId))
}
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDeleteFile, userInfo: ["ocId": metadata.ocId, "fileNameView": metadata.fileNameView, "classFile": metadata.classFile, "onlyLocalCache": true])
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDeleteFile, userInfo: ["ocId": metadata.ocId, "fileNameView": metadata.fileNameView, "serverUrl": metadata.serverUrl, "account": metadata.account, "classFile": metadata.classFile, "onlyLocalCache": true])
}
return completion(0, "")
}
@@ -1110,7 +1125,7 @@ import Queuer
NCManageDatabase.shared.deleteDirectoryAndSubDirectory(serverUrl: CCUtility.stringAppendServerUrl(metadata.serverUrl, addFileName: metadata.fileName), account: metadata.account)
}
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDeleteFile, userInfo: ["ocId": metadata.ocId, "fileNameView": metadata.fileNameView, "classFile": metadata.classFile, "onlyLocalCache": true])
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDeleteFile, userInfo: ["ocId": metadata.ocId, "fileNameView": metadata.fileNameView, "serverUrl": metadata.serverUrl, "account": metadata.account, "classFile": metadata.classFile, "onlyLocalCache": false])
}
completion(errorCode, errorDescription)
@@ -1141,43 +1156,36 @@ import Queuer
let ocId = metadata.ocId
NCCommunication.shared.setFavorite(fileName: fileName, favorite: favorite) { account, errorCode, errorDescription in
-
if errorCode == 0 && metadata.account == account {
-
NCManageDatabase.shared.setMetadataFavorite(ocId: metadata.ocId, favorite: favorite)
-
#if !EXTENSION
if favorite {
NCOperationQueue.shared.synchronizationMetadata(metadata, selector: NCGlobal.shared.selectorReadFile)
}
#endif
-
- if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterFavoriteFile, userInfo: ["ocId": metadata.ocId])
- }
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterFavoriteFile, userInfo: ["ocId": ocId, "serverUrl": metadata.serverUrl])
}
-
completion(errorCode, errorDescription)
}
}
@objc func listingFavoritescompletion(selector: String, completion: @escaping (_ account: String, _ metadatas: [tableMetadata]?, _ errorCode: Int, _ errorDescription: String) -> Void) {
NCCommunication.shared.listingFavorites(showHiddenFiles: CCUtility.getShowHiddenFiles(), queue: NCCommunicationCommon.shared.backgroundQueue) { account, files, errorCode, errorDescription in
+ guard errorCode == 0 else {
+ completion(account, nil, errorCode, errorDescription)
+ return
+ }
- if errorCode == 0 {
- NCManageDatabase.shared.convertNCCommunicationFilesToMetadatas(files, useMetadataFolder: false, account: account) { _, _, metadatas in
- NCManageDatabase.shared.updateMetadatasFavorite(account: account, metadatas: metadatas)
- if selector != NCGlobal.shared.selectorListingFavorite {
- #if !EXTENSION
- for metadata in metadatas {
- NCOperationQueue.shared.synchronizationMetadata(metadata, selector: selector)
- }
- #endif
+ NCManageDatabase.shared.convertNCCommunicationFilesToMetadatas(files, useMetadataFolder: false, account: account) { _, _, metadatas in
+ NCManageDatabase.shared.updateMetadatasFavorite(account: account, metadatas: metadatas)
+ if selector != NCGlobal.shared.selectorListingFavorite {
+ #if !EXTENSION
+ for metadata in metadatas {
+ NCOperationQueue.shared.synchronizationMetadata(metadata, selector: selector)
}
- completion(account, metadatas, errorCode, errorDescription)
+ #endif
}
- } else {
- completion(account, nil, errorCode, errorDescription)
+ completion(account, metadatas, errorCode, errorDescription)
}
}
}
@@ -1191,7 +1199,7 @@ import Queuer
NCContentPresenter.shared.messageNotification(metadata.fileName, description: "_files_lock_error_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode, priority: .max)
return
}
- NCNetworking.shared.readFile(serverUrlFileName: metadata.serverUrl + "/" + metadata.fileName, account: metadata.account) { account, metadata, errorCode, errorDescription in
+ NCNetworking.shared.readFile(serverUrlFileName: metadata.serverUrl + "/" + metadata.fileName) { account, metadata, errorCode, errorDescription in
guard errorCode == 0, let metadata = metadata else { return }
NCManageDatabase.shared.addMetadata(metadata)
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource)
@@ -1294,7 +1302,7 @@ import Queuer
}
if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterRenameFile, userInfo: ["ocId": metadata.ocId])
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterRenameFile, userInfo: ["ocId": metadata.ocId, "account": metadata.account])
}
}
@@ -1333,14 +1341,11 @@ import Queuer
NCCommunication.shared.moveFileOrFolder(serverUrlFileNameSource: serverUrlFileNameSource, serverUrlFileNameDestination: serverUrlFileNameDestination, overwrite: overwrite) { account, errorCode, errorDescription in
if errorCode == 0 {
-
if metadata.directory {
NCManageDatabase.shared.deleteDirectoryAndSubDirectory(serverUrl: CCUtility.stringAppendServerUrl(metadata.serverUrl, addFileName: metadata.fileName), account: account)
}
-
NCManageDatabase.shared.moveMetadata(ocId: metadata.ocId, serverUrlTo: serverUrlTo)
-
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterMoveFile, userInfo: ["ocId": metadata.ocId, "serverUrlFrom": serverUrlFrom])
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterMoveFile, userInfo: ["ocId": metadata.ocId, "account": metadata.account, "serverUrlFrom": serverUrlFrom])
}
completion(errorCode, errorDescription)
@@ -1377,10 +1382,8 @@ import Queuer
NCCommunication.shared.copyFileOrFolder(serverUrlFileNameSource: serverUrlFileNameSource, serverUrlFileNameDestination: serverUrlFileNameDestination, overwrite: overwrite) { _, errorCode, errorDescription in
if errorCode == 0 {
-
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterCopyFile, userInfo: ["ocId": metadata.ocId, "serverUrlTo": serverUrlTo])
}
-
completion(errorCode, errorDescription)
}
}
@@ -1390,13 +1393,9 @@ import Queuer
func getVideoUrl(metadata: tableMetadata, completition: @escaping (_ url: URL?) -> Void) {
if CCUtility.fileProviderStorageExists(metadata) {
-
completition(URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)))
-
} else {
-
NCCommunication.shared.getDirectDownload(fileId: metadata.fileId) { _, url, errorCode, _ in
-
if errorCode == 0 && url != nil {
if let url = URL(string: url!) {
completition(url)
@@ -1448,3 +1447,9 @@ import Queuer
}
*/
}
+
+extension Array where Element == URLQueryItem {
+ subscript(name: String) -> URLQueryItem? {
+ first(where: { $0.name == name })
+ }
+}
diff --git a/iOSClient/Networking/NCNetworkingCheckRemoteUser.swift b/iOSClient/Networking/NCNetworkingCheckRemoteUser.swift
index e68d2a72a..0acf5dd40 100644
--- a/iOSClient/Networking/NCNetworkingCheckRemoteUser.swift
+++ b/iOSClient/Networking/NCNetworkingCheckRemoteUser.swift
@@ -29,7 +29,6 @@ import NCCommunication
return instance
}()
- let appDelegate = UIApplication.shared.delegate as! AppDelegate
var checkRemoteUserInProgress = false
@objc func checkRemoteUser(account: String, errorCode: Int, errorDescription: String) {
@@ -58,18 +57,20 @@ import NCCommunication
NCCommunication.shared.getRemoteWipeStatus(serverUrl: tableAccount.urlBase, token: token) { account, wipe, errorCode, _ in
+ let appDelegate = UIApplication.shared.delegate as! AppDelegate
if wipe {
- self.appDelegate.deleteAccount(account, wipe: true)
+ appDelegate.deleteAccount(account, wipe: true)
NCContentPresenter.shared.messageNotification(tableAccount.user, description: "_wipe_account_", delay: NCGlobal.shared.dismissAfterSecondLong, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
NCCommunication.shared.setRemoteWipeCompletition(serverUrl: tableAccount.urlBase, token: token) { _, _, _ in print("wipe") }
} else {
- if UIApplication.shared.applicationState == .active && NCCommunication.shared.isNetworkReachable() {
+ if UIApplication.shared.applicationState == .active && NCCommunication.shared.isNetworkReachable() && !CCUtility.getPassword(account).isEmpty && !appDelegate.deletePasswordSession {
let description = String.localizedStringWithFormat(NSLocalizedString("_error_check_remote_user_", comment: ""), tableAccount.user, tableAccount.urlBase)
NCContentPresenter.shared.messageNotification("_error_", description: description, delay: NCGlobal.shared.dismissAfterSecondLong, type: NCContentPresenter.messageType.error, errorCode: errorCode, priority: .max)
CCUtility.setPassword(account, password: nil)
+ appDelegate.deletePasswordSession = true
}
}
diff --git a/iOSClient/Networking/NCNetworkingChunkedUpload.swift b/iOSClient/Networking/NCNetworkingChunkedUpload.swift
index 684484fe9..6335a8e5b 100644
--- a/iOSClient/Networking/NCNetworkingChunkedUpload.swift
+++ b/iOSClient/Networking/NCNetworkingChunkedUpload.swift
@@ -34,164 +34,176 @@ extension NCNetworking {
let chunkFolderPath = metadata.urlBase + "/" + NCUtilityFileSystem.shared.getWebDAV(account: metadata.account) + "/uploads/" + metadata.userId + "/" + chunkFolder
let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
let chunkSize = CCUtility.getChunkSize()
+ let fileSizeInGB = Double(metadata.size) / 1e9
+ let ocIdTemp = metadata.ocId
+ let selector = metadata.sessionSelector
var uploadErrorCode: Int = 0
var uploadErrorDescription: String = ""
+
var filesNames = NCManageDatabase.shared.getChunks(account: metadata.account, ocId: metadata.ocId)
if filesNames.count == 0 {
-
+ NCContentPresenter.shared.noteTop(text: NSLocalizedString("_upload_chunk_", comment: ""), image: nil, type: NCContentPresenter.messageType.info, delay: .infinity, priority: .max)
filesNames = NCCommunicationCommon.shared.chunkedFile(inputDirectory: directoryProviderStorageOcId, outputDirectory: directoryProviderStorageOcId, fileName: metadata.fileName, chunkSizeMB: chunkSize)
-
if filesNames.count > 0 {
NCManageDatabase.shared.addChunks(account: metadata.account, ocId: metadata.ocId, chunkFolder: chunkFolder, fileNames: filesNames)
} else {
+ NCContentPresenter.shared.dismiss()
NCContentPresenter.shared.messageNotification("_error_", description: "_err_file_not_found_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorReadFile)
NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
return completion(uploadErrorCode, uploadErrorDescription)
}
-
} else {
-
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": metadata.serverUrl])
}
- NCContentPresenter.shared.noteTop(text: NSLocalizedString("_upload_chunk_", comment: ""), image: nil, type: NCContentPresenter.messageType.info, delay: NCGlobal.shared.dismissAfterSecond, priority: .max)
-
createChunkedFolder(chunkFolderPath: chunkFolderPath, account: metadata.account) { errorCode, errorDescription in
+ NCContentPresenter.shared.dismiss(after: NCGlobal.shared.dismissAfterSecond)
start()
- if errorCode == 0 {
-
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadStartFile, userInfo: ["ocId": metadata.ocId])
-
- for fileName in filesNames {
-
- let serverUrlFileName = chunkFolderPath + "/" + fileName
- let fileNameChunkLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: fileName)!
-
- var size: Int64?
- if let tableChunk = NCManageDatabase.shared.getChunk(account: metadata.account, fileName: fileName) {
- size = tableChunk.size - NCUtilityFileSystem.shared.getFileSize(filePath: fileNameChunkLocalPath)
- }
-
- let semaphore = Semaphore()
+ guard errorCode == 0 else {
+ self.uploadChunkFileError(metadata: metadata, chunkFolderPath: chunkFolderPath, directoryProviderStorageOcId: directoryProviderStorageOcId, errorCode: errorCode, errorDescription: errorDescription)
+ completion(errorCode, errorDescription)
+ return
+ }
- NCCommunication.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameChunkLocalPath, requestHandler: { request in
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadStartFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "sessionSelector": metadata.sessionSelector])
- self.uploadRequest[fileNameLocalPath] = request
+ for fileName in filesNames {
- }, taskHandler: { task in
+ let serverUrlFileName = chunkFolderPath + "/" + fileName
+ let fileNameChunkLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: fileName)!
- NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, sessionError: "", sessionTaskIdentifier: task.taskIdentifier, status: NCGlobal.shared.metadataStatusUploading)
+ var size: Int64?
+ if let tableChunk = NCManageDatabase.shared.getChunk(account: metadata.account, fileName: fileName) {
+ size = tableChunk.size - NCUtilityFileSystem.shared.getFileSize(filePath: fileNameChunkLocalPath)
+ }
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadStartFile, userInfo: ["ocId": metadata.ocId])
+ let semaphore = Semaphore()
- NCCommunicationCommon.shared.writeLog("Upload chunk: " + fileName)
+ NCCommunication.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameChunkLocalPath, requestHandler: { request in
- }, progressHandler: { progress in
+ self.uploadRequest[fileNameLocalPath] = request
- if let size = size {
+ }, taskHandler: { task in
- let totalBytesExpected = size + progress.completedUnitCount
- let totalBytes = metadata.size
- let fractionCompleted = Float(totalBytesExpected) / Float(totalBytes)
+ NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, sessionError: "", sessionTaskIdentifier: task.taskIdentifier, status: NCGlobal.shared.metadataStatusUploading)
+ NCCommunicationCommon.shared.writeLog("Upload chunk: " + fileName)
- NotificationCenter.default.postOnMainThread(
- name: NCGlobal.shared.notificationCenterProgressTask,
- object: nil,
- userInfo: [
- "account": metadata.account,
- "ocId": metadata.ocId,
- "fileName": metadata.fileName,
- "serverUrl": metadata.serverUrl,
- "status": NSNumber(value: NCGlobal.shared.metadataStatusInUpload),
- "progress": NSNumber(value: fractionCompleted),
- "totalBytes": NSNumber(value: totalBytes),
- "totalBytesExpected": NSNumber(value: totalBytesExpected)])
- }
+ }, progressHandler: { progress in
- }) { _, _, _, _, _, _, _, errorCode, errorDescription in
+ if let size = size {
+ let totalBytesExpected = metadata.size
+ let totalBytes = size + progress.completedUnitCount
+ let fractionCompleted = Float(totalBytes) / Float(totalBytesExpected)
- self.uploadRequest[fileNameLocalPath] = nil
- uploadErrorCode = errorCode
- uploadErrorDescription = errorDescription
- semaphore.continue()
+ NotificationCenter.default.postOnMainThread(
+ name: NCGlobal.shared.notificationCenterProgressTask,
+ object: nil,
+ userInfo: [
+ "account": metadata.account,
+ "ocId": metadata.ocId,
+ "fileName": metadata.fileName,
+ "serverUrl": metadata.serverUrl,
+ "status": NSNumber(value: NCGlobal.shared.metadataStatusInUpload),
+ "progress": NSNumber(value: fractionCompleted),
+ "totalBytes": NSNumber(value: totalBytes),
+ "totalBytesExpected": NSNumber(value: totalBytesExpected)])
}
- semaphore.wait()
+ }) { _, _, _, _, _, _, _, errorCode, errorDescription in
- if uploadErrorCode == 0 {
- NCManageDatabase.shared.deleteChunk(account: metadata.account, ocId: metadata.ocId, fileName: fileName)
- } else {
- break
- }
+ self.uploadRequest.removeValue(forKey: fileNameLocalPath)
+ uploadErrorCode = errorCode
+ uploadErrorDescription = errorDescription
+ semaphore.continue()
}
- if uploadErrorCode == 0 {
+ semaphore.wait()
- // Assembling the chunks
- let serverUrlFileNameSource = chunkFolderPath + "/.file"
- let pathServerUrl = CCUtility.returnPathfromServerUrl(metadata.serverUrl, urlBase: metadata.urlBase, account: metadata.account)!
- let serverUrlFileNameDestination = metadata.urlBase + "/" + NCUtilityFileSystem.shared.getWebDAV(account: metadata.account) + "/files/" + metadata.userId + pathServerUrl + "/" + metadata.fileName
+ if uploadErrorCode == 0 {
+ NCManageDatabase.shared.deleteChunk(account: metadata.account, ocId: metadata.ocId, fileName: fileName)
+ } else {
+ break
+ }
+ }
- var addCustomHeaders: [String: String] = [:]
- let creationDate = "\(metadata.creationDate.timeIntervalSince1970)"
- let modificationDate = "\(metadata.date.timeIntervalSince1970)"
+ guard uploadErrorCode == 0 else {
+ self.uploadChunkFileError(metadata: metadata, chunkFolderPath: chunkFolderPath, directoryProviderStorageOcId: directoryProviderStorageOcId, errorCode: uploadErrorCode, errorDescription: uploadErrorDescription)
+ completion(errorCode, errorDescription)
+ return
+ }
- addCustomHeaders["X-OC-CTime"] = creationDate
- addCustomHeaders["X-OC-MTime"] = modificationDate
+ // Assembling the chunks
+ let serverUrlFileNameSource = chunkFolderPath + "/.file"
+ let pathServerUrl = CCUtility.returnPathfromServerUrl(metadata.serverUrl, urlBase: metadata.urlBase, account: metadata.account)!
+ let serverUrlFileNameDestination = metadata.urlBase + "/" + NCUtilityFileSystem.shared.getWebDAV(account: metadata.account) + "/files/" + metadata.userId + pathServerUrl + "/" + metadata.fileName
- NCCommunication.shared.moveFileOrFolder(serverUrlFileNameSource: serverUrlFileNameSource, serverUrlFileNameDestination: serverUrlFileNameDestination, overwrite: true, addCustomHeaders: addCustomHeaders) { _, errorCode, errorDescription in
+ var addCustomHeaders: [String: String] = [:]
+ let creationDate = "\(metadata.creationDate.timeIntervalSince1970)"
+ let modificationDate = "\(metadata.date.timeIntervalSince1970)"
- NCCommunicationCommon.shared.writeLog("Assembling chunk with error code: \(errorCode)")
+ addCustomHeaders["X-OC-CTime"] = creationDate
+ addCustomHeaders["X-OC-MTime"] = modificationDate
- if errorCode == 0 {
+ // Calculate Assemble Timeout
+ let ASSEMBLE_TIME_PER_GB: Double = 3 * 60 // 3 min
+ let ASSEMBLE_TIME_MIN: Double = 60 // 60 sec
+ let ASSEMBLE_TIME_MAX: Double = 30 * 60 // 30 min
+ let timeout = max(ASSEMBLE_TIME_MIN, min(ASSEMBLE_TIME_PER_GB * fileSizeInGB, ASSEMBLE_TIME_MAX))
- let serverUrl = metadata.serverUrl
- let assetLocalIdentifier = metadata.assetLocalIdentifier
+ NCCommunication.shared.moveFileOrFolder(serverUrlFileNameSource: serverUrlFileNameSource, serverUrlFileNameDestination: serverUrlFileNameDestination, overwrite: true, addCustomHeaders: addCustomHeaders, timeout: timeout, queue: DispatchQueue.global(qos: .background)) { _, errorCode, errorDescription in
- NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
- NCManageDatabase.shared.deleteChunks(account: metadata.account, ocId: metadata.ocId)
- NCUtilityFileSystem.shared.deleteFile(filePath: directoryProviderStorageOcId)
+ NCCommunicationCommon.shared.writeLog("Assembling chunk with error code: \(errorCode)")
- self.readFile(serverUrlFileName: serverUrlFileNameDestination, account: metadata.account) { _, metadata, _, _ in
+ guard uploadErrorCode == 0 else {
+ self.uploadChunkFileError(metadata: metadata, chunkFolderPath: chunkFolderPath, directoryProviderStorageOcId: directoryProviderStorageOcId, errorCode: errorCode, errorDescription: errorDescription)
+ completion(errorCode, errorDescription)
+ return
+ }
- if errorCode == 0, let metadata = metadata {
+ let serverUrl = metadata.serverUrl
+ let assetLocalIdentifier = metadata.assetLocalIdentifier
+ let isLivePhoto = metadata.livePhoto
+ let isE2eEncrypted = metadata.e2eEncrypted
+ let account = metadata.account
+ let fileName = metadata.fileName
- metadata.assetLocalIdentifier = assetLocalIdentifier
- // Delete Asset on Photos album
- if CCUtility.getRemovePhotoCameraRoll() && !metadata.assetLocalIdentifier.isEmpty {
- metadata.deleteAssetLocalIdentifier = true
- }
- NCManageDatabase.shared.addMetadata(metadata)
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": serverUrl])
+ NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp))
+ NCManageDatabase.shared.deleteChunks(account: metadata.account, ocId: ocIdTemp)
- } else {
+ self.readFile(serverUrlFileName: serverUrlFileNameDestination) { (_, metadata, _, _) in
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSourceNetworkForced, userInfo: ["serverUrl": serverUrl])
- }
+ if errorCode == 0, let metadata = metadata {
- completion(errorCode, errorDescription)
- }
+ metadata.assetLocalIdentifier = assetLocalIdentifier
+ metadata.e2eEncrypted = isE2eEncrypted
+ metadata.livePhoto = isLivePhoto
- } else {
+ // Delete Asset on Photos album
+ if CCUtility.getRemovePhotoCameraRoll() && !metadata.assetLocalIdentifier.isEmpty {
+ metadata.deleteAssetLocalIdentifier = true
+ }
+ NCManageDatabase.shared.addMetadata(metadata)
- self.uploadChunkFileError(metadata: metadata, chunkFolderPath: chunkFolderPath, directoryProviderStorageOcId: directoryProviderStorageOcId, errorCode: errorCode, errorDescription: errorDescription)
- completion(errorCode, errorDescription)
+ if selector == NCGlobal.shared.selectorUploadFileNODelete {
+ NCUtilityFileSystem.shared.moveFile(atPath: CCUtility.getDirectoryProviderStorageOcId(ocIdTemp, fileNameView: fileName), toPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: fileName))
+ NCManageDatabase.shared.addLocalFile(metadata: metadata)
}
- }
+ NCUtilityFileSystem.shared.deleteFile(filePath: directoryProviderStorageOcId)
- } else {
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": serverUrl])
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": serverUrl, "account": account, "fileName": fileName, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
- self.uploadChunkFileError(metadata: metadata, chunkFolderPath: chunkFolderPath, directoryProviderStorageOcId: directoryProviderStorageOcId, errorCode: uploadErrorCode, errorDescription: uploadErrorDescription)
- completion(errorCode, errorDescription)
- }
+ } else {
- } else {
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSourceNetworkForced, userInfo: ["serverUrl": serverUrl])
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": ocIdTemp, "serverUrl": serverUrl, "account": account, "fileName": fileName, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
+ }
- self.uploadChunkFileError(metadata: metadata, chunkFolderPath: chunkFolderPath, directoryProviderStorageOcId: directoryProviderStorageOcId, errorCode: errorCode, errorDescription: errorDescription)
- completion(errorCode, errorDescription)
+ completion(errorCode, errorDescription)
+ }
}
}
}
@@ -244,6 +256,6 @@ extension NCNetworking {
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: errorDescription, sessionTaskIdentifier: NCGlobal.shared.metadataStatusNormal, status: NCGlobal.shared.metadataStatusUploadError)
}
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "ocIdTemp": metadata.ocId, "errorCode": errorCode, "errorDescription": ""])
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": metadata.ocId, "errorCode": errorCode, "errorDescription": ""])
}
}
diff --git a/iOSClient/Networking/NCNetworkingE2EE.swift b/iOSClient/Networking/NCNetworkingE2EE.swift
index 0d738164c..a12085b44 100644
--- a/iOSClient/Networking/NCNetworkingE2EE.swift
+++ b/iOSClient/Networking/NCNetworkingE2EE.swift
@@ -177,7 +177,7 @@ import Alamofire
try FileManager.default.moveItem(atPath: atPath, toPath: toPath)
} catch { }
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterRenameFile, userInfo: ["ocId": metadata.ocId])
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterRenameFile, userInfo: ["ocId": metadata.ocId, "account": metadata.account])
}
// unlock
@@ -202,8 +202,7 @@ import Alamofire
// Verify max size
if metadata.size > NCGlobal.shared.e2eeMaxFileSize {
NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp))
-
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "ocIdTemp": ocIdTemp, "errorCode": NCGlobal.shared.errorInternalError, "errorDescription": "E2E Error file too big"])
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "errorCode": NCGlobal.shared.errorInternalError, "errorDescription": "E2E Error file too big"])
start()
return completion(NCGlobal.shared.errorInternalError, "E2E Error file too big")
}
@@ -221,9 +220,8 @@ import Alamofire
let serverUrlFileName = serverUrl + "/" + metadata.fileName
if NCEndToEndEncryption.sharedManager()?.encryptFileName(metadata.fileNameView, fileNameIdentifier: metadata.fileName, directory: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId), key: &key, initializationVector: &initializationVector, authenticationTag: &authenticationTag) == false {
-
NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp))
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "ocIdTemp": ocIdTemp, "errorCode": NCGlobal.shared.errorInternalError, "errorDescription": "_e2e_error_create_encrypted_"])
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "errorCode": NCGlobal.shared.errorInternalError, "errorDescription": "_e2e_error_create_encrypted_"])
start()
return completion(NCGlobal.shared.errorInternalError, "_e2e_error_create_encrypted_")
}
@@ -257,10 +255,8 @@ import Alamofire
return completion(NCGlobal.shared.errorInternalError, "_e2e_error_create_encrypted_")
}
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl])
-
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": metadata.serverUrl])
NCContentPresenter.shared.noteTop(text: NSLocalizedString("_upload_e2ee_", comment: ""), image: nil, type: NCContentPresenter.messageType.info, delay: NCGlobal.shared.dismissAfterSecond, priority: .max)
-
NCNetworkingE2EE.shared.sendE2EMetadata(account: metadata.account, serverUrl: serverUrl, fileNameRename: nil, fileNameNewRename: nil, deleteE2eEncryption: nil, urlBase: metadata.urlBase, upload: true) { e2eToken, errorCode, errorDescription in
start()
@@ -271,8 +267,7 @@ import Alamofire
NCNetworking.shared.uploadRequest[fileNameLocalPathRequest] = request
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: nil, sessionSelector: nil, sessionTaskIdentifier: nil, status: NCGlobal.shared.metadataStatusUploading)
-
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadStartFile, userInfo: ["ocId": metadata.ocId])
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadStartFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "sessionSelector": metadata.sessionSelector])
}, taskHandler: { _ in
@@ -292,17 +287,13 @@ import Alamofire
}) { account, ocId, etag, date, _, _, error, errorCode, errorDescription in
- NCNetworking.shared.uploadRequest[fileNameLocalPath] = nil
-
+ NCNetworking.shared.uploadRequest.removeValue(forKey: fileNameLocalPath)
if let metadata = NCManageDatabase.shared.getMetadataFromOcId(metadata.ocId) {
-
- let metadata = tableMetadata.init(value: metadata)
-
if error?.isExplicitlyCancelledError ?? false {
CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
completion(0, "")
} else if errorCode == 0 && ocId != nil {
@@ -322,9 +313,8 @@ import Alamofire
NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp))
NCManageDatabase.shared.addLocalFile(metadata: metadata)
- NCUtility.shared.createImageFrom(fileName: metadata.fileNameView, ocId: metadata.ocId, etag: metadata.etag, classFile: metadata.classFile)
-
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
+ NCUtility.shared.createImageFrom(fileNameView: metadata.fileNameView, ocId: metadata.ocId, etag: metadata.etag, classFile: metadata.classFile)
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
} else {
@@ -340,10 +330,9 @@ import Alamofire
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
}
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
}
}
-
NCNetworkingE2EE.shared.unlock(account: metadata.account, serverUrl: serverUrl) { _, _, _, _ in
completion(errorCode, errorDescription)
}
@@ -353,8 +342,7 @@ import Alamofire
if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocIdTemp) {
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
-
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": errorDescription])
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account, "fileName": metadata.fileName, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": errorDescription])
}
completion(errorCode, errorDescription)
}
diff --git a/iOSClient/Networking/NCNetworkingProcessUpload.swift b/iOSClient/Networking/NCNetworkingProcessUpload.swift
index b2f5eac52..6ed7bdc2d 100644
--- a/iOSClient/Networking/NCNetworkingProcessUpload.swift
+++ b/iOSClient/Networking/NCNetworkingProcessUpload.swift
@@ -24,6 +24,7 @@
import UIKit
import NCCommunication
import Photos
+import Queuer
class NCNetworkingProcessUpload: NSObject {
@@ -37,9 +38,9 @@ class NCNetworkingProcessUpload: NSObject {
startTimer()
}
- @objc func startProcess() {
+ private func startProcess() {
if timerProcess?.isValid ?? false {
- process()
+ DispatchQueue.main.async { self.process() }
}
}
@@ -53,38 +54,41 @@ class NCNetworkingProcessUpload: NSObject {
}
@objc private func process() {
+ guard !appDelegate.account.isEmpty else { return }
- if appDelegate.account == "" { return }
+ stopTimer()
+ let applicationState = UIApplication.shared.applicationState
var counterUpload: Int = 0
- let sessionSelectors = [NCGlobal.shared.selectorUploadFile, NCGlobal.shared.selectorUploadAutoUpload, NCGlobal.shared.selectorUploadAutoUploadAll]
-
+ let sessionSelectors = [NCGlobal.shared.selectorUploadFileNODelete, NCGlobal.shared.selectorUploadFile, NCGlobal.shared.selectorUploadAutoUpload, NCGlobal.shared.selectorUploadAutoUploadAll]
let metadatasUpload = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "status == %d OR status == %d", NCGlobal.shared.metadataStatusInUpload, NCGlobal.shared.metadataStatusUploading))
counterUpload = metadatasUpload.count
- stopTimer()
-
print("[LOG] PROCESS-UPLOAD \(counterUpload)")
- NCNetworking.shared.getOcIdInBackgroundSession { listOcId in
+ // Update Badge
+ let counterBadge = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "status == %d OR status == %d OR status == %d", NCGlobal.shared.metadataStatusWaitUpload, NCGlobal.shared.metadataStatusInUpload, NCGlobal.shared.metadataStatusUploading))
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUpdateBadgeNumber, userInfo: ["counter":counterBadge.count])
+
+ NCNetworking.shared.getOcIdInBackgroundSession(queue: DispatchQueue.global(qos: .background), completion: { listOcId in
for sessionSelector in sessionSelectors {
if counterUpload < self.maxConcurrentOperationUpload {
let limit = self.maxConcurrentOperationUpload - counterUpload
- var predicate = NSPredicate()
- if UIApplication.shared.applicationState == .background {
- predicate = NSPredicate(format: "sessionSelector == %@ AND status == %d AND (classFile != %@ || livePhoto == true)", sessionSelector, NCGlobal.shared.metadataStatusWaitUpload, NCCommunicationCommon.typeClassFile.video.rawValue)
- } else {
- predicate = NSPredicate(format: "sessionSelector == %@ AND status == %d", sessionSelector, NCGlobal.shared.metadataStatusWaitUpload)
- }
- let metadatas = NCManageDatabase.shared.getAdvancedMetadatas(predicate: predicate, page: 1, limit: limit, sorted: "date", ascending: true)
+ let metadatas = NCManageDatabase.shared.getAdvancedMetadatas(predicate: NSPredicate(format: "sessionSelector == %@ AND status == %d", sessionSelector, NCGlobal.shared.metadataStatusWaitUpload), page: 1, limit: limit, sorted: "date", ascending: true)
if metadatas.count > 0 {
NCCommunicationCommon.shared.writeLog("PROCESS-UPLOAD find \(metadatas.count) items")
}
for metadata in metadatas {
+ // Different account
+ if self.appDelegate.account != metadata.account {
+ NCCommunicationCommon.shared.writeLog("Process auto upload skipped file: \(metadata.serverUrl)/\(metadata.fileNameView) on account: \(metadata.account), because the actual account is \(self.appDelegate.account).")
+ continue
+ }
+
// Is already in upload background? skipped
if listOcId.contains(metadata.ocId) {
NCCommunicationCommon.shared.writeLog("Process auto upload skipped file: \(metadata.serverUrl)/\(metadata.fileNameView), because is already in session.")
@@ -99,56 +103,33 @@ class NCNetworkingProcessUpload: NSObject {
// Is already in upload E2EE / CHUNK ? exit [ ONLY ONE IN QUEUE ]
for metadata in metadatasUpload {
if metadata.chunk || metadata.e2eEncrypted {
- self.startTimer()
- return
+ counterUpload = self.maxConcurrentOperationUpload
+ continue
}
}
- // Chunk
- if metadata.chunk && UIApplication.shared.applicationState == .active {
- if let metadata = NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusInUpload) {
- NCNetworking.shared.upload(metadata: metadata) {
- // start
- } completion: { _, _ in
- DispatchQueue.main.async {
- self.startTimer()
- }
- }
- } else {
- self.startTimer()
+ let semaphore = Semaphore()
+ self.extractFiles(from: metadata) { metadatas in
+ if metadatas.isEmpty {
+ NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
}
- return
- }
-
- // E2EE
- if metadata.e2eEncrypted && UIApplication.shared.applicationState == .active {
- if let metadata = NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusInUpload) {
- NCNetworking.shared.upload(metadata: metadata) {
- // start
- } completion: { _, _ in
- DispatchQueue.main.async {
- self.startTimer()
- }
+ for metadata in metadatas {
+ if (metadata.e2eEncrypted || metadata.chunk) && applicationState != .active { continue }
+ let isWiFi = NCNetworking.shared.networkReachability == NCCommunicationCommon.typeReachability.reachableEthernetOrWiFi
+ if metadata.session == NCNetworking.shared.sessionIdentifierBackgroundWWan && !isWiFi { continue }
+ if let metadata = NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusInUpload) {
+ NCNetworking.shared.upload(metadata: metadata)
+ }
+ if metadata.e2eEncrypted || metadata.chunk {
+ counterUpload = self.maxConcurrentOperationUpload
+ } else {
+ counterUpload += 1
}
- } else {
- self.startTimer()
- }
- return
- }
-
- counterUpload += 1
- if let metadata = NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusInUpload) {
- NCNetworking.shared.upload(metadata: metadata) {
- // start
- } completion: { _, _ in
- // completion
}
+ semaphore.continue()
}
+ semaphore.wait()
}
-
- } else {
- self.startTimer()
- return
}
}
@@ -161,14 +142,16 @@ class NCNetworkingProcessUpload: NSObject {
}
// verify delete Asset Local Identifiers in auto upload (DELETE Photos album)
- if (counterUpload == 0 && !self.appDelegate.isPasscodePresented()) {
- self.deleteAssetLocalIdentifiers(account: self.appDelegate.account) {
+ DispatchQueue.main.async {
+ if (counterUpload == 0 && !self.appDelegate.isPasscodePresented()) {
+ self.deleteAssetLocalIdentifiers(account: self.appDelegate.account) {
+ self.startTimer()
+ }
+ } else {
self.startTimer()
}
- } else {
- self.startTimer()
}
- }
+ })
}
private func deleteAssetLocalIdentifiers(account: String, completition: @escaping () -> Void) {
@@ -201,23 +184,67 @@ class NCNetworkingProcessUpload: NSObject {
// MARK: -
+ func extractFiles(from metadata: tableMetadata, completition: @escaping (_ metadatas: [tableMetadata]) -> Void) {
+
+ let chunckSize = CCUtility.getChunkSize() * 1000000
+ var metadatas: [tableMetadata] = []
+ let metadataSource = tableMetadata.init(value: metadata)
+
+ guard !metadata.isExtractFile else { return completition([metadataSource]) }
+ guard !metadataSource.assetLocalIdentifier.isEmpty else {
+ let filePath = CCUtility.getDirectoryProviderStorageOcId(metadataSource.ocId, fileNameView: metadataSource.fileName)!
+ metadataSource.size = NCUtilityFileSystem.shared.getFileSize(filePath: filePath)
+ let results = NCCommunicationCommon.shared.getInternalType(fileName: metadataSource.fileNameView, mimeType: metadataSource.contentType, directory: false)
+ metadataSource.contentType = results.mimeType
+ metadataSource.iconName = results.iconName
+ metadataSource.classFile = results.classFile
+ if let date = NCUtilityFileSystem.shared.getFileCreationDate(filePath: filePath) { metadataSource.creationDate = date }
+ if let date = NCUtilityFileSystem.shared.getFileModificationDate(filePath: filePath) { metadataSource.date = date }
+ metadataSource.chunk = chunckSize != 0 && metadata.size > chunckSize
+ metadataSource.e2eEncrypted = CCUtility.isFolderEncrypted(metadata.serverUrl, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase)
+ metadataSource.isExtractFile = true
+ if let metadata = NCManageDatabase.shared.addMetadata(metadataSource) {
+ metadatas.append(metadata)
+ }
+ return completition(metadatas)
+ }
+
+ NCUtility.shared.extractImageVideoFromAssetLocalIdentifier(metadata: metadataSource, modifyMetadataForUpload: true) { metadata, fileNamePath, returnError in
+ if let metadata = metadata, let fileNamePath = fileNamePath, !returnError {
+ metadatas.append(metadata)
+ let toPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
+ NCUtilityFileSystem.shared.moveFile(atPath: fileNamePath, toPath: toPath)
+ } else {
+ return completition(metadatas)
+ }
+ let fetchAssets = PHAsset.fetchAssets(withLocalIdentifiers: [metadataSource.assetLocalIdentifier], options: nil)
+ if metadataSource.livePhoto, fetchAssets.count > 0 {
+ NCUtility.shared.createMetadataLivePhotoFromMetadata(metadataSource, asset: fetchAssets.firstObject) { metadata in
+ if let metadata = metadata, let metadata = NCManageDatabase.shared.addMetadata(metadata) {
+ metadatas.append(metadata)
+ }
+ completition(metadatas)
+ }
+ } else {
+ completition(metadatas)
+ }
+ }
+ }
+
+ // MARK: -
+
@objc func createProcessUploads(metadatas: [tableMetadata], verifyAlreadyExists: Bool = false) {
var metadatasForUpload: [tableMetadata] = []
-
for metadata in metadatas {
-
if verifyAlreadyExists {
if NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ && serverUrl == %@ && fileName == %@ && session != ''", metadata.account, metadata.serverUrl, metadata.fileName)) != nil {
continue
}
}
-
metadatasForUpload.append(metadata)
}
-
NCManageDatabase.shared.addMetadatas(metadatasForUpload)
-
startProcess()
}
@@ -287,5 +314,11 @@ class NCNetworkingProcessUpload: NSObject {
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: "", sessionSelector: nil, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusWaitUpload)
}
}
+
+ // download
+ let metadatasDownload = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "session == %@", NCCommunicationCommon.shared.sessionIdentifierDownload))
+ for metadata in metadatasDownload {
+ NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: "", sessionError: "", sessionSelector: "", sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusNormal)
+ }
}
}
diff --git a/iOSClient/Networking/NCOperationQueue.swift b/iOSClient/Networking/NCOperationQueue.swift
index 82be80822..a39e59365 100644
--- a/iOSClient/Networking/NCOperationQueue.swift
+++ b/iOSClient/Networking/NCOperationQueue.swift
@@ -32,11 +32,14 @@ import NCCommunication
}()
private var downloadQueue = Queuer(name: "downloadQueue", maxConcurrentOperationCount: 5, qualityOfService: .default)
- private let deleteQueue = Queuer(name: "deleteQueue", maxConcurrentOperationCount: 1, qualityOfService: .default)
+ private let deleteQueue = Queuer(name: "deleteQueue", maxConcurrentOperationCount: 10, qualityOfService: .default)
+ private let deleteQueueE2EE = Queuer(name: "deleteQueue", maxConcurrentOperationCount: 1, qualityOfService: .default)
private let copyMoveQueue = Queuer(name: "copyMoveQueue", maxConcurrentOperationCount: 1, qualityOfService: .default)
private let synchronizationQueue = Queuer(name: "synchronizationQueue", maxConcurrentOperationCount: 1, qualityOfService: .default)
private let downloadThumbnailQueue = Queuer(name: "downloadThumbnailQueue", maxConcurrentOperationCount: 10, qualityOfService: .default)
+ private let downloadThumbnailActivityQueue = Queuer(name: "downloadThumbnailActivityQueue", maxConcurrentOperationCount: 10, qualityOfService: .default)
private let downloadAvatarQueue = Queuer(name: "downloadAvatarQueue", maxConcurrentOperationCount: 10, qualityOfService: .default)
+ private let unifiedSearchQueue = Queuer(name: "unifiedSearchQueue", maxConcurrentOperationCount: 1, qualityOfService: .default)
private var timerReadFileForMediaQueue: Timer?
@@ -46,155 +49,184 @@ import NCCommunication
copyMoveCancelAll()
synchronizationCancelAll()
downloadThumbnailCancelAll()
+ downloadThumbnailActivityCancelAll()
downloadAvatarCancelAll()
+ unifiedSearchCancelAll()
}
- // Download file
+ // MARK: - Download file
func download(metadata: tableMetadata, selector: String) {
- for operation in downloadQueue.operations as! [NCOperationDownload] {
- if operation.metadata.ocId == metadata.ocId {
- return
- }
+ for case let operation as NCOperationDownload in downloadQueue.operations where operation.metadata.ocId == metadata.ocId {
+ return
}
downloadQueue.addOperation(NCOperationDownload(metadata: metadata, selector: selector))
}
- @objc func downloadCancelAll() {
+
+ func downloadCancelAll() {
downloadQueue.cancelAll()
}
- @objc func downloadCount() -> Int {
+
+ func downloadQueueCount() -> Int {
return downloadQueue.operationCount
}
- @objc func downloadExists(metadata: tableMetadata) -> Bool {
- for operation in downloadQueue.operations as! [NCOperationDownload] {
- if operation.metadata.ocId == metadata.ocId {
- return true
- }
+
+ func downloadExists(metadata: tableMetadata) -> Bool {
+ for case let operation as NCOperationDownload in downloadQueue.operations where operation.metadata.ocId == metadata.ocId {
+ return true
}
return false
}
- // Delete file
+ // MARK: - Delete file
- @objc func delete(metadata: tableMetadata, onlyLocalCache: Bool) {
- for operation in deleteQueue.operations as! [NCOperationDelete] {
- if operation.metadata.ocId == metadata.ocId {
+ func delete(metadata: tableMetadata, onlyLocalCache: Bool) {
+
+ let isFolderEncrypted = CCUtility.isFolderEncrypted(metadata.serverUrl, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase)
+ if isFolderEncrypted {
+ for case let operation as NCOperationDelete in deleteQueueE2EE.operations where operation.metadata.ocId == metadata.ocId {
+ return
+ }
+ deleteQueueE2EE.addOperation(NCOperationDelete(metadata: metadata, onlyLocalCache: onlyLocalCache))
+ } else {
+ for case let operation as NCOperationDelete in deleteQueue.operations where operation.metadata.ocId == metadata.ocId {
return
}
+ deleteQueue.addOperation(NCOperationDelete(metadata: metadata, onlyLocalCache: onlyLocalCache))
}
- deleteQueue.addOperation(NCOperationDelete(metadata: metadata, onlyLocalCache: onlyLocalCache))
}
- @objc func deleteCancelAll() {
+
+ func deleteCancelAll() {
deleteQueue.cancelAll()
}
- @objc func deleteCount() -> Int {
- return deleteQueue.operationCount
- }
- // Copy Move file
+ // MARK: - Copy Move file
- @objc func copyMove(metadata: tableMetadata, serverUrl: String, overwrite: Bool, move: Bool) {
- for operation in copyMoveQueue.operations as! [NCOperationCopyMove] {
- if operation.metadata.ocId == metadata.ocId {
- return
- }
+ func copyMove(metadata: tableMetadata, serverUrl: String, overwrite: Bool, move: Bool) {
+ for case let operation as NCOperationCopyMove in copyMoveQueue.operations where operation.metadata.ocId == metadata.ocId {
+ return
}
copyMoveQueue.addOperation(NCOperationCopyMove(metadata: metadata, serverUrlTo: serverUrl, overwrite: overwrite, move: move))
}
- @objc func copyMoveCancelAll() {
+
+ func copyMoveCancelAll() {
copyMoveQueue.cancelAll()
}
- @objc func copyMoveCount() -> Int {
- return copyMoveQueue.operationCount
- }
- // Synchronization
+ // MARK: - Synchronization
- @objc func synchronizationMetadata(_ metadata: tableMetadata, selector: String) {
- for operation in synchronizationQueue.operations as! [NCOperationSynchronization] {
- if operation.metadata.ocId == metadata.ocId {
- return
- }
+ func synchronizationMetadata(_ metadata: tableMetadata, selector: String) {
+ for case let operation as NCOperationSynchronization in synchronizationQueue.operations where operation.metadata.ocId == metadata.ocId {
+ return
}
synchronizationQueue.addOperation(NCOperationSynchronization(metadata: metadata, selector: selector))
}
- @objc func synchronizationCancelAll() {
+
+ func synchronizationCancelAll() {
synchronizationQueue.cancelAll()
}
- // Download Thumbnail
+ // MARK: - Download Thumbnail
- @objc func downloadThumbnail(metadata: tableMetadata, placeholder: Bool, cell: UIView?, view: UIView?) {
+ func downloadThumbnail(metadata: tableMetadata, placeholder: Bool, cell: UIView?, view: UIView?) {
let cell: NCCellProtocol? = cell as? NCCellProtocol
if placeholder {
- if metadata.iconName.count > 0 {
- cell?.filePreviewImageView?.image = UIImage(named: metadata.iconName)
- } else {
+ if metadata.iconName.isEmpty {
cell?.filePreviewImageView?.image = NCBrandColor.cacheImages.file
+ } else {
+ cell?.filePreviewImageView?.image = UIImage(named: metadata.iconName)
}
}
if metadata.hasPreview && metadata.status == NCGlobal.shared.metadataStatusNormal && (!CCUtility.fileProviderStoragePreviewIconExists(metadata.ocId, etag: metadata.etag)) {
- for operation in downloadThumbnailQueue.operations as! [NCOperationDownloadThumbnail] {
- if operation.metadata.ocId == metadata.ocId {
- return
- }
+ for case let operation as NCOperationDownloadThumbnail in downloadThumbnailQueue.operations where operation.metadata.ocId == metadata.ocId {
+ return
}
downloadThumbnailQueue.addOperation(NCOperationDownloadThumbnail(metadata: metadata, cell: cell, view: view))
}
}
func cancelDownloadThumbnail(metadata: tableMetadata) {
- for operation in downloadThumbnailQueue.operations as! [NCOperationDownloadThumbnail] {
- if operation.metadata.ocId == metadata.ocId {
- operation.cancel()
- }
+ for case let operation as NCOperationDownloadThumbnail in downloadThumbnailQueue.operations where operation.metadata.ocId == metadata.ocId {
+ operation.cancel()
}
}
- @objc func downloadThumbnailCancelAll() {
+ func downloadThumbnailCancelAll() {
downloadThumbnailQueue.cancelAll()
}
- // Download Avatar
+ // MARK: - Download Thumbnail Activity
+
+ func downloadThumbnailActivity(fileNamePathOrFileId: String, fileNamePreviewLocalPath: String, fileId: String, cell: NCActivityCollectionViewCell, collectionView: UICollectionView?) {
+
+ cell.imageView?.image = UIImage(named: "file_photo")
+ cell.fileId = fileId
+
+ if !FileManager.default.fileExists(atPath: fileNamePreviewLocalPath) {
+ for case let operation as NCOperationDownloadThumbnailActivity in downloadThumbnailActivityQueue.operations where operation.fileId == fileId {
+ return
+ }
+ downloadThumbnailActivityQueue.addOperation(NCOperationDownloadThumbnailActivity(fileNamePathOrFileId: fileNamePathOrFileId, fileNamePreviewLocalPath: fileNamePreviewLocalPath, fileId: fileId, cell: cell, collectionView: collectionView))
+ }
+ }
+
+ func cancelDownloadThumbnailActivity(fileId: String) {
+ for case let operation as NCOperationDownloadThumbnailActivity in downloadThumbnailActivityQueue.operations where operation.fileId == fileId {
+ operation.cancel()
+ }
+ }
+
+ func downloadThumbnailActivityCancelAll() {
+ downloadThumbnailActivityQueue.cancelAll()
+ }
+
+ // MARK: - Download Avatar
- func downloadAvatar(user: String, dispalyName: String?, fileName: String, cell: NCCellProtocol, view: UIView?) {
+ func downloadAvatar(user: String, dispalyName: String?, fileName: String, cell: NCCellProtocol, view: UIView?, cellImageView: UIImageView?) {
let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName
if let image = NCManageDatabase.shared.getImageAvatarLoaded(fileName: fileName) {
+ cellImageView?.image = image
cell.fileAvatarImageView?.image = image
return
}
if let account = NCManageDatabase.shared.getActiveAccount() {
- cell.fileAvatarImageView?.image = NCUtility.shared.loadUserImage(
+ cellImageView?.image = NCUtility.shared.loadUserImage(
for: user,
displayName: dispalyName,
userBaseUrl: account)
}
- for operation in downloadAvatarQueue.operations as! [NCOperationDownloadAvatar] {
- if operation.fileName == fileName {
- return
- }
+ for case let operation as NCOperationDownloadAvatar in downloadAvatarQueue.operations where operation.fileName == fileName {
+ return
}
- downloadAvatarQueue.addOperation(NCOperationDownloadAvatar(user: user, fileName: fileName, fileNameLocalPath: fileNameLocalPath, cell: cell, view: view))
+ downloadAvatarQueue.addOperation(NCOperationDownloadAvatar(user: user, fileName: fileName, fileNameLocalPath: fileNameLocalPath, cell: cell, view: view, cellImageView: cellImageView))
}
func cancelDownloadAvatar(user: String) {
- for operation in downloadAvatarQueue.operations as! [NCOperationDownloadAvatar] {
- if operation.user == user {
- operation.cancel()
- }
+ for case let operation as NCOperationDownloadAvatar in downloadAvatarQueue.operations where operation.user == user {
+ operation.cancel()
}
}
- @objc func downloadAvatarCancelAll() {
+ func downloadAvatarCancelAll() {
downloadAvatarQueue.cancelAll()
}
+
+ // MARK: - Unified Search
+
+ func unifiedSearchAddSection(collectionViewCommon: NCCollectionViewCommon, metadatas: [tableMetadata], searchResult: NCCSearchResult) {
+ unifiedSearchQueue.addOperation(NCOperationUnifiedSearch.init(collectionViewCommon: collectionViewCommon, metadatas: metadatas, searchResult: searchResult))
+ }
+
+ func unifiedSearchCancelAll() {
+ unifiedSearchQueue.cancelAll()
+ }
}
// MARK: -
@@ -398,9 +430,9 @@ class NCOperationDownloadThumbnail: ConcurrentOperation {
var metadata: tableMetadata
var cell: NCCellProtocol?
var view: UIView?
- var fileNamePath: String = ""
- var fileNamePreviewLocalPath: String = ""
- var fileNameIconLocalPath: String = ""
+ var fileNamePath: String
+ var fileNamePreviewLocalPath: String
+ var fileNameIconLocalPath: String
init(metadata: tableMetadata, cell: NCCellProtocol?, view: UIView?) {
self.metadata = tableMetadata.init(value: metadata)
@@ -430,17 +462,15 @@ class NCOperationDownloadThumbnail: ConcurrentOperation {
etag: etagResource,
queue: NCCommunicationCommon.shared.backgroundQueue) { _, _, imageIcon, _, etag, errorCode, _ in
- if errorCode == 0 && imageIcon != nil {
+ if errorCode == 0, let imageIcon = imageIcon {
NCManageDatabase.shared.setMetadataEtagResource(ocId: self.metadata.ocId, etagResource: etag)
DispatchQueue.main.async {
- if self.metadata.ocId == self.cell?.fileObjectId {
- if let filePreviewImageView = self.cell?.filePreviewImageView {
- UIView.transition(with: filePreviewImageView,
- duration: 0.75,
- options: .transitionCrossDissolve,
- animations: { filePreviewImageView.image = imageIcon! },
- completion: nil)
- }
+ if self.metadata.ocId == self.cell?.fileObjectId, let filePreviewImageView = self.cell?.filePreviewImageView {
+ UIView.transition(with: filePreviewImageView,
+ duration: 0.75,
+ options: .transitionCrossDissolve,
+ animations: { filePreviewImageView.image = imageIcon },
+ completion: nil)
} else {
if self.view is UICollectionView {
(self.view as? UICollectionView)?.reloadData()
@@ -459,6 +489,58 @@ class NCOperationDownloadThumbnail: ConcurrentOperation {
// MARK: -
+class NCOperationDownloadThumbnailActivity: ConcurrentOperation {
+
+ var cell: NCActivityCollectionViewCell?
+ var collectionView: UICollectionView?
+ var fileNamePathOrFileId: String
+ var fileNamePreviewLocalPath: String
+ var fileId: String
+
+ init(fileNamePathOrFileId: String, fileNamePreviewLocalPath: String, fileId: String, cell: NCActivityCollectionViewCell?, collectionView: UICollectionView?) {
+ self.fileNamePathOrFileId = fileNamePathOrFileId
+ self.fileNamePreviewLocalPath = fileNamePreviewLocalPath
+ self.fileId = fileId
+ self.cell = cell
+ self.collectionView = collectionView
+ }
+
+ override func start() {
+
+ if isCancelled {
+ self.finish()
+ } else {
+
+ NCCommunication.shared.downloadPreview(
+ fileNamePathOrFileId: fileNamePathOrFileId,
+ fileNamePreviewLocalPath: fileNamePreviewLocalPath,
+ widthPreview: 0,
+ heightPreview: 0,
+ etag: nil,
+ useInternalEndpoint: false,
+ queue: NCCommunicationCommon.shared.backgroundQueue) { _, imagePreview, _, _, _, errorCode, _ in
+
+ if errorCode == 0, let imagePreview = imagePreview {
+ DispatchQueue.main.async {
+ if self.fileId == self.cell?.fileId, let imageView = self.cell?.imageView {
+ UIView.transition(with: imageView,
+ duration: 0.75,
+ options: .transitionCrossDissolve,
+ animations: { imageView.image = imagePreview },
+ completion: nil)
+ } else {
+ self.collectionView?.reloadData()
+ }
+ }
+ }
+ self.finish()
+ }
+ }
+ }
+}
+
+// MARK: -
+
class NCOperationDownloadAvatar: ConcurrentOperation {
var user: String
@@ -467,14 +549,16 @@ class NCOperationDownloadAvatar: ConcurrentOperation {
var fileNameLocalPath: String
var cell: NCCellProtocol!
var view: UIView?
+ var cellImageView: UIImageView?
- init(user: String, fileName: String, fileNameLocalPath: String, cell: NCCellProtocol, view: UIView?) {
+ init(user: String, fileName: String, fileNameLocalPath: String, cell: NCCellProtocol, view: UIView?, cellImageView: UIImageView?) {
self.user = user
self.fileName = fileName
self.fileNameLocalPath = fileNameLocalPath
self.cell = cell
self.view = view
self.etag = NCManageDatabase.shared.getTableAvatar(fileName: fileName)?.etag
+ self.cellImageView = cellImageView
}
override func start() {
@@ -485,22 +569,14 @@ class NCOperationDownloadAvatar: ConcurrentOperation {
NCCommunication.shared.downloadAvatar(user: user, fileNameLocalPath: fileNameLocalPath, sizeImage: NCGlobal.shared.avatarSize, avatarSizeRounded: NCGlobal.shared.avatarSizeRounded, etag: self.etag, queue: NCCommunicationCommon.shared.backgroundQueue) { _, imageAvatar, _, etag, errorCode, _ in
if errorCode == 0, let imageAvatar = imageAvatar, let etag = etag {
-
NCManageDatabase.shared.addAvatar(fileName: self.fileName, etag: etag)
-
DispatchQueue.main.async {
- if self.user == self.cell.fileUser {
- if let avatarImageView = self.cell?.fileAvatarImageView {
- UIView.transition(with: avatarImageView, duration: 0.75, options: .transitionCrossDissolve) {
- avatarImageView.image = imageAvatar
- } completion: { _ in
- if self.view is UICollectionView {
- (self.view as? UICollectionView)?.reloadData()
- } else if self.view is UITableView {
- (self.view as? UITableView)?.reloadData()
- }
- }
- }
+ if self.user == self.cell.fileUser, let avatarImageView = self.cellImageView {
+ UIView.transition(with: avatarImageView,
+ duration: 0.75,
+ options: .transitionCrossDissolve,
+ animations: { avatarImageView.image = imageAvatar },
+ completion: nil)
} else {
if self.view is UICollectionView {
(self.view as? UICollectionView)?.reloadData()
@@ -509,12 +585,46 @@ class NCOperationDownloadAvatar: ConcurrentOperation {
}
}
}
-
} else if errorCode == NCGlobal.shared.errorNotModified {
-
NCManageDatabase.shared.setAvatarLoaded(fileName: self.fileName)
}
+ self.finish()
+ }
+ }
+ }
+}
+
+// MARK: -
+
+class NCOperationUnifiedSearch: ConcurrentOperation {
+ var collectionViewCommon: NCCollectionViewCommon
+ var metadatas: [tableMetadata]
+ var searchResult: NCCSearchResult
+
+ init(collectionViewCommon: NCCollectionViewCommon, metadatas: [tableMetadata], searchResult: NCCSearchResult) {
+ self.collectionViewCommon = collectionViewCommon
+ self.metadatas = metadatas
+ self.searchResult = searchResult
+ }
+
+ func reloadDataThenPerform(_ closure: @escaping (() -> Void)) {
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
+ CATransaction.begin()
+ CATransaction.setCompletionBlock(closure)
+ self.collectionViewCommon.collectionView.reloadData()
+ CATransaction.commit()
+ }
+ }
+
+ override func start() {
+
+ if isCancelled {
+ self.finish()
+ } else {
+ self.collectionViewCommon.dataSource.addSection(metadatas: metadatas, searchResult: searchResult)
+ self.collectionViewCommon.searchResults?.append(self.searchResult)
+ reloadDataThenPerform {
self.finish()
}
}
diff --git a/iOSClient/Networking/NCService.swift b/iOSClient/Networking/NCService.swift
index 0084bdd7f..1cabc8962 100644
--- a/iOSClient/Networking/NCService.swift
+++ b/iOSClient/Networking/NCService.swift
@@ -39,11 +39,11 @@ class NCService: NSObject {
NCManageDatabase.shared.clearAllAvatarLoaded()
- if appDelegate.account == "" { return }
+ guard !appDelegate.account.isEmpty else { return }
- self.addInternalTypeIdentifier()
- self.requestUserProfile()
- self.requestServerStatus()
+ addInternalTypeIdentifier()
+ requestServerStatus()
+ requestUserProfile()
}
// MARK: -
@@ -79,180 +79,167 @@ class NCService: NSObject {
NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: "com.apple.iwork.keynote.key", classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorQuickLook, iconName: NCCommunicationCommon.typeIconFile.ppt.rawValue, name: "keynote")
}
- private func requestUserProfile() {
+ private func requestServerStatus() {
- if appDelegate.account == "" { return }
+ NCCommunication.shared.getServerStatus(serverUrl: appDelegate.urlBase, queue: NCCommunicationCommon.shared.backgroundQueue) { serverProductName, _, versionMajor, _, _, extendedSupport, errorCode, _ in
+ guard errorCode == 0, extendedSupport == false else {
+ return
+ }
- NCCommunication.shared.getUserProfile(queue: NCCommunicationCommon.shared.backgroundQueue) { account, userProfile, errorCode, errorDescription in
+ if serverProductName == "owncloud" {
+ NCContentPresenter.shared.messageNotification("_warning_", description: "_warning_owncloud_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
+ } else if versionMajor <= NCGlobal.shared.nextcloud_unsupported_version {
+ NCContentPresenter.shared.messageNotification("_warning_", description: "_warning_unsupported_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
+ }
+ }
+ }
- if errorCode == 0 && account == self.appDelegate.account {
+ private func requestUserProfile() {
+ guard !appDelegate.account.isEmpty else { return }
- // Update User (+ userProfile.id) & active account & account network
- guard let tableAccount = NCManageDatabase.shared.setAccountUserProfile(userProfile!) else {
- NCContentPresenter.shared.messageNotification("Account", description: "Internal error : account not found on DB", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
- return
+ NCCommunication.shared.getUserProfile(queue: NCCommunicationCommon.shared.backgroundQueue) { account, userProfile, errorCode, errorDescription in
+ guard errorCode == 0, account == self.appDelegate.account else {
+ NCBrandColor.shared.settingThemingColor(account: account)
+ if errorCode == 401 || errorCode == 403 {
+ NCNetworkingCheckRemoteUser.shared.checkRemoteUser(account: account, errorCode: errorCode, errorDescription: errorDescription)
}
+ return
+ }
- self.appDelegate.settingAccount(tableAccount.account, urlBase: tableAccount.urlBase, user: tableAccount.user, userId: tableAccount.userId, password: CCUtility.getPassword(tableAccount.account))
-
- // Synchronize favorite
- NCNetworking.shared.listingFavoritescompletion(selector: NCGlobal.shared.selectorReadFile) { _, _, _, _ in }
+ // Update User (+ userProfile.id) & active account & account network
+ guard let tableAccount = NCManageDatabase.shared.setAccountUserProfile(userProfile!) else {
+ NCContentPresenter.shared.messageNotification("Account", description: "Internal error : account not found on DB", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
+ return
+ }
- // Synchronize Offline
- self.synchronizeOffline(account: tableAccount.account)
+ self.appDelegate.settingAccount(tableAccount.account, urlBase: tableAccount.urlBase, user: tableAccount.user, userId: tableAccount.userId, password: CCUtility.getPassword(tableAccount.account))
- // Get Avatar
- let fileName = tableAccount.userBaseUrl + "-" + self.appDelegate.user + ".png"
- let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName
- let etag = NCManageDatabase.shared.getTableAvatar(fileName: fileName)?.etag
+ // Synchronize favorite
+ NCNetworking.shared.listingFavoritescompletion(selector: NCGlobal.shared.selectorReadFile) { _, _, _, _ in }
- NCCommunication.shared.downloadAvatar(user: tableAccount.userId, fileNameLocalPath: fileNameLocalPath, sizeImage: NCGlobal.shared.avatarSize, avatarSizeRounded: NCGlobal.shared.avatarSizeRounded, etag: etag, queue: NCCommunicationCommon.shared.backgroundQueue) { _, _, _, etag, errorCode, _ in
+ // Synchronize Offline
+ self.synchronizeOffline(account: tableAccount.account)
- if let etag = etag, errorCode == 0 {
- NCManageDatabase.shared.addAvatar(fileName: fileName, etag: etag)
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadAvatar, userInfo: nil)
- } else if errorCode == NCGlobal.shared.errorNotModified {
+ // Get Avatar
+ let fileName = tableAccount.userBaseUrl + "-" + self.appDelegate.user + ".png"
+ let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName
+ let etag = NCManageDatabase.shared.getTableAvatar(fileName: fileName)?.etag
+ NCCommunication.shared.downloadAvatar(user: tableAccount.userId, fileNameLocalPath: fileNameLocalPath, sizeImage: NCGlobal.shared.avatarSize, avatarSizeRounded: NCGlobal.shared.avatarSizeRounded, etag: etag, queue: NCCommunicationCommon.shared.backgroundQueue) { _, _, _, etag, errorCode, _ in
+ guard let etag = etag, errorCode == 0 else {
+ if errorCode == NCGlobal.shared.errorNotModified {
NCManageDatabase.shared.setAvatarLoaded(fileName: fileName)
}
+ return
}
- self.requestServerCapabilities()
-
- } else {
-
- if errorCode == 401 || errorCode == 403 {
- NCNetworkingCheckRemoteUser.shared.checkRemoteUser(account: account, errorCode: errorCode, errorDescription: errorDescription)
- }
+ NCManageDatabase.shared.addAvatar(fileName: fileName, etag: etag)
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadAvatar, userInfo: nil)
}
- }
- }
-
- private func requestServerStatus() {
-
- NCCommunication.shared.getServerStatus(serverUrl: appDelegate.urlBase, queue: NCCommunicationCommon.shared.backgroundQueue) { serverProductName, _, versionMajor, _, _, extendedSupport, errorCode, _ in
- if errorCode == 0 && extendedSupport == false {
-
- if serverProductName == "owncloud" {
- NCContentPresenter.shared.messageNotification("_warning_", description: "_warning_owncloud_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
- } else if versionMajor <= NCGlobal.shared.nextcloud_unsupported_version {
- NCContentPresenter.shared.messageNotification("_warning_", description: "_warning_unsupported_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorInternalError, priority: .max)
- }
- }
+ self.requestServerCapabilities()
}
}
private func requestServerCapabilities() {
-
- if appDelegate.account == "" { return }
+ guard !appDelegate.account.isEmpty else { return }
NCCommunication.shared.getCapabilities(queue: NCCommunicationCommon.shared.backgroundQueue) { account, data, errorCode, errorDescription in
+ guard errorCode == 0, let data = data else {
+ NCBrandColor.shared.settingThemingColor(account: account)
+ if errorCode == 401 || errorCode == 403 {
+ NCNetworkingCheckRemoteUser.shared.checkRemoteUser(account: account, errorCode: errorCode, errorDescription: errorDescription)
+ }
+ return
+ }
- if errorCode == 0 && data != nil {
-
- NCManageDatabase.shared.addCapabilitiesJSon(data!, account: account)
-
- let serverVersionMajor = NCManageDatabase.shared.getCapabilitiesServerInt(account: account, elements: NCElementsJSON.shared.capabilitiesVersionMajor)
+ NCManageDatabase.shared.addCapabilitiesJSon(data, account: account)
+ let serverVersionMajor = NCManageDatabase.shared.getCapabilitiesServerInt(account: account, elements: NCElementsJSON.shared.capabilitiesVersionMajor)
- // Setup communication
- if serverVersionMajor > 0 {
- NCCommunicationCommon.shared.setup(nextcloudVersion: serverVersionMajor)
- }
- NCCommunicationCommon.shared.setup(webDav: NCUtilityFileSystem.shared.getWebDAV(account: account))
+ // Setup communication
+ if serverVersionMajor > 0 {
+ NCCommunicationCommon.shared.setup(nextcloudVersion: serverVersionMajor)
+ }
+ NCCommunicationCommon.shared.setup(webDav: NCUtilityFileSystem.shared.getWebDAV(account: account))
- // Theming
+ // Theming
+ let themingColorNew = NCManageDatabase.shared.getCapabilitiesServerString(account: account, elements: NCElementsJSON.shared.capabilitiesThemingColor)
+ let themingColorElementNew = NCManageDatabase.shared.getCapabilitiesServerString(account: account, elements: NCElementsJSON.shared.capabilitiesThemingColorElement)
+ let themingColorTextNew = NCManageDatabase.shared.getCapabilitiesServerString(account: account, elements: NCElementsJSON.shared.capabilitiesThemingColorText)
+ if themingColorNew != NCBrandColor.shared.themingColor || themingColorElementNew != NCBrandColor.shared.themingColorElement || themingColorTextNew != NCBrandColor.shared.themingColorText {
NCBrandColor.shared.settingThemingColor(account: account)
+ }
- // File Sharing
- let isFilesSharingEnabled = NCManageDatabase.shared.getCapabilitiesServerBool(account: account, elements: NCElementsJSON.shared.capabilitiesFileSharingApiEnabled, exists: false)
- if isFilesSharingEnabled {
- NCCommunication.shared.readShares(parameters: NCCShareParameter(), queue: NCCommunicationCommon.shared.backgroundQueue) { account, shares, errorCode, errorDescription in
- if errorCode == 0 {
- NCManageDatabase.shared.deleteTableShare(account: account)
- if shares != nil {
- NCManageDatabase.shared.addShare(urlBase: self.appDelegate.urlBase, account: account, shares: shares!)
- }
- self.appDelegate.shares = NCManageDatabase.shared.getTableShares(account: account)
- } else {
- NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+ // File Sharing
+ let isFilesSharingEnabled = NCManageDatabase.shared.getCapabilitiesServerBool(account: account, elements: NCElementsJSON.shared.capabilitiesFileSharingApiEnabled, exists: false)
+ if isFilesSharingEnabled {
+ NCCommunication.shared.readShares(parameters: NCCShareParameter(), queue: NCCommunicationCommon.shared.backgroundQueue) { account, shares, errorCode, errorDescription in
+ if errorCode == 0 {
+ NCManageDatabase.shared.deleteTableShare(account: account)
+ if shares != nil {
+ NCManageDatabase.shared.addShare(urlBase: self.appDelegate.urlBase, account: account, shares: shares!)
}
+ self.appDelegate.shares = NCManageDatabase.shared.getTableShares(account: account)
+ } else {
+ NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
}
}
+ }
- let comments = NCManageDatabase.shared.getCapabilitiesServerBool(account: account, elements: NCElementsJSON.shared.capabilitiesFilesComments, exists: false)
- let activity = NCManageDatabase.shared.getCapabilitiesServerArray(account: account, elements: NCElementsJSON.shared.capabilitiesActivity)
-
- if !isFilesSharingEnabled && !comments && activity == nil {
- self.appDelegate.disableSharesView = true
- } else {
- self.appDelegate.disableSharesView = false
- }
+ let comments = NCManageDatabase.shared.getCapabilitiesServerBool(account: account, elements: NCElementsJSON.shared.capabilitiesFilesComments, exists: false)
+ let activity = NCManageDatabase.shared.getCapabilitiesServerArray(account: account, elements: NCElementsJSON.shared.capabilitiesActivity)
- // Text direct editor detail
- if serverVersionMajor >= NCGlobal.shared.nextcloudVersion18 {
- NCCommunication.shared.NCTextObtainEditorDetails(queue: NCCommunicationCommon.shared.backgroundQueue) { account, editors, creators, errorCode, _ in
- if errorCode == 0 && account == self.appDelegate.account {
- NCManageDatabase.shared.addDirectEditing(account: account, editors: editors, creators: creators)
- }
- }
- }
+ if !isFilesSharingEnabled && !comments && activity == nil {
+ self.appDelegate.disableSharesView = true
+ } else {
+ self.appDelegate.disableSharesView = false
+ }
- // External file Server
- let isExternalSitesServerEnabled = NCManageDatabase.shared.getCapabilitiesServerBool(account: account, elements: NCElementsJSON.shared.capabilitiesExternalSitesExists, exists: true)
- if isExternalSitesServerEnabled {
- NCCommunication.shared.getExternalSite(queue: NCCommunicationCommon.shared.backgroundQueue) { account, externalSites, errorCode, _ in
- if errorCode == 0 && account == self.appDelegate.account {
- NCManageDatabase.shared.deleteExternalSites(account: account)
- for externalSite in externalSites {
- NCManageDatabase.shared.addExternalSites(externalSite, account: account)
- }
- }
+ // Text direct editor detail
+ if serverVersionMajor >= NCGlobal.shared.nextcloudVersion18 {
+ NCCommunication.shared.NCTextObtainEditorDetails(queue: NCCommunicationCommon.shared.backgroundQueue) { account, editors, creators, errorCode, _ in
+ if errorCode == 0 && account == self.appDelegate.account {
+ NCManageDatabase.shared.addDirectEditing(account: account, editors: editors, creators: creators)
}
-
- } else {
- NCManageDatabase.shared.deleteExternalSites(account: account)
}
+ }
- // User Status
- let userStatus = NCManageDatabase.shared.getCapabilitiesServerBool(account: account, elements: NCElementsJSON.shared.capabilitiesUserStatusEnabled, exists: false)
- if userStatus {
- NCCommunication.shared.getUserStatus(queue: NCCommunicationCommon.shared.backgroundQueue) { account, clearAt, icon, message, messageId, messageIsPredefined, status, statusIsUserDefined, userId, errorCode, _ in
- if errorCode == 0 && account == self.appDelegate.account && userId == self.appDelegate.userId {
- NCManageDatabase.shared.setAccountUserStatus(userStatusClearAt: clearAt, userStatusIcon: icon, userStatusMessage: message, userStatusMessageId: messageId, userStatusMessageIsPredefined: messageIsPredefined, userStatusStatus: status, userStatusStatusIsUserDefined: statusIsUserDefined, account: account)
+ // External file Server
+ let isExternalSitesServerEnabled = NCManageDatabase.shared.getCapabilitiesServerBool(account: account, elements: NCElementsJSON.shared.capabilitiesExternalSitesExists, exists: true)
+ if isExternalSitesServerEnabled {
+ NCCommunication.shared.getExternalSite(queue: NCCommunicationCommon.shared.backgroundQueue) { account, externalSites, errorCode, _ in
+ if errorCode == 0 && account == self.appDelegate.account {
+ NCManageDatabase.shared.deleteExternalSites(account: account)
+ for externalSite in externalSites {
+ NCManageDatabase.shared.addExternalSites(externalSite, account: account)
}
}
}
+ } else {
+ NCManageDatabase.shared.deleteExternalSites(account: account)
+ }
- // Added UTI for Collabora
- if let richdocumentsMimetypes = NCManageDatabase.shared.getCapabilitiesServerArray(account: account, elements: NCElementsJSON.shared.capabilitiesRichdocumentsMimetypes) {
- for mimeType in richdocumentsMimetypes {
- NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: mimeType, classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorCollabora, iconName: NCCommunicationCommon.typeIconFile.document.rawValue, name: "document")
+ // User Status
+ let userStatus = NCManageDatabase.shared.getCapabilitiesServerBool(account: account, elements: NCElementsJSON.shared.capabilitiesUserStatusEnabled, exists: false)
+ if userStatus {
+ NCCommunication.shared.getUserStatus(queue: NCCommunicationCommon.shared.backgroundQueue) { account, clearAt, icon, message, messageId, messageIsPredefined, status, statusIsUserDefined, userId, errorCode, _ in
+ if errorCode == 0 && account == self.appDelegate.account && userId == self.appDelegate.userId {
+ NCManageDatabase.shared.setAccountUserStatus(userStatusClearAt: clearAt, userStatusIcon: icon, userStatusMessage: message, userStatusMessageId: messageId, userStatusMessageIsPredefined: messageIsPredefined, userStatusStatus: status, userStatusStatusIsUserDefined: statusIsUserDefined, account: account)
}
}
+ }
- // Added UTI for ONLYOFFICE & Text
- if let directEditingCreators = NCManageDatabase.shared.getDirectEditingCreators(account: account) {
- for directEditing in directEditingCreators {
- NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: directEditing.mimetype, classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: directEditing.editor, iconName: NCCommunicationCommon.typeIconFile.document.rawValue, name: "document")
- }
+ // Added UTI for Collabora
+ if let richdocumentsMimetypes = NCManageDatabase.shared.getCapabilitiesServerArray(account: account, elements: NCElementsJSON.shared.capabilitiesRichdocumentsMimetypes) {
+ for mimeType in richdocumentsMimetypes {
+ NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: mimeType, classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: NCGlobal.shared.editorCollabora, iconName: NCCommunicationCommon.typeIconFile.document.rawValue, name: "document")
}
+ }
- // Handwerkcloud
- // let isHandwerkcloudEnabled = NCManageDatabase.shared.getCapabilitiesServerBool(account: account, elements: NCElementsJSON.shared.capabilitiesHWCEnabled, exists: false)
- // if (isHandwerkcloudEnabled) {
- // self.requestHC()
- // }
-
- } else if errorCode != 0 {
-
- NCBrandColor.shared.settingThemingColor(account: account)
-
- if errorCode == 401 || errorCode == 403 {
- NCNetworkingCheckRemoteUser.shared.checkRemoteUser(account: account, errorCode: errorCode, errorDescription: errorDescription)
+ // Added UTI for ONLYOFFICE & Text
+ if let directEditingCreators = NCManageDatabase.shared.getDirectEditingCreators(account: account) {
+ for directEditing in directEditingCreators {
+ NCCommunicationCommon.shared.addInternalTypeIdentifier(typeIdentifier: directEditing.mimetype, classFile: NCCommunicationCommon.typeClassFile.document.rawValue, editor: directEditing.editor, iconName: NCCommunicationCommon.typeIconFile.document.rawValue, name: "document")
}
-
- } else {
- NCBrandColor.shared.settingThemingColor(account: account)
}
}
}
@@ -280,8 +267,4 @@ class NCService: NSObject {
}
// MARK: - Thirt Part
-
- private func requestHC() {
-
- }
}
diff --git a/iOSClient/Notification/NCNotification.swift b/iOSClient/Notification/NCNotification.swift
index bbe9eb8a1..b4700778a 100644
--- a/iOSClient/Notification/NCNotification.swift
+++ b/iOSClient/Notification/NCNotification.swift
@@ -49,10 +49,6 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
// Empty
let offset = (self.navigationController?.navigationBar.bounds.height ?? 0) - 20
emptyDataSet = NCEmptyDataSet(view: tableView, offset: -offset, delegate: self)
-
- NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil)
-
- changeTheming()
}
override func viewWillAppear(_ animated: Bool) {
@@ -86,10 +82,6 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
getNetwokingNotification()
}
- @objc func changeTheming() {
- tableView.reloadData()
- }
-
// MARK: - Empty
func emptyDataSetView(_ view: NCEmptyView) {
@@ -146,7 +138,7 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
cell.avatar.image = image
} else if !FileManager.default.fileExists(atPath: fileNameLocalPath) {
cell.fileUser = user
- NCOperationQueue.shared.downloadAvatar(user: user, dispalyName: json["user"]?["name"].string, fileName: fileName, cell: cell, view: tableView)
+ NCOperationQueue.shared.downloadAvatar(user: user, dispalyName: json["user"]?["name"].string, fileName: fileName, cell: cell, view: tableView, cellImageView: cell.fileAvatarImageView)
}
}
@@ -164,18 +156,20 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
cell.primary.isEnabled = false
cell.primary.isHidden = true
cell.primary.titleLabel?.font = .systemFont(ofSize: 15)
- cell.primary.setTitleColor(.white, for: .normal)
cell.primary.layer.cornerRadius = 15
cell.primary.layer.masksToBounds = true
cell.primary.layer.backgroundColor = NCBrandColor.shared.brandElement.cgColor
+ cell.primary.setTitleColor(NCBrandColor.shared.brandText, for: .normal)
cell.secondary.isEnabled = false
cell.secondary.isHidden = true
cell.secondary.titleLabel?.font = .systemFont(ofSize: 15)
- cell.secondary.setTitleColor(NCBrandColor.shared.label, for: .normal)
cell.secondary.layer.cornerRadius = 15
cell.secondary.layer.masksToBounds = true
- cell.secondary.layer.backgroundColor = NCBrandColor.shared.systemFill.cgColor
+ cell.secondary.layer.borderWidth = 1
+ cell.secondary.layer.borderColor = NCBrandColor.shared.systemGray.cgColor
+ cell.secondary.layer.backgroundColor = NCBrandColor.shared.secondarySystemBackground.cgColor
+ cell.secondary.setTitleColor(.black, for: .normal)
// Action
if let actions = notification.actions,
@@ -278,8 +272,6 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
func getNetwokingNotification() {
- NCUtility.shared.startActivityIndicator(backgroundView: self.navigationController?.view, blurEffect: true)
-
NCCommunication.shared.getNotifications { account, notifications, errorCode, _ in
if errorCode == 0 && account == self.appDelegate.account {
@@ -296,8 +288,6 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty
self.reloadDatasource()
}
-
- NCUtility.shared.stopActivityIndicator()
}
}
}
@@ -323,28 +313,12 @@ class NCNotificationCell: UITableViewCell, NCCellProtocol {
weak var delegate: NCNotificationCellDelegate?
var notification: NCCommunicationNotifications?
- var filePreviewImageView: UIImageView? {
- get {
- return nil
- }
- }
var fileAvatarImageView: UIImageView? {
- get {
- return avatar
- }
- }
- var fileObjectId: String? {
- get {
- return nil
- }
+ get { return avatar }
}
var fileUser: String? {
- get {
- return user
- }
- set {
- user = newValue ?? ""
- }
+ get { return user }
+ set { user = newValue ?? "" }
}
override func awakeFromNib() {
diff --git a/iOSClient/Offline/NCOffline.swift b/iOSClient/Offline/NCOffline.swift
index 1baaddc2b..224f453d1 100644
--- a/iOSClient/Offline/NCOffline.swift
+++ b/iOSClient/Offline/NCOffline.swift
@@ -33,7 +33,10 @@ class NCOffline: NCCollectionViewCommon {
titleCurrentFolder = NSLocalizedString("_manage_file_offline_", comment: "")
layoutKey = NCGlobal.shared.layoutViewOffline
- enableSearchBar = true
+ enableSearchBar = false
+ headerMenuButtonsCommand = false
+ headerMenuButtonsView = true
+ headerRichWorkspaceDisable = true
emptyImage = UIImage(named: "folder")?.image(color: NCBrandColor.shared.brandElement, size: UIScreen.main.bounds.width)
emptyTitle = "_files_no_files_"
emptyDescription = "_tutorial_offline_view_"
@@ -41,37 +44,39 @@ class NCOffline: NCCollectionViewCommon {
// MARK: - DataSource + NC Endpoint
- override func reloadDataSource() {
+ override func reloadDataSource(forced: Bool = true) {
super.reloadDataSource()
DispatchQueue.global().async {
-
var ocIds: [String] = []
+ var metadatas: [tableMetadata] = []
- if !self.isSearching {
-
- if self.serverUrl == "" {
-
- if let directories = NCManageDatabase.shared.getTablesDirectory(predicate: NSPredicate(format: "account == %@ AND offline == true", self.appDelegate.account), sorted: "serverUrl", ascending: true) {
- for directory: tableDirectory in directories {
- ocIds.append(directory.ocId)
- }
- }
-
- let files = NCManageDatabase.shared.getTableLocalFiles(predicate: NSPredicate(format: "account == %@ AND offline == true", self.appDelegate.account), sorted: "fileName", ascending: true)
- for file: tableLocalFile in files {
- ocIds.append(file.ocId)
+ if self.serverUrl.isEmpty {
+ if let directories = NCManageDatabase.shared.getTablesDirectory(predicate: NSPredicate(format: "account == %@ AND offline == true", self.appDelegate.account), sorted: "serverUrl", ascending: true) {
+ for directory: tableDirectory in directories {
+ ocIds.append(directory.ocId)
}
-
- self.metadatasSource = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND ocId IN %@", self.appDelegate.account, ocIds))
-
- } else {
-
- self.metadatasSource = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
}
+ let files = NCManageDatabase.shared.getTableLocalFiles(predicate: NSPredicate(format: "account == %@ AND offline == true", self.appDelegate.account), sorted: "fileName", ascending: true)
+ for file in files {
+ ocIds.append(file.ocId)
+ }
+ metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND ocId IN %@", self.appDelegate.account, ocIds))
+ } else {
+ metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
}
- self.dataSource = NCDataSource(metadatasSource: self.metadatasSource, sort: self.layoutForView?.sort, ascending: self.layoutForView?.ascending, directoryOnTop: self.layoutForView?.directoryOnTop, favoriteOnTop: true, filterLivePhoto: true)
+ self.dataSource = NCDataSource(
+ metadatas: metadatas,
+ account: self.appDelegate.account,
+ sort: self.layoutForView?.sort,
+ ascending: self.layoutForView?.ascending,
+ directoryOnTop: self.layoutForView?.directoryOnTop,
+ favoriteOnTop: true,
+ filterLivePhoto: true,
+ groupByField: self.groupByField,
+ providers: self.providers,
+ searchResults: self.searchResults)
DispatchQueue.main.async {
self.refreshControl.endRefreshing()
@@ -83,40 +88,33 @@ class NCOffline: NCCollectionViewCommon {
override func reloadDataSourceNetwork(forced: Bool = false) {
super.reloadDataSourceNetwork(forced: forced)
- if isSearching {
- networkSearch()
+ guard !serverUrl.isEmpty else {
+ self.reloadDataSource()
return
}
- if serverUrl == "" {
-
- self.reloadDataSource()
-
- } else {
-
- isReloadDataSourceNetworkInProgress = true
- collectionView?.reloadData()
+ isReloadDataSourceNetworkInProgress = true
+ collectionView?.reloadData()
- networkReadFolder(forced: forced) { tableDirectory, metadatas, metadatasUpdate, metadatasDelete, errorCode, _ in
- if errorCode == 0 {
- for metadata in metadatas ?? [] {
- if !metadata.directory {
- if NCManageDatabase.shared.isDownloadMetadata(metadata, download: true) {
- NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorDownloadFile)
- }
+ networkReadFolder(forced: forced) { tableDirectory, metadatas, metadatasUpdate, metadatasDelete, errorCode, _ in
+ if errorCode == 0 {
+ for metadata in metadatas ?? [] {
+ if !metadata.directory {
+ if NCManageDatabase.shared.isDownloadMetadata(metadata, download: true) {
+ NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorDownloadFile)
}
}
}
+ }
- DispatchQueue.main.async {
- self.refreshControl.endRefreshing()
- self.isReloadDataSourceNetworkInProgress = false
- self.richWorkspaceText = tableDirectory?.richWorkspace
- if metadatasUpdate?.count ?? 0 > 0 || metadatasDelete?.count ?? 0 > 0 || forced {
- self.reloadDataSource()
- } else {
- self.collectionView?.reloadData()
- }
+ DispatchQueue.main.async {
+ self.refreshControl.endRefreshing()
+ self.isReloadDataSourceNetworkInProgress = false
+ self.richWorkspaceText = tableDirectory?.richWorkspace
+ if metadatasUpdate?.count ?? 0 > 0 || metadatasDelete?.count ?? 0 > 0 || forced {
+ self.reloadDataSource()
+ } else {
+ self.collectionView?.reloadData()
}
}
}
diff --git a/iOSClient/Recent/NCRecent.swift b/iOSClient/Recent/NCRecent.swift
index f85d2370d..717de856e 100644
--- a/iOSClient/Recent/NCRecent.swift
+++ b/iOSClient/Recent/NCRecent.swift
@@ -34,26 +34,28 @@ class NCRecent: NCCollectionViewCommon {
titleCurrentFolder = NSLocalizedString("_recent_", comment: "")
layoutKey = NCGlobal.shared.layoutViewRecent
enableSearchBar = false
+ headerMenuButtonsCommand = false
+ headerMenuButtonsView = false
+ headerRichWorkspaceDisable = true
emptyImage = UIImage(named: "recent")?.image(color: .gray, size: UIScreen.main.bounds.width)
emptyTitle = "_files_no_files_"
emptyDescription = ""
}
- // MARK: - Collection View
-
- override func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
- return CGSize(width: collectionView.frame.width, height: 0)
- }
-
// MARK: - DataSource + NC Endpoint
- override func reloadDataSource() {
+ override func reloadDataSource(forced: Bool = true) {
super.reloadDataSource()
DispatchQueue.global().async {
-
- self.metadatasSource = NCManageDatabase.shared.getAdvancedMetadatas(predicate: NSPredicate(format: "account == %@", self.appDelegate.account), page: 1, limit: 100, sorted: "date", ascending: false)
- self.dataSource = NCDataSource(metadatasSource: self.metadatasSource, directoryOnTop: false, favoriteOnTop: false)
+ let metadatas = NCManageDatabase.shared.getAdvancedMetadatas(predicate: NSPredicate(format: "account == %@", self.appDelegate.account), page: 1, limit: 100, sorted: "date", ascending: false)
+ self.dataSource = NCDataSource(metadatas: metadatas,
+ account: self.appDelegate.account,
+ directoryOnTop: false,
+ favoriteOnTop: false,
+ groupByField: self.groupByField,
+ providers: self.providers,
+ searchResults: self.searchResults)
DispatchQueue.main.async {
self.refreshControl.endRefreshing()
@@ -65,11 +67,6 @@ class NCRecent: NCCollectionViewCommon {
override func reloadDataSourceNetwork(forced: Bool = false) {
super.reloadDataSourceNetwork(forced: forced)
- if isSearching {
- networkSearch()
- return
- }
-
let requestBodyRecent =
"""
<?xml version=\"1.0\"?>
diff --git a/iOSClient/Rename file/NCRenameFile.swift b/iOSClient/Rename file/NCRenameFile.swift
index 57a661fd8..c053a772c 100644
--- a/iOSClient/Rename file/NCRenameFile.swift
+++ b/iOSClient/Rename file/NCRenameFile.swift
@@ -161,6 +161,8 @@ class NCRenameFile: UIViewController, UITextFieldDelegate {
if let metadata = self.metadata {
+ let extCurrent = (metadata.fileNameView as NSString).pathExtension
+
if fileNameWithoutExt.text == nil || fileNameWithoutExt.text?.count == 0 {
self.fileNameWithoutExt.text = (metadata.fileNameView as NSString).deletingPathExtension
return
@@ -182,9 +184,9 @@ class NCRenameFile: UIViewController, UITextFieldDelegate {
extNew = ext.text!
}
- if extNew != metadata.ext {
+ if extNew != extCurrent {
- let message = String(format: NSLocalizedString("_rename_ext_message_", comment: ""), extNew, metadata.ext)
+ let message = String(format: NSLocalizedString("_rename_ext_message_", comment: ""), extNew, extCurrent)
let alertController = UIAlertController(title: NSLocalizedString("_rename_ext_title_", comment: ""), message: message, preferredStyle: .alert)
var title = NSLocalizedString("_use_", comment: "") + " ." + extNew
@@ -194,7 +196,7 @@ class NCRenameFile: UIViewController, UITextFieldDelegate {
self.renameMetadata(metadata, fileNameNew: fileNameNew)
}))
- title = NSLocalizedString("_keep_", comment: "") + " ." + metadata.ext
+ title = NSLocalizedString("_keep_", comment: "") + " ." + extCurrent
alertController.addAction(UIAlertAction(title: title, style: .default, handler: { _ in
self.ext.text = metadata.fileExtension
}))
@@ -229,11 +231,11 @@ class NCRenameFile: UIViewController, UITextFieldDelegate {
func renameMetadata(_ metadata: tableMetadata, fileNameNew: String) {
- NCUtility.shared.startActivityIndicator(backgroundView: nil, blurEffect: true)
+ NCActivityIndicator.shared.start()
NCNetworking.shared.renameMetadata(metadata, fileNameNew: fileNameNew, viewController: self) { errorCode, errorDescription in
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
if errorCode == 0 {
diff --git a/iOSClient/RichWorkspace/NCRichWorkspaceCommon.swift b/iOSClient/RichWorkspace/NCRichWorkspaceCommon.swift
index ee58eb7d2..e2576929d 100644
--- a/iOSClient/RichWorkspace/NCRichWorkspaceCommon.swift
+++ b/iOSClient/RichWorkspace/NCRichWorkspaceCommon.swift
@@ -37,12 +37,12 @@ import NCCommunication
guard let directEditingCreator = NCManageDatabase.shared.getDirectEditingCreators(predicate: NSPredicate(format: "account == %@ AND editor == 'text'", appDelegate.account))?.first else { return }
- NCUtility.shared.startActivityIndicator(backgroundView: viewController.view, blurEffect: true)
+ NCActivityIndicator.shared.start(backgroundView: viewController.view)
let fileNamePath = CCUtility.returnFileNamePath(fromFileName: NCGlobal.shared.fileNameRichWorkspace, serverUrl: serverUrl, urlBase: appDelegate.urlBase, account: appDelegate.account)!
NCCommunication.shared.NCTextCreateFile(fileNamePath: fileNamePath, editorId: directEditingCreator.editor, creatorId: directEditingCreator.identifier, templateId: "") { account, url, errorCode, errorMessage in
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
if errorCode == 0 && account == self.appDelegate.account {
@@ -72,12 +72,12 @@ import NCCommunication
if metadata.url == "" {
- NCUtility.shared.startActivityIndicator(backgroundView: viewController.view, blurEffect: true)
+ NCActivityIndicator.shared.start(backgroundView: viewController.view)
let fileNamePath = CCUtility.returnFileNamePath(fromFileName: metadata.fileName, serverUrl: metadata.serverUrl, urlBase: appDelegate.urlBase, account: appDelegate.account)!
NCCommunication.shared.NCTextOpenFile(fileNamePath: fileNamePath, editor: "text") { account, url, errorCode, errorMessage in
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
if errorCode == 0 && account == self.appDelegate.account {
diff --git a/iOSClient/RichWorkspace/NCViewerRichWorkspace.swift b/iOSClient/RichWorkspace/NCViewerRichWorkspace.swift
index 7ba567793..652005b76 100644
--- a/iOSClient/RichWorkspace/NCViewerRichWorkspace.swift
+++ b/iOSClient/RichWorkspace/NCViewerRichWorkspace.swift
@@ -34,8 +34,9 @@ import MarkdownKit
private var markdownParser = MarkdownParser()
private var textViewColor: UIColor?
- @objc public var richWorkspaceText: String = ""
- @objc public var serverUrl: String = ""
+ var richWorkspaceText: String = ""
+ var serverUrl: String = ""
+ var delegate: NCCollectionViewCommon?
// MARK: - View Life Cycle
@@ -60,13 +61,13 @@ import MarkdownKit
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
- NCNetworking.shared.readFile(serverUrlFileName: serverUrl, account: appDelegate.account) { account, metadata, errorCode, _ in
+ NCNetworking.shared.readFile(serverUrlFileName: serverUrl) { (account, metadata, errorCode, errorDescription) in
if errorCode == 0 && account == self.appDelegate.account {
guard let metadata = metadata else { return }
- NCManageDatabase.shared.setDirectory(richWorkspace: metadata.richWorkspace, serverUrl: self.serverUrl, account: account)
+ NCManageDatabase.shared.setDirectory(serverUrl: self.serverUrl, richWorkspace: metadata.richWorkspace, account: account)
if self.richWorkspaceText != metadata.richWorkspace && metadata.richWorkspace != nil {
- self.appDelegate.activeFiles?.richWorkspaceText = self.richWorkspaceText
+ self.delegate?.richWorkspaceText = self.richWorkspaceText
self.richWorkspaceText = metadata.richWorkspace!
DispatchQueue.main.async {
self.textView.attributedText = self.markdownParser.parse(metadata.richWorkspace!)
diff --git a/iOSClient/ScanDocument/NCScan.swift b/iOSClient/ScanDocument/NCScan.swift
index a5d395610..e015e7d18 100755
--- a/iOSClient/ScanDocument/NCScan.swift
+++ b/iOSClient/ScanDocument/NCScan.swift
@@ -22,6 +22,8 @@
//
import UIKit
+import Photos
+import EasyTipView
@available(iOS 13.0, *)
class NCScan: UIViewController, NCScanCellCellDelegate {
@@ -44,6 +46,8 @@ class NCScan: UIViewController, NCScanCellCellDelegate {
internal let appDelegate = (UIApplication.shared.delegate as? AppDelegate)!
+ private var tipView: EasyTipView?
+
enum TypeFilter {
case original
case grayScale
@@ -89,12 +93,37 @@ class NCScan: UIViewController, NCScanCellCellDelegate {
let longPressRecognizerPlus = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPressGesture(recognizer:)))
add.addGestureRecognizer(longPressRecognizerPlus)
+ // TIP
+ var preferences = EasyTipView.Preferences()
+ preferences.drawing.foregroundColor = .white
+ preferences.drawing.backgroundColor = NCBrandColor.shared.nextcloud
+ preferences.drawing.textAlignment = .left
+ preferences.drawing.arrowPosition = .left
+ preferences.drawing.cornerRadius = 10
+
+ preferences.animating.dismissTransform = CGAffineTransform(translationX: 0, y: 100)
+ preferences.animating.showInitialTransform = CGAffineTransform(translationX: 0, y: -100)
+ preferences.animating.showInitialAlpha = 0
+ preferences.animating.showDuration = 1.5
+ preferences.animating.dismissDuration = 1.5
+
+ tipView = EasyTipView(text: NSLocalizedString("_tip_addcopyimage_", comment: ""), preferences: preferences, delegate: self)
+
collectionViewSource.reloadData()
collectionViewDestination.reloadData()
loadImage()
}
+ override func viewDidAppear(_ animated: Bool) {
+ super.viewDidAppear(animated)
+
+ // TIP
+ if !NCManageDatabase.shared.tipExists(NCGlobal.shared.tipNCScanAddImage) {
+ self.tipView?.show(forView: add, withinSuperview: self.view)
+ }
+ }
+
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
@@ -133,6 +162,9 @@ class NCScan: UIViewController, NCScanCellCellDelegate {
@IBAction func add(sender: UIButton) {
+ // TIP
+ dismissTip()
+
NCCreateScanDocument.shared.openScannerDocument(viewController: self)
}
@@ -314,6 +346,9 @@ class NCScan: UIViewController, NCScanCellCellDelegate {
UIMenuController.shared.setTargetRect(recognizerView.frame, in: recognizerSuperView)
UIMenuController.shared.setMenuVisible(true, animated: true)
}
+
+ // TIP
+ dismissTip()
}
}
@@ -370,3 +405,19 @@ class NCScan: UIViewController, NCScanCellCellDelegate {
}
}
}
+
+@available(iOS 13.0, *)
+extension NCScan: EasyTipViewDelegate {
+
+ // TIP
+ func easyTipViewDidTap(_ tipView: EasyTipView) {
+ NCManageDatabase.shared.addTip(NCGlobal.shared.tipNCScanAddImage)
+ }
+
+ func easyTipViewDidDismiss(_ tipView: EasyTipView) { }
+
+ func dismissTip() {
+ NCManageDatabase.shared.addTip(NCGlobal.shared.tipNCScanAddImage)
+ self.tipView?.dismiss()
+ }
+}
diff --git a/iOSClient/Select/NCSelect.swift b/iOSClient/Select/NCSelect.swift
index 76f0ecaa5..7734158d9 100644
--- a/iOSClient/Select/NCSelect.swift
+++ b/iOSClient/Select/NCSelect.swift
@@ -58,11 +58,12 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
private var emptyDataSet: NCEmptyDataSet?
- private let keyLayout = NCGlobal.shared.layoutViewMove
+ private let layoutKey = NCGlobal.shared.layoutViewMove
private var serverUrlPush = ""
private var metadataFolder = tableMetadata()
private var isEditMode = false
+ private var isSearching = false
private var networkInProgress = false
private var selectOcId: [String] = []
private var overwrite = true
@@ -71,6 +72,7 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
internal var richWorkspaceText: String?
private var layoutForView: NCGlobal.layoutForViewType?
+ internal var headerMenu: NCSectionHeaderMenu?
private var autoUploadFileName = ""
private var autoUploadDirectory = ""
@@ -78,10 +80,6 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
private var listLayout: NCListLayout!
private var gridLayout: NCGridLayout!
- private let headerHeight: CGFloat = 50
- private var headerRichWorkspaceHeight: CGFloat = 0
- private let footerHeight: CGFloat = 50
-
private var shares: [tableShare]?
private var backgroundImageView = UIImageView()
@@ -97,6 +95,7 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
self.navigationController?.presentationController?.delegate = self
view.backgroundColor = NCBrandColor.shared.systemBackground
+ selectCommandViewSelect?.separatorView.backgroundColor = NCBrandColor.shared.separator
activeAccount = NCManageDatabase.shared.getActiveAccount()
@@ -120,7 +119,7 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
bottomContraint?.constant = UIApplication.shared.keyWindow?.rootViewController?.view.safeAreaInsets.bottom ?? 0
// Empty
- emptyDataSet = NCEmptyDataSet(view: collectionView, offset: headerHeight, delegate: self)
+ emptyDataSet = NCEmptyDataSet(view: collectionView, offset: NCGlobal.shared.heightButtonsView, delegate: self)
// Type of command view
if typeOfCommandView == .select || typeOfCommandView == .selectCreateFolder {
@@ -158,11 +157,8 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
bottomContraint?.constant = 150
}
- NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSource), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSource), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(createFolder(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterCreateFolder), object: nil)
-
- changeTheming()
}
override func viewWillAppear(_ animated: Bool) {
@@ -179,7 +175,7 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
autoUploadFileName = NCManageDatabase.shared.getAccountAutoUploadFileName()
autoUploadDirectory = NCManageDatabase.shared.getAccountAutoUploadDirectory(urlBase: activeAccount.urlBase, account: activeAccount.account)
- layoutForView = NCUtility.shared.getLayoutForView(key: keyLayout, serverUrl: serverUrl)
+ layoutForView = NCUtility.shared.getLayoutForView(key: layoutKey, serverUrl: serverUrl)
gridLayout.itemForLine = CGFloat(layoutForView?.itemForLine ?? 3)
if layoutForView?.layout == NCGlobal.shared.layoutList {
@@ -207,21 +203,16 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
// MARK: - NotificationCenter
- @objc func changeTheming() {
-
- collectionView.reloadData()
- selectCommandViewSelect?.separatorView.backgroundColor = NCBrandColor.shared.separator
- }
-
@objc func createFolder(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["ocId"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
- if metadata.serverUrl == serverUrl {
- pushMetadata(metadata)
- }
- }
- }
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ let serverUrl = userInfo["serverUrl"] as? String,
+ serverUrl == self.serverUrl,
+ let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId)
+ else { return }
+
+ pushMetadata(metadata)
}
// MARK: - Empty
@@ -275,33 +266,36 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
// MARK: TAP EVENT
- func tapSwitchHeader(sender: Any) {
+ func tapButtonSwitch(_ sender: Any) {
+
+ if layoutForView?.layout == NCGlobal.shared.layoutGrid {
- if collectionView.collectionViewLayout == gridLayout {
// list layout
- UIView.animate(withDuration: 0.0, animations: {
- self.collectionView.collectionViewLayout.invalidateLayout()
- self.collectionView.setCollectionViewLayout(self.listLayout, animated: false, completion: { _ in
- self.collectionView.reloadData()
- })
- })
+ headerMenu?.buttonSwitch.accessibilityLabel = NSLocalizedString("_grid_view_", comment: "")
layoutForView?.layout = NCGlobal.shared.layoutList
+ NCUtility.shared.setLayoutForView(key: layoutKey, serverUrl: serverUrl, layout: layoutForView?.layout)
+
+ self.collectionView.reloadData()
+ self.collectionView.collectionViewLayout.invalidateLayout()
+ self.collectionView.setCollectionViewLayout(self.listLayout, animated: true)
+
} else {
+
// grid layout
- UIView.animate(withDuration: 0.0, animations: {
- self.collectionView.collectionViewLayout.invalidateLayout()
- self.collectionView.setCollectionViewLayout(self.gridLayout, animated: false, completion: { _ in
- self.collectionView.reloadData()
- })
- })
+ headerMenu?.buttonSwitch.accessibilityLabel = NSLocalizedString("_list_view_", comment: "")
layoutForView?.layout = NCGlobal.shared.layoutGrid
+ NCUtility.shared.setLayoutForView(key: layoutKey, serverUrl: serverUrl, layout: layoutForView?.layout)
+
+ self.collectionView.reloadData()
+ self.collectionView.collectionViewLayout.invalidateLayout()
+ self.collectionView.setCollectionViewLayout(self.gridLayout, animated: true)
}
}
- func tapOrderHeader(sender: Any) {
+ func tapButtonOrder(_ sender: Any) {
let sortMenu = NCSortMenu()
- sortMenu.toggleMenu(viewController: self, key: keyLayout, sortButton: sender as? UIButton, serverUrl: serverUrl)
+ sortMenu.toggleMenu(viewController: self, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl)
}
// MARK: - Push metadata
@@ -361,38 +355,6 @@ extension NCSelect: UICollectionViewDelegate {
extension NCSelect: UICollectionViewDataSource {
- func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
-
- if kind == UICollectionView.elementKindSectionHeader {
-
- let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionHeaderMenu", for: indexPath) as! NCSectionHeaderMenu
-
- if collectionView.collectionViewLayout == gridLayout {
- header.buttonSwitch.setImage(UIImage(named: "switchList")?.image(color: NCBrandColor.shared.gray, size: 25), for: .normal)
- } else {
- header.buttonSwitch.setImage(UIImage(named: "switchGrid")?.image(color: NCBrandColor.shared.gray, size: 25), for: .normal)
- }
-
- header.delegate = self
- header.setStatusButton(count: dataSource.metadatas.count)
- header.setTitleSorted(datasourceTitleButton: layoutForView?.titleButtonHeader ?? "")
- header.viewRichWorkspaceHeightConstraint.constant = headerRichWorkspaceHeight
- header.setRichWorkspaceText(richWorkspaceText: richWorkspaceText)
-
- return header
-
- } else {
-
- let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as! NCSectionFooter
-
- let info = dataSource.getFilesInformation()
- footer.setTitleLabel(directories: info.directories, files: info.files, size: info.size)
-
- return footer
- }
-
- }
-
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
guard let metadata = dataSource.cellForItemAt(indexPath: indexPath) else { return }
@@ -411,7 +373,7 @@ extension NCSelect: UICollectionViewDataSource {
activeAccount.account == metadata.account,
let cell = cell as? NCCellProtocol {
let fileName = metadata.userBaseUrl + "-" + metadata.ownerId + ".png"
- NCOperationQueue.shared.downloadAvatar(user: metadata.ownerId, dispalyName: metadata.ownerDisplayName, fileName: fileName, cell: cell, view: collectionView)
+ NCOperationQueue.shared.downloadAvatar(user: metadata.ownerId, dispalyName: metadata.ownerDisplayName, fileName: fileName, cell: cell, view: collectionView, cellImageView: cell.fileAvatarImageView)
}
}
@@ -420,11 +382,11 @@ extension NCSelect: UICollectionViewDataSource {
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
- return 1
+ return dataSource.numberOfSections()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
- let numberOfItems = dataSource.numberOfItems()
+ let numberOfItems = dataSource.numberOfItemsInSection(section)
emptyDataSet?.numberOfItemsInSection(numberOfItems, section: section)
return numberOfItems
}
@@ -439,16 +401,13 @@ extension NCSelect: UICollectionViewDataSource {
}
}
- var tableShare: tableShare?
var isShare = false
var isMounted = false
isShare = metadata.permissions.contains(NCGlobal.shared.permissionShared) && !metadataFolder.permissions.contains(NCGlobal.shared.permissionShared)
isMounted = metadata.permissions.contains(NCGlobal.shared.permissionMounted) && !metadataFolder.permissions.contains(NCGlobal.shared.permissionMounted)
- if dataSource.metadataShare[metadata.ocId] != nil {
- tableShare = dataSource.metadataShare[metadata.ocId]
- }
+ let tableShare = dataSource.metadatasForSection[indexPath.section].metadataShare[metadata.ocId]
// LAYOUT LIST
@@ -493,23 +452,16 @@ extension NCSelect: UICollectionViewDataSource {
} else {
cell.imageItem.image = NCBrandColor.cacheImages.folder
}
+ cell.imageItem.image = cell.imageItem.image?.colorizeFolder(metadata: metadata)
cell.labelInfo.text = CCUtility.dateDiff(metadata.date as Date)
- let lockServerUrl = CCUtility.stringAppendServerUrl(metadata.serverUrl, addFileName: metadata.fileName)!
- let tableDirectory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", activeAccount.account, lockServerUrl))
-
- // Local image: offline
- if tableDirectory != nil && tableDirectory!.offline {
- cell.imageLocal.image = NCBrandColor.cacheImages.offlineFlag
- }
-
} else {
cell.labelInfo.text = CCUtility.dateDiff(metadata.date as Date) + " · " + CCUtility.transformedSize(metadata.size)
// image local
- if dataSource.metadataOffLine.contains(metadata.ocId) {
+ if dataSource.metadatasForSection[indexPath.section].metadataOffLine.contains(metadata.ocId) {
cell.imageLocal.image = NCBrandColor.cacheImages.offlineFlag
} else if CCUtility.fileProviderStorageExists(metadata) {
cell.imageLocal.image = NCBrandColor.cacheImages.local
@@ -594,19 +546,12 @@ extension NCSelect: UICollectionViewDataSource {
} else {
cell.imageItem.image = NCBrandColor.cacheImages.folder
}
-
- let lockServerUrl = CCUtility.stringAppendServerUrl(metadata.serverUrl, addFileName: metadata.fileName)!
- let tableDirectory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", activeAccount.account, lockServerUrl))
-
- // Local image: offline
- if tableDirectory != nil && tableDirectory!.offline {
- cell.imageLocal.image = NCBrandColor.cacheImages.offlineFlag
- }
+ cell.imageItem.image = cell.imageItem.image?.colorizeFolder(metadata: metadata)
} else {
// image Local
- if dataSource.metadataOffLine.contains(metadata.ocId) {
+ if dataSource.metadatasForSection[indexPath.section].metadataOffLine.contains(metadata.ocId) {
cell.imageLocal.image = NCBrandColor.cacheImages.offlineFlag
} else if CCUtility.fileProviderStorageExists(metadata) {
cell.imageLocal.image = NCBrandColor.cacheImages.local
@@ -632,26 +577,118 @@ extension NCSelect: UICollectionViewDataSource {
return collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as! NCGridCell
}
+
+ func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
+
+ if kind == UICollectionView.elementKindSectionHeader {
+
+ if indexPath.section == 0 {
+
+ let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionHeaderMenu", for: indexPath) as! NCSectionHeaderMenu
+ let (_, heightHeaderRichWorkspace, heightHeaderSection) = getHeaderHeight(section: indexPath.section)
+
+ self.headerMenu = header
+
+ if layoutForView?.layout == NCGlobal.shared.layoutGrid {
+ header.setImageSwitchList()
+ header.buttonSwitch.accessibilityLabel = NSLocalizedString("_list_view_", comment: "")
+ } else {
+ header.setImageSwitchGrid()
+ header.buttonSwitch.accessibilityLabel = NSLocalizedString("_grid_view_", comment: "")
+ }
+
+ header.delegate = self
+
+ header.setButtonsCommand(heigt: 0)
+ header.setButtonsView(heigt: NCGlobal.shared.heightButtonsView)
+ header.setStatusButtonsView(enable: !dataSource.getMetadataSourceForAllSections().isEmpty)
+ header.setSortedTitle(layoutForView?.titleButtonHeader ?? "")
+
+ header.setRichWorkspaceHeight(heightHeaderRichWorkspace)
+ header.setRichWorkspaceText(richWorkspaceText)
+
+ header.setSectionHeight(heightHeaderSection)
+ if heightHeaderSection == 0 {
+ header.labelSection.text = ""
+ } else {
+ header.labelSection.text = self.dataSource.getSectionValue(indexPath: indexPath)
+ }
+ header.labelSection.textColor = NCBrandColor.shared.label
+
+ return header
+
+ } else {
+
+ let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionHeader", for: indexPath) as! NCSectionHeader
+
+ header.labelSection.text = self.dataSource.getSectionValue(indexPath: indexPath)
+ header.labelSection.textColor = NCBrandColor.shared.brandElement
+
+ return header
+ }
+
+ } else {
+
+ let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as! NCSectionFooter
+ let sections = dataSource.numberOfSections()
+ let section = indexPath.section
+
+ footer.setTitleLabel("")
+ footer.separatorIsHidden(true)
+
+ if sections == 1 || section == sections - 1 {
+ let info = dataSource.getFooterInformationAllMetadatas()
+ footer.setTitleLabel(directories: info.directories, files: info.files, size: info.size)
+ } else {
+ footer.separatorIsHidden(false)
+ }
+
+ return footer
+ }
+ }
}
extension NCSelect: UICollectionViewDelegateFlowLayout {
- func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
+ func getHeaderHeight(section:Int) -> (heightHeaderCommands: CGFloat, heightHeaderRichWorkspace: CGFloat, heightHeaderSection: CGFloat) {
- headerRichWorkspaceHeight = 0
+ var headerRichWorkspace: CGFloat = 0
if let richWorkspaceText = richWorkspaceText {
let trimmed = richWorkspaceText.trimmingCharacters(in: .whitespaces)
- if trimmed.count > 0 {
- headerRichWorkspaceHeight = UIScreen.main.bounds.size.height / 4
+ if trimmed.count > 0 && !isSearching {
+ headerRichWorkspace = UIScreen.main.bounds.size.height / 6
}
}
- return CGSize(width: collectionView.frame.width, height: headerHeight + headerRichWorkspaceHeight)
+ if isSearching || layoutForView?.layout == NCGlobal.shared.layoutGrid || dataSource.numberOfSections() > 1 {
+ if section == 0 {
+ return (NCGlobal.shared.heightButtonsView, headerRichWorkspace, NCGlobal.shared.heightSection)
+ } else {
+ return (0, 0, NCGlobal.shared.heightSection)
+ }
+ } else {
+ return (NCGlobal.shared.heightButtonsView, headerRichWorkspace, 0)
+ }
+ }
+
+ func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
+
+ let (heightHeaderCommands, heightHeaderRichWorkspace, heightHeaderSection) = getHeaderHeight(section: section)
+ let heightHeader = heightHeaderCommands + heightHeaderRichWorkspace + heightHeaderSection
+
+ return CGSize(width: collectionView.frame.width, height: heightHeader)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
- return CGSize(width: collectionView.frame.width, height: footerHeight)
+
+ let sections = dataSource.numberOfSections()
+
+ if section == sections - 1 {
+ return CGSize(width: collectionView.frame.width, height: NCGlobal.shared.endHeightFooter)
+ } else {
+ return CGSize(width: collectionView.frame.width, height: NCGlobal.shared.heightFooter)
+ }
}
}
@@ -666,8 +703,14 @@ extension NCSelect {
@objc func loadDatasource(withLoadFolder: Bool) {
var predicate: NSPredicate?
+ var groupByField = "name"
+
+ layoutForView = NCUtility.shared.getLayoutForView(key: layoutKey, serverUrl: serverUrl)
- layoutForView = NCUtility.shared.getLayoutForView(key: keyLayout, serverUrl: serverUrl)
+ // set GroupField for Grid
+ if layoutForView?.layout == NCGlobal.shared.layoutGrid {
+ groupByField = "classFile"
+ }
if includeDirectoryE2EEncryption {
@@ -686,8 +729,15 @@ extension NCSelect {
}
}
- let metadatasSource = NCManageDatabase.shared.getMetadatas(predicate: predicate!)
- self.dataSource = NCDataSource(metadatasSource: metadatasSource, sort: layoutForView?.sort, ascending: layoutForView?.ascending, directoryOnTop: layoutForView?.directoryOnTop, favoriteOnTop: true, filterLivePhoto: true)
+ let metadatas = NCManageDatabase.shared.getMetadatas(predicate: predicate!)
+ self.dataSource = NCDataSource(metadatas: metadatas,
+ account: activeAccount.account,
+ sort: layoutForView?.sort,
+ ascending: layoutForView?.ascending,
+ directoryOnTop: layoutForView?.directoryOnTop,
+ favoriteOnTop: true,
+ filterLivePhoto: true,
+ groupByField: groupByField)
if withLoadFolder {
loadFolder()
@@ -742,18 +792,30 @@ class NCSelectCommandView: UIView {
selectButton?.layer.cornerRadius = 15
selectButton?.layer.masksToBounds = true
selectButton?.setTitle(NSLocalizedString("_select_", comment: ""), for: .normal)
+ selectButton?.backgroundColor = NCBrandColor.shared.brand
+ selectButton?.setTitleColor(UIColor(white: 1, alpha: 0.3), for: .highlighted)
+ selectButton?.setTitleColor(NCBrandColor.shared.brandText, for: .normal)
createFolderButton?.layer.cornerRadius = 15
createFolderButton?.layer.masksToBounds = true
createFolderButton?.setTitle(NSLocalizedString("_create_folder_", comment: ""), for: .normal)
+ createFolderButton?.backgroundColor = NCBrandColor.shared.brand
+ createFolderButton?.setTitleColor(UIColor(white: 1, alpha: 0.3), for: .highlighted)
+ createFolderButton?.setTitleColor(NCBrandColor.shared.brandText, for: .normal)
copyButton?.layer.cornerRadius = 15
copyButton?.layer.masksToBounds = true
copyButton?.setTitle(NSLocalizedString("_copy_", comment: ""), for: .normal)
+ copyButton?.backgroundColor = NCBrandColor.shared.brand
+ copyButton?.setTitleColor(UIColor(white: 1, alpha: 0.3), for: .highlighted)
+ copyButton?.setTitleColor(NCBrandColor.shared.brandText, for: .normal)
moveButton?.layer.cornerRadius = 15
moveButton?.layer.masksToBounds = true
moveButton?.setTitle(NSLocalizedString("_move_", comment: ""), for: .normal)
+ moveButton?.backgroundColor = NCBrandColor.shared.brand
+ moveButton?.setTitleColor(UIColor(white: 1, alpha: 0.3), for: .highlighted)
+ moveButton?.setTitleColor(NCBrandColor.shared.brandText, for: .normal)
}
@IBAction func createFolderButtonPressed(_ sender: UIButton) {
diff --git a/iOSClient/Settings/CCAdvanced.m b/iOSClient/Settings/CCAdvanced.m
index 625e94c2d..f9d010122 100755
--- a/iOSClient/Settings/CCAdvanced.m
+++ b/iOSClient/Settings/CCAdvanced.m
@@ -84,34 +84,6 @@
[row.cellConfig setObject:NCBrandColor.shared.label forKey:@"textLabel.textColor"];
[section addFormRow:row];
- // Disable Local Cache After Upload
-
- section = [XLFormSectionDescriptor formSection];
- [form addFormSection:section];
- section.footerTitle = NSLocalizedString(@"_disableLocalCacheAfterUpload_footer_", nil);
-
- row = [XLFormRowDescriptor formRowDescriptorWithTag:@"disableLocalCacheAfterUpload" rowType:XLFormRowDescriptorTypeBooleanSwitch title:NSLocalizedString(@"_disableLocalCacheAfterUpload_", nil)];
- row.cellConfigAtConfigure[@"backgroundColor"] = NCBrandColor.shared.secondarySystemGroupedBackground;
- if ([CCUtility getDisableLocalCacheAfterUpload]) row.value = @"1";
- else row.value = @"0";
- [row.cellConfig setObject:[UIFont systemFontOfSize:15.0] forKey:@"textLabel.font"];
- [row.cellConfig setObject:NCBrandColor.shared.label forKey:@"textLabel.textColor"];
- [section addFormRow:row];
-
- // Automatic download image
-
- section = [XLFormSectionDescriptor formSection];
- [form addFormSection:section];
- section.footerTitle = NSLocalizedString(@"_automatic_Download_Image_footer_", nil);
-
- row = [XLFormRowDescriptor formRowDescriptorWithTag:@"automaticDownloadImage" rowType:XLFormRowDescriptorTypeBooleanSwitch title:NSLocalizedString(@"_automatic_Download_Image_", nil)];
- row.cellConfigAtConfigure[@"backgroundColor"] = NCBrandColor.shared.secondarySystemGroupedBackground;
- if ([CCUtility getAutomaticDownloadImage]) row.value = @"1";
- else row.value = @"0";
- [row.cellConfig setObject:[UIFont systemFontOfSize:15.0] forKey:@"textLabel.font"];
- [row.cellConfig setObject:NCBrandColor.shared.label forKey:@"textLabel.textColor"];
- [section addFormRow:row];
-
// Section : Files App --------------------------------------------------------------
if (![NCBrandOptions shared].disable_openin_file) {
@@ -200,7 +172,7 @@
NSInteger logLevel = [CCUtility getLogLevel];
BOOL isSimulatorOrTestFlight = [[NCUtility shared] isSimulatorOrTestFlight];
- NSString *versionNextcloudiOS = [NSString stringWithFormat:[NCBrandOptions shared].textCopyrightNextcloudiOS, NCUtility.shared.getVersionApp];
+ NSString *versionNextcloudiOS = [NSString stringWithFormat:[NCBrandOptions shared].textCopyrightNextcloudiOS, [[NCUtility shared] getVersionAppWithBuild:true]];
if (isSimulatorOrTestFlight) {
[[NCCommunicationCommon shared] writeLog:[NSString stringWithFormat:@"Clear log with level %lu %@ (Simulator / TestFlight)", (unsigned long)logLevel, versionNextcloudiOS]];
} else {
@@ -364,17 +336,7 @@
[CCUtility setRemovePhotoCameraRoll:[[rowDescriptor.value valueData] boolValue]];
}
-
- if ([rowDescriptor.tag isEqualToString:@"disableLocalCacheAfterUpload"]) {
-
- [CCUtility setDisableLocalCacheAfterUpload:[[rowDescriptor.value valueData] boolValue]];
- }
-
- if ([rowDescriptor.tag isEqualToString:@"automaticDownloadImage"]) {
-
- [CCUtility setAutomaticDownloadImage:[[rowDescriptor.value valueData] boolValue]];
- }
-
+
if ([rowDescriptor.tag isEqualToString:@"disablefilesapp"]) {
[CCUtility setDisableFilesApp:[[rowDescriptor.value valueData] boolValue]];
@@ -441,11 +403,8 @@
// Inizialized home
[[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:NCGlobal.shared.notificationCenterInitialize object:nil userInfo:nil];
- // Clear Media
- [appDelegate.activeMedia reloadDataSourceWithCompletion:^(NSArray *metadatas) { }];
-
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void) {
- [[NCUtility shared] stopActivityIndicator];
+ [[NCActivityIndicator shared] stop];
[self calculateSize];
});
}
@@ -457,7 +416,7 @@
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:NSLocalizedString(@"_want_delete_cache_", nil) preferredStyle:UIAlertControllerStyleActionSheet];
[alertController addAction: [UIAlertAction actionWithTitle:NSLocalizedString(@"_yes_", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
- [[NCUtility shared] startActivityIndicatorWithBackgroundView:nil blurEffect:true bottom:0 style: UIActivityIndicatorViewStyleWhiteLarge];
+ [[NCActivityIndicator shared] startActivityWithBackgroundView:nil style: UIActivityIndicatorViewStyleWhiteLarge];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void) {
[self clearCache];
});
@@ -528,7 +487,7 @@
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
- if (indexPath.section == 7 && indexPath.row == 2) {
+ if (indexPath.section == 5 && indexPath.row == 2) {
return 80;
} else {
return NCGlobal.shared.heightCellSettings;
diff --git a/iOSClient/Settings/NCEndToEndInitialize.swift b/iOSClient/Settings/NCEndToEndInitialize.swift
index 1337ad354..737d68097 100644
--- a/iOSClient/Settings/NCEndToEndInitialize.swift
+++ b/iOSClient/Settings/NCEndToEndInitialize.swift
@@ -196,7 +196,7 @@ class NCEndToEndInitialize: NSObject {
alertController.addAction(cancel)
alertController.addTextField { textField -> Void in
passphraseTextField = textField
- passphraseTextField?.placeholder = "Enter passphrase (12 words)"
+ passphraseTextField?.placeholder = NSLocalizedString("_enter_passphrase_", comment: "")
}
self.appDelegate.window?.rootViewController?.present(alertController, animated: true)
@@ -210,8 +210,8 @@ class NCEndToEndInitialize: NSObject {
case NCGlobal.shared.errorResourceNotFound:
// message
- let e2ePassphrase = NYMnemonic.generateString(128, language: "english")
- let message = "\n" + NSLocalizedString("_e2e_settings_view_passphrase_", comment: "") + "\n\n" + e2ePassphrase!
+ guard let e2ePassphrase = NYMnemonic.generateString(128, language: "english") else { return }
+ let message = "\n" + NSLocalizedString("_e2e_settings_view_passphrase_", comment: "") + "\n\n" + e2ePassphrase
let alertController = UIAlertController(title: NSLocalizedString("_e2e_settings_title_", comment: ""), message: NSLocalizedString(message, comment: ""), preferredStyle: .alert)
@@ -220,9 +220,7 @@ class NCEndToEndInitialize: NSObject {
var privateKeyString: NSString?
guard let privateKeyChiper = NCEndToEndEncryption.sharedManager().encryptPrivateKey(self.appDelegate.userId, directory: CCUtility.getDirectoryUserData(), passphrase: e2ePassphrase, privateKey: &privateKeyString) else {
-
NCContentPresenter.shared.messageNotification("E2E privateKey", description: "Serious internal error to create PrivateKey chiper", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode, priority: .max)
-
return
}
diff --git a/iOSClient/Settings/NCManageAutoUploadFileName.swift b/iOSClient/Settings/NCManageAutoUploadFileName.swift
index 3f4774c7f..a42f2191c 100644
--- a/iOSClient/Settings/NCManageAutoUploadFileName.swift
+++ b/iOSClient/Settings/NCManageAutoUploadFileName.swift
@@ -22,6 +22,7 @@
//
import UIKit
+import Photos
class NCManageAutoUploadFileName: XLFormViewController {
diff --git a/iOSClient/Settings/NCManageEndToEndEncryption.m b/iOSClient/Settings/NCManageEndToEndEncryption.m
index 0d22adb5e..147671409 100644
--- a/iOSClient/Settings/NCManageEndToEndEncryption.m
+++ b/iOSClient/Settings/NCManageEndToEndEncryption.m
@@ -345,8 +345,13 @@
NSString *message = [NSString stringWithFormat:@"\n%@\n\n\n%@", NSLocalizedString(@"_e2e_settings_the_passphrase_is_", nil), e2ePassphrase];
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"_info_", nil) message:message preferredStyle:UIAlertControllerStyleAlert];
- UIAlertAction *okAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"OK action") style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { }];
+ UIAlertAction *okAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"_ok_", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { }];
+ UIAlertAction *copyPassphrase = [UIAlertAction actionWithTitle:NSLocalizedString(@"_copy_passphrase_", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
+ UIPasteboard.generalPasteboard.string = e2ePassphrase;
+ }];
+
[alertController addAction:okAction];
+ [alertController addAction:copyPassphrase];
[self presentViewController:alertController animated:YES completion:nil];
} else if ([passcodeType isEqualToString:@"removeLocallyEncryption"]) {
diff --git a/iOSClient/Settings/NCSettings.m b/iOSClient/Settings/NCSettings.m
index 6f9ab8b11..1f8a6ef4d 100644
--- a/iOSClient/Settings/NCSettings.m
+++ b/iOSClient/Settings/NCSettings.m
@@ -414,14 +414,14 @@
}
break;
case 4: {
-
+
NSString *versionServer = [[NCManageDatabase shared] getCapabilitiesServerStringWithAccount:appDelegate.account elements:NCElementsJSON.shared.capabilitiesVersionString];
NSString *themingName = [[NCManageDatabase shared] getCapabilitiesServerStringWithAccount:appDelegate.account elements:NCElementsJSON.shared.capabilitiesThemingName];
NSString *themingSlogan = [[NCManageDatabase shared] getCapabilitiesServerStringWithAccount:appDelegate.account elements:NCElementsJSON.shared.capabilitiesThemingSlogan];
NSString *versionNextcloud = [NSString stringWithFormat:[NCBrandOptions shared].textCopyrightNextcloudServer, versionServer];
- NSString *versionNextcloudiOS = [NSString stringWithFormat:[NCBrandOptions shared].textCopyrightNextcloudiOS, NCUtility.shared.getVersionApp];
-
+ NSString *versionNextcloudiOS = [NSString stringWithFormat:[NCBrandOptions shared].textCopyrightNextcloudiOS, [[NCUtility shared] getVersionAppWithBuild:true]];
+
NSString *nameSlogan = [NSString stringWithFormat:@"%@ - %@", themingName, themingSlogan];
sectionName = [NSString stringWithFormat:@"\n%@\n\n%@\n%@", versionNextcloudiOS, versionNextcloud, nameSlogan];
diff --git a/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.swift b/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.swift
index ffad1f97e..4f72a90c8 100644
--- a/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.swift
+++ b/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.swift
@@ -37,23 +37,21 @@ class NCShareAdvancePermissionFooter: UIView {
self.delegate = delegate
backgroundColor = .clear
- buttonCancel.backgroundColor = .clear
- buttonCancel.addTarget(self, action: #selector(cancelClicked), for: .touchUpInside)
buttonCancel.setTitle(NSLocalizedString("_cancel_", comment: ""), for: .normal)
-
buttonCancel.layer.cornerRadius = 25
buttonCancel.layer.masksToBounds = true
buttonCancel.layer.borderWidth = 1
- buttonCancel.backgroundColor = NCBrandColor.shared.secondarySystemBackground
buttonCancel.layer.borderColor = NCBrandColor.shared.systemGray.cgColor
- buttonCancel.setTitleColor(NCBrandColor.shared.label.withAlphaComponent(0.3), for: .highlighted)
+ buttonCancel.backgroundColor = NCBrandColor.shared.secondarySystemBackground
+ buttonCancel.addTarget(self, action: #selector(cancelClicked), for: .touchUpInside)
+ buttonCancel.setTitleColor(.black, for: .normal)
buttonNext.setTitle(NSLocalizedString(delegate?.isNewShare == true ? "_share_" : "_save_", comment: ""), for: .normal)
buttonNext.layer.cornerRadius = 25
buttonNext.layer.masksToBounds = true
buttonNext.backgroundColor = NCBrandColor.shared.brand
buttonNext.addTarget(self, action: #selector(nextClicked), for: .touchUpInside)
- buttonNext.setTitleColor(UIColor(white: 1, alpha: 0.3), for: .highlighted)
+ buttonNext.setTitleColor(NCBrandColor.shared.brandText, for: .normal)
}
@objc func cancelClicked() {
diff --git a/iOSClient/Share/NCShare+NCCellDelegate.swift b/iOSClient/Share/NCShare+NCCellDelegate.swift
index 78dfd1074..7fa0c1cbc 100644
--- a/iOSClient/Share/NCShare+NCCellDelegate.swift
+++ b/iOSClient/Share/NCShare+NCCellDelegate.swift
@@ -30,7 +30,7 @@ extension NCShare: NCShareLinkCellDelegate, NCShareUserCellDelegate {
guard let metadata = self.metadata, let appDelegate = appDelegate else { return }
let serverUrlFileName = metadata.serverUrl + "/" + metadata.fileName
- NCNetworking.shared.readFile(serverUrlFileName: serverUrlFileName, account: metadata.account) { _, metadata, errorCode, errorDescription in
+ NCNetworking.shared.readFile(serverUrlFileName: serverUrlFileName) { _, metadata, errorCode, errorDescription in
if errorCode == 0, let metadata = metadata {
let internalLink = appDelegate.urlBase + "/index.php/f/" + metadata.fileId
NCShareCommon.shared.copyLink(link: internalLink, viewController: self, sender: sender)
diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift
index fdad3c3f0..e9712cfe9 100644
--- a/iOSClient/Share/NCShare.swift
+++ b/iOSClient/Share/NCShare.swift
@@ -92,11 +92,6 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent
let isVisible = (self.navigationController?.topViewController as? NCSharePaging)?.indexPage == .sharing
networking?.readShare(showLoadingIndicator: isVisible)
}
-
- // changeTheming
- NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil)
-
- changeTheming()
}
func makeNewLinkShare() {
@@ -177,10 +172,6 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent
self.showProfileMenu(userId: metadata.ownerId)
}
- @objc func changeTheming() {
- tableView.reloadData()
- }
-
// MARK: -
@objc func reloadData() {
@@ -194,6 +185,7 @@ class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent
@IBAction func searchFieldDidEndOnExit(textField: UITextField) {
guard let searchString = textField.text, !searchString.isEmpty else { return }
+ if searchString.contains("@"), !NCUtility.shared.isValidEmail(searchString) { return }
networking?.getSharees(searchString: searchString)
}
@@ -338,7 +330,7 @@ extension NCShare: UITableViewDataSource {
cell.delegate = self
cell.setupCellUI(userId: appDelegate.userId)
let fileName = appDelegate.userBaseUrl + "-" + tableShare.shareWith + ".png"
- NCOperationQueue.shared.downloadAvatar(user: tableShare.shareWith, dispalyName: tableShare.shareWithDisplayname, fileName: fileName, cell: cell, view: tableView)
+ NCOperationQueue.shared.downloadAvatar(user: tableShare.shareWith, dispalyName: tableShare.shareWithDisplayname, fileName: fileName, cell: cell, view: tableView, cellImageView: cell.fileAvatarImageView)
return cell
}
}
diff --git a/iOSClient/Share/NCShareCommentsCell.swift b/iOSClient/Share/NCShareCommentsCell.swift
index 77335907b..ed0ddbced 100644
--- a/iOSClient/Share/NCShareCommentsCell.swift
+++ b/iOSClient/Share/NCShareCommentsCell.swift
@@ -37,17 +37,12 @@ class NCShareCommentsCell: UITableViewCell, NCCellProtocol {
var tableComments: tableComments?
weak var delegate: NCShareCommentsCellDelegate?
- var filePreviewImageView: UIImageView? {
- return nil
- }
var fileAvatarImageView: UIImageView? {
return imageItem
}
- var fileObjectId: String? {
- return nil
- }
var fileUser: String? {
- return tableComments?.actorId
+ get { return tableComments?.actorId }
+ set {}
}
override func awakeFromNib() {
diff --git a/iOSClient/Share/NCShareNetworking.swift b/iOSClient/Share/NCShareNetworking.swift
index cb65673c2..80f8f4899 100644
--- a/iOSClient/Share/NCShareNetworking.swift
+++ b/iOSClient/Share/NCShareNetworking.swift
@@ -43,14 +43,14 @@ class NCShareNetworking: NSObject {
func readShare(showLoadingIndicator: Bool) {
if showLoadingIndicator {
- NCUtility.shared.startActivityIndicator(backgroundView: view, blurEffect: false)
+ NCActivityIndicator.shared.start(backgroundView: view)
}
let filenamePath = CCUtility.returnFileNamePath(fromFileName: metadata.fileName, serverUrl: metadata.serverUrl, urlBase: urlBase, account: metadata.account)!
let parameter = NCCShareParameter(path: filenamePath)
NCCommunication.shared.readShares(parameters: parameter) { account, shares, errorCode, errorDescription in
if showLoadingIndicator {
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
}
if errorCode == 0, let shares = shares {
@@ -71,11 +71,11 @@ class NCShareNetworking: NSObject {
// Library update needed:
// https://github.com/nextcloud/ios-communication-library/pull/104
- NCUtility.shared.startActivityIndicator(backgroundView: view, blurEffect: false)
+ NCActivityIndicator.shared.start(backgroundView: view)
let filenamePath = CCUtility.returnFileNamePath(fromFileName: metadata.fileName, serverUrl: metadata.serverUrl, urlBase: urlBase, account: metadata.account)!
NCCommunication.shared.createShare(path: filenamePath, shareType: option.shareType, shareWith: option.shareWith, password: option.password, permissions: option.permissions) { (account, share, errorCode, errorDescription) in
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
if errorCode == 0, let share = share {
option.idShare = share.idShare
NCManageDatabase.shared.addShare(urlBase: self.urlBase, account: self.metadata.account, shares: [share])
@@ -91,9 +91,9 @@ class NCShareNetworking: NSObject {
}
func unShare(idShare: Int) {
- NCUtility.shared.startActivityIndicator(backgroundView: view, blurEffect: false)
+ NCActivityIndicator.shared.start(backgroundView: view)
NCCommunication.shared.deleteShare(idShare: idShare) { account, errorCode, errorDescription in
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
if errorCode == 0 {
NCManageDatabase.shared.deleteTableShare(account: account, idShare: idShare)
self.delegate?.unShareCompleted()
@@ -104,9 +104,9 @@ class NCShareNetworking: NSObject {
}
func updateShare(option: NCTableShareable) {
- NCUtility.shared.startActivityIndicator(backgroundView: view, blurEffect: false)
+ NCActivityIndicator.shared.start(backgroundView: view)
NCCommunication.shared.updateShare(idShare: option.idShare, password: option.password, expireDate: option.expDateString, permissions: option.permissions, note: option.note, label: option.label, hideDownload: option.hideDownload) { account, share, errorCode, errorDescription in
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
if errorCode == 0, let share = share {
NCManageDatabase.shared.addShare(urlBase: self.urlBase, account: self.metadata.account, shares: [share])
self.appDelegate.shares = NCManageDatabase.shared.getTableShares(account: self.metadata.account)
@@ -119,9 +119,9 @@ class NCShareNetworking: NSObject {
}
func getSharees(searchString: String) {
- NCUtility.shared.startActivityIndicator(backgroundView: view, blurEffect: false)
+ NCActivityIndicator.shared.start(backgroundView: view)
NCCommunication.shared.searchSharees(search: searchString) { _, sharees, errorCode, errorDescription in
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
if errorCode == 0 {
self.delegate?.getSharees(sharees: sharees)
} else {
diff --git a/iOSClient/Share/NCSharePaging.swift b/iOSClient/Share/NCSharePaging.swift
index c86f79b4b..5e21aba65 100644
--- a/iOSClient/Share/NCSharePaging.swift
+++ b/iOSClient/Share/NCSharePaging.swift
@@ -95,9 +95,11 @@ class NCSharePaging: UIViewController {
let pagingIndexItem = self.pagingViewController(pagingViewController, pagingItemAt: indexPage.rawValue) as? PagingIndexItem
self.title = pagingIndexItem?.title
- NotificationCenter.default.addObserver(self, selector: #selector(self.changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.orientationDidChange), name: UIDevice.orientationDidChangeNotification, object: nil)
- changeTheming()
+
+ pagingViewController.indicatorColor = NCBrandColor.shared.brandElement
+ (pagingViewController.view as? NCSharePagingView)?.setupConstraints()
+ pagingViewController.reloadMenu()
}
func setupCapabilities() {
@@ -140,7 +142,7 @@ class NCSharePaging: UIViewController {
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl])
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": metadata.serverUrl])
}
deinit {
@@ -158,12 +160,6 @@ class NCSharePaging: UIViewController {
currentVC?.textField?.resignFirstResponder()
}
- @objc func changeTheming() {
- pagingViewController.indicatorColor = NCBrandColor.shared.brandElement
- (pagingViewController.view as? NCSharePagingView)?.setupConstraints()
- pagingViewController.reloadMenu()
- }
-
// MARK: - Keyboard & TextField
@objc func keyboardWillShow(notification: Notification) {
let frameEndUserInfoKey = UIResponder.keyboardFrameEndUserInfoKey
@@ -319,13 +315,14 @@ class NCSharePagingView: PagingView {
if metadata.directory {
let image = 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(metadata: metadata)
+ headerView.path.text = NCUtilityFileSystem.shared.getPath(metadata: metadata, withFileName: true)
headerView.path.textColor = NCBrandColor.shared.label
headerView.path.trailingBuffer = headerView.path.frame.width
if metadata.favorite {
diff --git a/iOSClient/Share/NCShareUserCell.swift b/iOSClient/Share/NCShareUserCell.swift
index 97ef503b2..c9eb1957d 100644
--- a/iOSClient/Share/NCShareUserCell.swift
+++ b/iOSClient/Share/NCShareUserCell.swift
@@ -38,10 +38,13 @@ class NCShareUserCell: UITableViewCell, NCCellProtocol {
var tableShare: tableShare?
weak var delegate: NCShareUserCellDelegate?
- var fileAvatarImageView: UIImageView? { return imageItem }
- var fileObjectId: String? { return nil }
- var filePreviewImageView: UIImageView? { return nil }
- var fileUser: String? { return tableShare?.shareWith }
+ var fileAvatarImageView: UIImageView? {
+ return imageItem
+ }
+ var fileUser: String? {
+ get { return tableShare?.shareWith }
+ set {}
+ }
func setupCellUI(userId: String) {
guard let tableShare = tableShare else {
@@ -130,16 +133,12 @@ class NCSearchUserDropDownCell: DropDownCell, NCCellProtocol {
private var user: String = ""
- var fileAvatarImageView: UIImageView? { return imageItem }
- var fileObjectId: String? { return nil }
- var filePreviewImageView: UIImageView? { return nil }
+ var fileAvatarImageView: UIImageView? {
+ return imageItem
+ }
var fileUser: String? {
- get {
- return user
- }
- set {
- user = newValue ?? ""
- }
+ get { return user }
+ set { user = newValue ?? "" }
}
func setupCell(sharee: NCCommunicationSharee, baseUrl: NCUserBaseUrl) {
@@ -179,6 +178,5 @@ class NCSearchUserDropDownCell: DropDownCell, NCCellProtocol {
}
}
}
-
}
}
diff --git a/iOSClient/Shares/NCShares.swift b/iOSClient/Shares/NCShares.swift
index c6a2d2ac9..98bcc4a4c 100644
--- a/iOSClient/Shares/NCShares.swift
+++ b/iOSClient/Shares/NCShares.swift
@@ -34,6 +34,9 @@ class NCShares: NCCollectionViewCommon {
titleCurrentFolder = NSLocalizedString("_list_shares_", comment: "")
layoutKey = NCGlobal.shared.layoutViewShares
enableSearchBar = false
+ headerMenuButtonsCommand = false
+ headerMenuButtonsView = true
+ headerRichWorkspaceDisable = true
emptyImage = UIImage(named: "share")?.image(color: .gray, size: UIScreen.main.bounds.width)
emptyTitle = "_list_shares_no_files_"
emptyDescription = "_tutorial_list_shares_view_"
@@ -41,21 +44,30 @@ class NCShares: NCCollectionViewCommon {
// MARK: - DataSource + NC Endpoint
- override func reloadDataSource() {
+ override func reloadDataSource(forced: Bool = true) {
super.reloadDataSource()
DispatchQueue.global().async {
- self.metadatasSource.removeAll()
let sharess = NCManageDatabase.shared.getTableShares(account: self.appDelegate.account)
+ var metadatas: [tableMetadata] = []
for share in sharess {
if let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", self.appDelegate.account, share.serverUrl, share.fileName)) {
- if !(self.metadatasSource.contains { $0.ocId == metadata.ocId }) {
- self.metadatasSource.append(metadata)
+ if !(metadatas.contains { $0.ocId == metadata.ocId }) {
+ metadatas.append(metadata)
}
}
}
- self.dataSource = NCDataSource(metadatasSource: self.metadatasSource, sort: self.layoutForView?.sort, ascending: self.layoutForView?.ascending, directoryOnTop: self.layoutForView?.directoryOnTop, favoriteOnTop: true, filterLivePhoto: true)
+ self.dataSource = NCDataSource(metadatas: metadatas,
+ account: self.appDelegate.account,
+ sort: self.layoutForView?.sort,
+ ascending: self.layoutForView?.ascending,
+ directoryOnTop: self.layoutForView?.directoryOnTop,
+ favoriteOnTop: true,
+ filterLivePhoto: true,
+ groupByField: self.groupByField,
+ providers: self.providers,
+ searchResults: self.searchResults)
DispatchQueue.main.async {
self.refreshControl.endRefreshing()
@@ -67,11 +79,6 @@ class NCShares: NCCollectionViewCommon {
override func reloadDataSourceNetwork(forced: Bool = false) {
super.reloadDataSourceNetwork(forced: forced)
- if isSearching {
- networkSearch()
- return
- }
-
isReloadDataSourceNetworkInProgress = true
collectionView?.reloadData()
diff --git a/iOSClient/Supporting Files/af.lproj/Localizable.strings b/iOSClient/Supporting Files/af.lproj/Localizable.strings
index 38666ba61..3df84dd92 100644
--- a/iOSClient/Supporting Files/af.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/af.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/kk.lproj/InfoPlist.strings b/iOSClient/Supporting Files/an.lproj/InfoPlist.strings
index b58e1cf05..b58e1cf05 100644
--- a/iOSClient/Supporting Files/kk.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/an.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/kk.lproj/Localizable.strings b/iOSClient/Supporting Files/an.lproj/Localizable.strings
index d6feb161f..d3fd64216 100644
--- a/iOSClient/Supporting Files/kk.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/an.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ar.lproj/Localizable.strings b/iOSClient/Supporting Files/ar.lproj/Localizable.strings
index 70d6407c0..3a559f14b 100644
--- a/iOSClient/Supporting Files/ar.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/ar.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ast.lproj/Localizable.strings b/iOSClient/Supporting Files/ast.lproj/Localizable.strings
index 96059f72a..6d656defb 100644
--- a/iOSClient/Supporting Files/ast.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/ast.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/az.lproj/Localizable.strings b/iOSClient/Supporting Files/az.lproj/Localizable.strings
index dd3846eeb..ddde73b03 100644
--- a/iOSClient/Supporting Files/az.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/az.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/be.lproj/Localizable.strings b/iOSClient/Supporting Files/be.lproj/Localizable.strings
index 0c89fcb1e..87aa81c67 100644
--- a/iOSClient/Supporting Files/be.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/be.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/bg_BG.lproj/Localizable.strings b/iOSClient/Supporting Files/bg_BG.lproj/Localizable.strings
index c1f1efe32..3486f7163 100644
--- a/iOSClient/Supporting Files/bg_BG.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/bg_BG.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/bn_BD.lproj/Localizable.strings b/iOSClient/Supporting Files/bn_BD.lproj/Localizable.strings
index 58546a3cc..b1e15b787 100644
--- a/iOSClient/Supporting Files/bn_BD.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/bn_BD.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/br.lproj/Localizable.strings b/iOSClient/Supporting Files/br.lproj/Localizable.strings
index ed158d553..7a5af3733 100644
--- a/iOSClient/Supporting Files/br.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/br.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/bs.lproj/Localizable.strings b/iOSClient/Supporting Files/bs.lproj/Localizable.strings
index 09e98ca41..950c7817f 100644
--- a/iOSClient/Supporting Files/bs.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/bs.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ca.lproj/Localizable.strings b/iOSClient/Supporting Files/ca.lproj/Localizable.strings
index 4678b2456..0fbbf7ec2 100644
--- a/iOSClient/Supporting Files/ca.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/ca.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings b/iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings
index a345c34e5..46376b697 100644
--- a/iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/cy_GB.lproj/Localizable.strings b/iOSClient/Supporting Files/cy_GB.lproj/Localizable.strings
index 479794262..9e3321858 100644
--- a/iOSClient/Supporting Files/cy_GB.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/cy_GB.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/da.lproj/Localizable.strings b/iOSClient/Supporting Files/da.lproj/Localizable.strings
index 4715b9ce4..066045454 100644
--- a/iOSClient/Supporting Files/da.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/da.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/de.lproj/Localizable.strings b/iOSClient/Supporting Files/de.lproj/Localizable.strings
index 849fecc6b..debfa5a5a 100644
--- a/iOSClient/Supporting Files/de.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/de.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/el.lproj/Localizable.strings b/iOSClient/Supporting Files/el.lproj/Localizable.strings
index 3d34ca6c3..d1475e4ef 100644
--- a/iOSClient/Supporting Files/el.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/el.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/en-GB.lproj/Localizable.strings b/iOSClient/Supporting Files/en-GB.lproj/Localizable.strings
index e8e417484..c7354cff0 100644
--- a/iOSClient/Supporting Files/en-GB.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/en-GB.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/en.lproj/Localizable.strings b/iOSClient/Supporting Files/en.lproj/Localizable.strings
index cb7ccaeae..f84dd74bb 100644
--- a/iOSClient/Supporting Files/en.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/en.lproj/Localizable.strings
@@ -20,6 +20,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
+"_itunes_" = "iTunes";
"_cancel_" = "Cancel";
"_tap_to_cancel_" = "Tap to cancel";
"_cancel_request_" = "Do you want to cancel?";
@@ -114,6 +115,8 @@
"_comments_" = "Comments";
"_sharing_" = "Sharing";
"_details_" = "Details";
+"_sub_details_" = "Subscription Details";
+"_subscriptions_" = "Subscriptions";
"_dark_mode_" = "Dark mode";
"_dark_mode_detect_" = "Detect iOS dark mode";
"_screen_" = "Screen";
@@ -146,6 +149,10 @@
"_recent_" = "Recent";
"_view_in_folder_" = "View in folder";
"_leave_share_" = "Leave this share";
+"_premium_" = "Premium";
+"_professional_" = "Professional";
+"_current_" = "Current";
+"_buy_" = "Buy";
/* MARK: Files lock */
@@ -389,7 +396,9 @@
"_show_hidden_files_" = "Show hidden files";
"_format_compatibility_" = "Most Compatible";
"_format_compatibility_footer_" = "\"Most compatible\" will save photos as JPEG, if possible.";
+"_terms_" = "Terms of Service";
"_privacy_" = "Privacy";
+"_privacy_policy_" = "Privacy Policy";
"_privacy_footer_" = "Nextcloud iOS uses a service for the analysis of a crash. Your personal information is not sent with the report. If you want disable it, please change the setting \"Disable crash reporter\" to ON";
"_crashservice_title_" = "Disable crash reporter";
"_crashservice_alert_" = "This option requires a restart of the app to take effect";
@@ -667,10 +676,10 @@
"_untitled_txt_" = "Untitled.txt";
"_text_upload_title_" = "Upload text file";
"_e2e_settings_title_" = "Encryption";
-"_e2e_settings_" = "End-to-end encryption";
-"_e2e_settings_start_" = "Start end-to-end encryption";
-"_e2e_settings_not_available_" = "End-to-end encryption not available";
-"_e2e_settings_activated_" = "End-to-end encryption activated";
+"_e2e_settings_" = "End-to-End encryption";
+"_e2e_settings_start_" = "Start End-to-End encryption";
+"_e2e_settings_not_available_" = "End-to-End encryption not available";
+"_e2e_settings_activated_" = "End-to-End encryption activated";
"_e2e_settings_view_passphrase_" = "All 12 words together make a very strong password, letting only you view and make use of your encrypted files. Please write it down and keep it somewhere safe.";
"_e2e_settings_read_passphrase_" = "Read passphrase";
"_e2e_settings_lock_not_active_" = "Lock not active, go back to \"Settings\" and activate it";
@@ -681,7 +690,7 @@
"_e2e_settings_remove_message_" = "Confirm removal of encryption along with the passphrase.";
"_e2e_set_folder_encrypted_" = "Encrypt";
"_e2e_remove_folder_encrypted_" = "Decrypt";
-"_e2e_goto_settings_for_enable_" = "This is an encrypted directory, go to \"Settings\" and enable end-to-end encryption";
+"_e2e_goto_settings_for_enable_" = "This is an encrypted directory, go to \"Settings\" and enable End-to-End encryption";
"_e2e_delete_folder_not_permitted_" = "Deletion of the directory marked as \"encrypted\" is not allowed";
"_e2e_error_encode_metadata_" = "Serious internal error in encoding metadata";
"_e2e_error_decode_metadata_" = "Serious internal error in decoding metadata";
@@ -691,7 +700,7 @@
"_e2e_error_send_metadata_" = "Could not send metadata";
"_e2e_error_delete_metadata_" = "Could not delete metadata";
"_e2e_error_get_metadata_" = "Could not fetch metadata";
-"_e2e_error_not_enabled_" = "Serious internal error. End-to-end encryption not enabled";
+"_e2e_error_not_enabled_" = "Serious internal error. End-to-End encryption not enabled";
"_e2e_error_record_not_found_" = "Serious internal error. Records not found";
"_e2e_error_unlock_" = "Could not unlock folder";
"_e2e_error_lock_" = "Could not lock folder";
@@ -730,6 +739,7 @@
"_trash_view_" = "Deleted files";
"_trash_restore_all_" = "Restore all files";
"_trash_delete_all_" = "Empty trash";
+"_trash_delete_permanently_" = "Delete permanently";
"_trash_delete_all_description_" = "Do you want to empty the trash bin?";
"_trash_no_trash_" = "No files deleted";
"_trash_no_trash_description_" = "You can restore deleted files from here";
@@ -786,7 +796,7 @@
"_server_response_error_" = "Server response content error";
"_no_nextcloud_found_" = "Nextcloud server not found";
"_error_decompressing_" = "Error during decompressing. Unknown compression method or the file is corrupt";
-"_error_json_decoding_" = "Serious internal error in decoding metadata (The data couldn’t be read because it isn’t in the correct format.)";
+"_error_json_decoding_" = "Serious internal error in decoding metadata (The data couldn't be read because it isn't in the correct format.)";
"_error_check_remote_user_" = "Server responded with error, password re-entry is required";
"_request_entity_too_large_" = "The file is too large";
"_not_possible_download_" = "It is not possible to download the file";
@@ -801,7 +811,7 @@
"_internal_generic_error_" = "internal error";
"_editor_unknown_" = "Failed to open file: Editor is unknown";
"_err_file_not_found_" = "File not found, removed";
-"_err_e2ee_app_version_" = "The app version of end-to-end encryption is not compatible with the server, please update your server";
+"_err_e2ee_app_version_" = "The app version of End-to-End encryption is not compatible with the server, please update your server";
"_err_permission_microphone_" = "Please allow Microphone usage from Settings";
"_err_permission_photolibrary_" = "Please allow Photos from Settings";
"_err_permission_locationmanager_" = "Please allow Location - Always from Settings";
@@ -836,6 +846,10 @@
"_1_month_" = "1 month";
"_1_week_" = "1 week";
"_1_day_" = "1 day";
+"_monthly_" = "Monthly";
+"_yearly_" = "Yearly";
+"_weekly_" = "Weekly";
+"_day_" = "Day";
"_used_space_" = "Used space";
"_open_in_onlyoffice_" = "Open in ONLYOFFICE";
"_open_in_collabora_" = "Open with Collabora Online";
@@ -854,6 +868,18 @@
"_privacy_screen_" = "Splash screen when app inactive";
"_saving_" = "Saving …";
"_video_not_streamed_" = "The server does not allow video streaming, do you want to download it?";
+"_scan_" = "Scan";
+"_in_" = "in";
+"_enter_passphrase_" = "Enter passphrase (12 words)";
+"_show_more_results_" = "Show more results";
+"_waiting_for_" = "Waiting for:";
+"_reachable_wifi_" = "network reachable via Wi-Fi or cable";
+"_ITMS-90076_" = "Due to a change in the Nextcloud application identifier, the settings and password for accessing your cloud are reset, so please re-enter your account data and check your Settings. We are sorry about that.";
+"_password_not_present_" = "Please re-insert your credentials.";
+"_copy_passphrase_" = "Copy passphrase";
+"_select_color_" = "Select the color";
+"_change_color_" = "Change color";
+
// Video
"_select_trace_" = "Select the trace";
"_video_processing_" = "Video processing";
@@ -872,9 +898,13 @@
"_subtitle_not_found_" = "Subtitle not found";
"_disable_" = "Disable";
"_subtitle_not_dowloaded_" = "There are subtitles not downloaded locally";
+"_user_" = "User";
// Tip
"_tip_pdf_thumbnails_" = "Swipe left from the right edge of the screen to show the thumbnails.";
+"_tip_accountrequest_" = "Touch here to change account or to add a new one";
+"_tip_addcopyimage_" = "Long press to paste a copied image";
+"_tip_open_mediadetail_" = "Swipe up to show the details";
// MARK: Accessibility
@@ -889,3 +919,20 @@
"_off_" = "Off";
"_grid_view_" = "Show grid view";
"_list_view_" = "Show list view";
+
+// MARK: Plan customer
+"_leave_plan_title" = "We're sorry to see you go";
+"_leave_plan_description" = "You'll no longer have access to:";
+"_current_plan_" = "Current Plan";
+"_billing_plan_" = "Billing Plan";
+"_keep_plan_" = "Keep Plan";
+"_leave_plan_" = "Leave Plan";
+"_change_plan_" = "Change Plan";
+"_manage_plan_" = "Manage Plan";
+"_purchase_plan_" = "Purchase Plan";
+"_restore_plan_" = "Restore Purchased Plan";
+"_purchase_plan_description_" = "Purchases have been restored";
+"_choose_plan_" = "You should choose a plan in order to purchase it.";
+"_already_plan_" = "The selected plan has already been bought.";
+"_change_billing_" = "Change Billing";
+"_payment_method_" = "Payment Method";
diff --git a/iOSClient/Supporting Files/eo.lproj/Localizable.strings b/iOSClient/Supporting Files/eo.lproj/Localizable.strings
index 0999863cc..3ff2371f2 100644
--- a/iOSClient/Supporting Files/eo.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/eo.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/es-419.lproj/Localizable.strings b/iOSClient/Supporting Files/es-419.lproj/Localizable.strings
index f0d8dd7af..d485e916b 100644
--- a/iOSClient/Supporting Files/es-419.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/es-419.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/es-AR.lproj/Localizable.strings b/iOSClient/Supporting Files/es-AR.lproj/Localizable.strings
index e9222dd44..a8e9da977 100644
--- a/iOSClient/Supporting Files/es-AR.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/es-AR.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/es-CL.lproj/Localizable.strings b/iOSClient/Supporting Files/es-CL.lproj/Localizable.strings
index 7a52551e5..78b44a6a7 100644
--- a/iOSClient/Supporting Files/es-CL.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/es-CL.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/es-CO.lproj/Localizable.strings b/iOSClient/Supporting Files/es-CO.lproj/Localizable.strings
index fd097fa4f..10520162e 100644
--- a/iOSClient/Supporting Files/es-CO.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/es-CO.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/es-CR.lproj/Localizable.strings b/iOSClient/Supporting Files/es-CR.lproj/Localizable.strings
index 1f9cfde75..2327a8895 100644
--- a/iOSClient/Supporting Files/es-CR.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/es-CR.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/es-DO.lproj/Localizable.strings b/iOSClient/Supporting Files/es-DO.lproj/Localizable.strings
index fcff56a2c..6d6faba70 100644
--- a/iOSClient/Supporting Files/es-DO.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/es-DO.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/es-EC.lproj/Localizable.strings b/iOSClient/Supporting Files/es-EC.lproj/Localizable.strings
index 6e787565a..0fce9b9d6 100644
--- a/iOSClient/Supporting Files/es-EC.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/es-EC.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/es-GT.lproj/Localizable.strings b/iOSClient/Supporting Files/es-GT.lproj/Localizable.strings
index 1f9cfde75..e87ced038 100644
--- a/iOSClient/Supporting Files/es-GT.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/es-GT.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/es-HN.lproj/Localizable.strings b/iOSClient/Supporting Files/es-HN.lproj/Localizable.strings
index 34a8f1c0d..8186a8136 100644
--- a/iOSClient/Supporting Files/es-HN.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/es-HN.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/es-MX.lproj/Localizable.strings b/iOSClient/Supporting Files/es-MX.lproj/Localizable.strings
index 29ff32f9d..80bb4f3e0 100644
--- a/iOSClient/Supporting Files/es-MX.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/es-MX.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/es-NI.lproj/Localizable.strings b/iOSClient/Supporting Files/es-NI.lproj/Localizable.strings
index aa61e2455..aa04ba273 100644
--- a/iOSClient/Supporting Files/es-NI.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/es-NI.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/es-PA.lproj/Localizable.strings b/iOSClient/Supporting Files/es-PA.lproj/Localizable.strings
index aa61e2455..aa04ba273 100644
--- a/iOSClient/Supporting Files/es-PA.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/es-PA.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/es-PE.lproj/Localizable.strings b/iOSClient/Supporting Files/es-PE.lproj/Localizable.strings
index aa61e2455..aa04ba273 100644
--- a/iOSClient/Supporting Files/es-PE.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/es-PE.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/es-PR.lproj/Localizable.strings b/iOSClient/Supporting Files/es-PR.lproj/Localizable.strings
index aa61e2455..aa04ba273 100644
--- a/iOSClient/Supporting Files/es-PR.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/es-PR.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/es-PY.lproj/Localizable.strings b/iOSClient/Supporting Files/es-PY.lproj/Localizable.strings
index 484370411..78a6dfe64 100644
--- a/iOSClient/Supporting Files/es-PY.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/es-PY.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/es-SV.lproj/Localizable.strings b/iOSClient/Supporting Files/es-SV.lproj/Localizable.strings
index 1f9cfde75..2327a8895 100644
--- a/iOSClient/Supporting Files/es-SV.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/es-SV.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/es-UY.lproj/Localizable.strings b/iOSClient/Supporting Files/es-UY.lproj/Localizable.strings
index ba9fc8776..648c1bfd2 100644
--- a/iOSClient/Supporting Files/es-UY.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/es-UY.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/es.lproj/Localizable.strings b/iOSClient/Supporting Files/es.lproj/Localizable.strings
index 5ba66b02e..81c975079 100644
--- a/iOSClient/Supporting Files/es.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/es.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/et_EE.lproj/Localizable.strings b/iOSClient/Supporting Files/et_EE.lproj/Localizable.strings
index 618b9fd1a..500385980 100644
--- a/iOSClient/Supporting Files/et_EE.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/et_EE.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/eu.lproj/Localizable.strings b/iOSClient/Supporting Files/eu.lproj/Localizable.strings
index ed6b156bd..968804304 100644
--- a/iOSClient/Supporting Files/eu.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/eu.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/fa.lproj/Localizable.strings b/iOSClient/Supporting Files/fa.lproj/Localizable.strings
index 020b7b6bc..ab95ee920 100644
--- a/iOSClient/Supporting Files/fa.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/fa.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/fi-FI.lproj/Localizable.strings b/iOSClient/Supporting Files/fi-FI.lproj/Localizable.strings
index b0fa858c0..5f85dd01e 100644
--- a/iOSClient/Supporting Files/fi-FI.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/fi-FI.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/fo.lproj/Localizable.strings b/iOSClient/Supporting Files/fo.lproj/Localizable.strings
index aa76ef0b0..cdf672e8e 100644
--- a/iOSClient/Supporting Files/fo.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/fo.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/fr.lproj/InfoPlist.strings b/iOSClient/Supporting Files/fr.lproj/InfoPlist.strings
index ad8c81d8e..60551dca7 100644
--- a/iOSClient/Supporting Files/fr.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/fr.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/fr.lproj/Localizable.strings b/iOSClient/Supporting Files/fr.lproj/Localizable.strings
index f847542a1..b1f5fac31 100644
--- a/iOSClient/Supporting Files/fr.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/fr.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/gd.lproj/Localizable.strings b/iOSClient/Supporting Files/gd.lproj/Localizable.strings
index 2e758e91c..f8f8cdeea 100644
--- a/iOSClient/Supporting Files/gd.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/gd.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/gl.lproj/Localizable.strings b/iOSClient/Supporting Files/gl.lproj/Localizable.strings
index 53b4ba168..c327907ec 100644
--- a/iOSClient/Supporting Files/gl.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/gl.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/he.lproj/Localizable.strings b/iOSClient/Supporting Files/he.lproj/Localizable.strings
index a09013332..6d0a0c4a1 100644
--- a/iOSClient/Supporting Files/he.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/he.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/hi_IN.lproj/Localizable.strings b/iOSClient/Supporting Files/hi_IN.lproj/Localizable.strings
index d6feb161f..247442d61 100644
--- a/iOSClient/Supporting Files/hi_IN.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/hi_IN.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/hr.lproj/Localizable.strings b/iOSClient/Supporting Files/hr.lproj/Localizable.strings
index 0e5ef62ad..4b63bf841 100644
--- a/iOSClient/Supporting Files/hr.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/hr.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/hsb.lproj/Localizable.strings b/iOSClient/Supporting Files/hsb.lproj/Localizable.strings
index 6f11a3e51..f78460495 100644
--- a/iOSClient/Supporting Files/hsb.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/hsb.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/hu.lproj/Localizable.strings b/iOSClient/Supporting Files/hu.lproj/Localizable.strings
index d78522d67..398ed2aea 100644
--- a/iOSClient/Supporting Files/hu.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/hu.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/hy.lproj/Localizable.strings b/iOSClient/Supporting Files/hy.lproj/Localizable.strings
index a56cf377e..216b401ca 100644
--- a/iOSClient/Supporting Files/hy.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/hy.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ia.lproj/Localizable.strings b/iOSClient/Supporting Files/ia.lproj/Localizable.strings
index 4447846b0..6162c207d 100644
--- a/iOSClient/Supporting Files/ia.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/ia.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/id.lproj/Localizable.strings b/iOSClient/Supporting Files/id.lproj/Localizable.strings
index 2b5c81e56..bd636dbc8 100644
--- a/iOSClient/Supporting Files/id.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/id.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ig.lproj/Localizable.strings b/iOSClient/Supporting Files/ig.lproj/Localizable.strings
index b1e6f9f2f..665802506 100644
--- a/iOSClient/Supporting Files/ig.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/ig.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/is.lproj/Localizable.strings b/iOSClient/Supporting Files/is.lproj/Localizable.strings
index e99e2bb2d..5781f3c66 100644
--- a/iOSClient/Supporting Files/is.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/is.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/it.lproj/Localizable.strings b/iOSClient/Supporting Files/it.lproj/Localizable.strings
index 8e113f338..2ad412712 100644
--- a/iOSClient/Supporting Files/it.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/it.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ja-JP.lproj/Localizable.strings b/iOSClient/Supporting Files/ja-JP.lproj/Localizable.strings
index 4c5ef5480..050fc708f 100644
--- a/iOSClient/Supporting Files/ja-JP.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/ja-JP.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ka-GE.lproj/Localizable.strings b/iOSClient/Supporting Files/ka-GE.lproj/Localizable.strings
index 384abecfc..a11aa6464 100644
--- a/iOSClient/Supporting Files/ka-GE.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/ka-GE.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ka.lproj/Localizable.strings b/iOSClient/Supporting Files/ka.lproj/Localizable.strings
index 800fbe66e..1ee274fe4 100644
--- a/iOSClient/Supporting Files/ka.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/ka.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/kab.lproj/Localizable.strings b/iOSClient/Supporting Files/kab.lproj/Localizable.strings
index 83f45f735..9ada0f194 100644
--- a/iOSClient/Supporting Files/kab.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/kab.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/km.lproj/Localizable.strings b/iOSClient/Supporting Files/km.lproj/Localizable.strings
index e2343fd71..d79335d22 100644
--- a/iOSClient/Supporting Files/km.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/km.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/kn.lproj/Localizable.strings b/iOSClient/Supporting Files/kn.lproj/Localizable.strings
index 105d64240..e48d62f23 100644
--- a/iOSClient/Supporting Files/kn.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/kn.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ko.lproj/Localizable.strings b/iOSClient/Supporting Files/ko.lproj/Localizable.strings
index 6c9f2609d..34ed136ee 100644
--- a/iOSClient/Supporting Files/ko.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/ko.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/la.lproj/Localizable.strings b/iOSClient/Supporting Files/la.lproj/Localizable.strings
index 2baa2f06e..8793cbccc 100644
--- a/iOSClient/Supporting Files/la.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/la.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/lb.lproj/Localizable.strings b/iOSClient/Supporting Files/lb.lproj/Localizable.strings
index 4990dc5c8..1f4600d8d 100644
--- a/iOSClient/Supporting Files/lb.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/lb.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/lo.lproj/Localizable.strings b/iOSClient/Supporting Files/lo.lproj/Localizable.strings
index 150df0194..4f1fd5b63 100644
--- a/iOSClient/Supporting Files/lo.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/lo.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/lt_LT.lproj/Localizable.strings b/iOSClient/Supporting Files/lt_LT.lproj/Localizable.strings
index cba973880..b307faffa 100644
--- a/iOSClient/Supporting Files/lt_LT.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/lt_LT.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/lv.lproj/Localizable.strings b/iOSClient/Supporting Files/lv.lproj/Localizable.strings
index 80d3d3063..d880e1b18 100644
--- a/iOSClient/Supporting Files/lv.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/lv.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/mk.lproj/Localizable.strings b/iOSClient/Supporting Files/mk.lproj/Localizable.strings
index 79abd4af6..9b9671bb9 100644
--- a/iOSClient/Supporting Files/mk.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/mk.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/mn.lproj/Localizable.strings b/iOSClient/Supporting Files/mn.lproj/Localizable.strings
index 2106f082d..43ca4b313 100644
--- a/iOSClient/Supporting Files/mn.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/mn.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/mr.lproj/Localizable.strings b/iOSClient/Supporting Files/mr.lproj/Localizable.strings
index 9a4c98b34..5d886216d 100644
--- a/iOSClient/Supporting Files/mr.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/mr.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ms_MY.lproj/Localizable.strings b/iOSClient/Supporting Files/ms_MY.lproj/Localizable.strings
index a68b50a6b..f083b1caa 100644
--- a/iOSClient/Supporting Files/ms_MY.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/ms_MY.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/my.lproj/Localizable.strings b/iOSClient/Supporting Files/my.lproj/Localizable.strings
index 29dec98a8..fa4d74606 100644
--- a/iOSClient/Supporting Files/my.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/my.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/nb-NO.lproj/Localizable.strings b/iOSClient/Supporting Files/nb-NO.lproj/Localizable.strings
index 95fcaa666..8032ad8a1 100644
--- a/iOSClient/Supporting Files/nb-NO.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/nb-NO.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ne.lproj/Localizable.strings b/iOSClient/Supporting Files/ne.lproj/Localizable.strings
index e882cb781..d09db6e67 100644
--- a/iOSClient/Supporting Files/ne.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/ne.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/nl.lproj/Localizable.strings b/iOSClient/Supporting Files/nl.lproj/Localizable.strings
index 9b6b823d5..09ffdf118 100644
--- a/iOSClient/Supporting Files/nl.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/nl.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/nn_NO.lproj/Localizable.strings b/iOSClient/Supporting Files/nn_NO.lproj/Localizable.strings
index 1f04dcda5..056056e47 100644
--- a/iOSClient/Supporting Files/nn_NO.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/nn_NO.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/oc.lproj/Localizable.strings b/iOSClient/Supporting Files/oc.lproj/Localizable.strings
index e04570e48..ffff72c9e 100644
--- a/iOSClient/Supporting Files/oc.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/oc.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/pl.lproj/Localizable.strings b/iOSClient/Supporting Files/pl.lproj/Localizable.strings
index e1065e025..7e825a0b3 100644
--- a/iOSClient/Supporting Files/pl.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/pl.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ps.lproj/Localizable.strings b/iOSClient/Supporting Files/ps.lproj/Localizable.strings
index 9031888a4..131f275cb 100644
--- a/iOSClient/Supporting Files/ps.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/ps.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/pt-BR.lproj/Localizable.strings b/iOSClient/Supporting Files/pt-BR.lproj/Localizable.strings
index 464d3f855..c7a7c4ccf 100644
--- a/iOSClient/Supporting Files/pt-BR.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/pt-BR.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/pt-PT.lproj/InfoPlist.strings b/iOSClient/Supporting Files/pt-PT.lproj/InfoPlist.strings
index b58e1cf05..39b1fdfa8 100644
--- a/iOSClient/Supporting Files/pt-PT.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/pt-PT.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/pt-PT.lproj/Localizable.strings b/iOSClient/Supporting Files/pt-PT.lproj/Localizable.strings
index 0e826616a..2f1b88e76 100644
--- a/iOSClient/Supporting Files/pt-PT.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/pt-PT.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ro.lproj/Localizable.strings b/iOSClient/Supporting Files/ro.lproj/Localizable.strings
index fe1d77757..37d2ee8ef 100644
--- a/iOSClient/Supporting Files/ro.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/ro.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ru.lproj/InfoPlist.strings b/iOSClient/Supporting Files/ru.lproj/InfoPlist.strings
index b58e1cf05..04da94e52 100644
--- a/iOSClient/Supporting Files/ru.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/ru.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ru.lproj/Localizable.strings b/iOSClient/Supporting Files/ru.lproj/Localizable.strings
index c87d9f964..e21871bca 100644
--- a/iOSClient/Supporting Files/ru.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/ru.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/sc.lproj/Localizable.strings b/iOSClient/Supporting Files/sc.lproj/Localizable.strings
index 43da9b89e..aa41dbdc3 100644
--- a/iOSClient/Supporting Files/sc.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/sc.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/si.lproj/Localizable.strings b/iOSClient/Supporting Files/si.lproj/Localizable.strings
index ca90225b0..237faf080 100644
--- a/iOSClient/Supporting Files/si.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/si.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/sk-SK.lproj/InfoPlist.strings b/iOSClient/Supporting Files/sk-SK.lproj/InfoPlist.strings
index d0a95dc1c..b0174ff6a 100644
--- a/iOSClient/Supporting Files/sk-SK.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/sk-SK.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/sk-SK.lproj/Localizable.strings b/iOSClient/Supporting Files/sk-SK.lproj/Localizable.strings
index 389d16f42..31f1f216f 100644
--- a/iOSClient/Supporting Files/sk-SK.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/sk-SK.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/sl.lproj/InfoPlist.strings b/iOSClient/Supporting Files/sl.lproj/InfoPlist.strings
index b58e1cf05..36fd73fbf 100644
--- a/iOSClient/Supporting Files/sl.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/sl.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/sl.lproj/Localizable.strings b/iOSClient/Supporting Files/sl.lproj/Localizable.strings
index e93456fc3..6c1177a65 100644
--- a/iOSClient/Supporting Files/sl.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/sl.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/sq.lproj/Localizable.strings b/iOSClient/Supporting Files/sq.lproj/Localizable.strings
index 8e1194c04..13caa4aa2 100644
--- a/iOSClient/Supporting Files/sq.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/sq.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/sr.lproj/Localizable.strings b/iOSClient/Supporting Files/sr.lproj/Localizable.strings
index 63b2a1bea..997484f4b 100644
--- a/iOSClient/Supporting Files/sr.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/sr.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/sr@latin.lproj/Localizable.strings b/iOSClient/Supporting Files/sr@latin.lproj/Localizable.strings
index e18103b5c..2217bf456 100644
--- a/iOSClient/Supporting Files/sr@latin.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/sr@latin.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/sv.lproj/Localizable.strings b/iOSClient/Supporting Files/sv.lproj/Localizable.strings
index be2b8a132..549aaaf15 100644
--- a/iOSClient/Supporting Files/sv.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/sv.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/sw.lproj/Localizable.strings b/iOSClient/Supporting Files/sw.lproj/Localizable.strings
index d6feb161f..247442d61 100644
--- a/iOSClient/Supporting Files/sw.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/sw.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ta.lproj/Localizable.strings b/iOSClient/Supporting Files/ta.lproj/Localizable.strings
index bfb871e98..81406f1e6 100644
--- a/iOSClient/Supporting Files/ta.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/ta.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/th_TH.lproj/Localizable.strings b/iOSClient/Supporting Files/th_TH.lproj/Localizable.strings
index 16615f2b1..8cb1e7c06 100644
--- a/iOSClient/Supporting Files/th_TH.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/th_TH.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/tk.lproj/Localizable.strings b/iOSClient/Supporting Files/tk.lproj/Localizable.strings
index be672326e..637b5dc7b 100644
--- a/iOSClient/Supporting Files/tk.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/tk.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/tr.lproj/Localizable.strings b/iOSClient/Supporting Files/tr.lproj/Localizable.strings
index fdff9602b..e52b1705a 100644
--- a/iOSClient/Supporting Files/tr.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/tr.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ug.lproj/Localizable.strings b/iOSClient/Supporting Files/ug.lproj/Localizable.strings
index 4fd0b3de0..6e0e7a60c 100644
--- a/iOSClient/Supporting Files/ug.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/ug.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/uk.lproj/Localizable.strings b/iOSClient/Supporting Files/uk.lproj/Localizable.strings
index c0ecb041e..7ce540bc0 100644
--- a/iOSClient/Supporting Files/uk.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/uk.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ur_PK.lproj/Localizable.strings b/iOSClient/Supporting Files/ur_PK.lproj/Localizable.strings
index 2be0c7a1a..6aedccf51 100644
--- a/iOSClient/Supporting Files/ur_PK.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/ur_PK.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/uz.lproj/Localizable.strings b/iOSClient/Supporting Files/uz.lproj/Localizable.strings
index 6a10a5bae..65ebd5bc2 100644
--- a/iOSClient/Supporting Files/uz.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/uz.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/vi.lproj/Localizable.strings b/iOSClient/Supporting Files/vi.lproj/Localizable.strings
index 175916657..75e46841a 100644
--- a/iOSClient/Supporting Files/vi.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/vi.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/zh-Hans.lproj/Localizable.strings b/iOSClient/Supporting Files/zh-Hans.lproj/Localizable.strings
index 945bdd621..78e566523 100644
--- a/iOSClient/Supporting Files/zh-Hans.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/zh-Hans.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/zh-Hant-TW.lproj/InfoPlist.strings b/iOSClient/Supporting Files/zh-Hant-TW.lproj/InfoPlist.strings
index b58e1cf05..af62566f5 100644
--- a/iOSClient/Supporting Files/zh-Hant-TW.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/zh-Hant-TW.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/zh-Hant-TW.lproj/Localizable.strings b/iOSClient/Supporting Files/zh-Hant-TW.lproj/Localizable.strings
index ab783619a..1f4de1585 100644
--- a/iOSClient/Supporting Files/zh-Hant-TW.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/zh-Hant-TW.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/zh_HK.lproj/Localizable.strings b/iOSClient/Supporting Files/zh_HK.lproj/Localizable.strings
index 946102aad..f343c077d 100644
--- a/iOSClient/Supporting Files/zh_HK.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/zh_HK.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Transfers/NCTransferCell.swift b/iOSClient/Transfers/NCTransferCell.swift
index 2df137685..acbf1fdca 100755
--- a/iOSClient/Transfers/NCTransferCell.swift
+++ b/iOSClient/Transfers/NCTransferCell.swift
@@ -43,33 +43,35 @@ class NCTransferCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellP
var indexPath = IndexPath()
var namedButtonMore = ""
- var fileAvatarImageView: UIImageView? {
- get {
- return nil
- }
- }
var fileObjectId: String? {
- get {
- return objectId
- }
- set {
- objectId = newValue ?? ""
- }
+ get { return objectId }
+ set { objectId = newValue ?? "" }
}
var filePreviewImageView: UIImageView? {
- get {
- return imageItem
- }
+ get { return imageItem }
+ set { imageItem = newValue }
}
var fileUser: String? {
- get {
- return user
- }
- set {
- user = newValue ?? ""
- }
+ get { return user }
+ set { user = newValue ?? "" }
}
-
+ var fileTitleLabel: UILabel? {
+ get { return labelTitle }
+ set { labelTitle = newValue }
+ }
+ var fileInfoLabel: UILabel? {
+ get { return labelInfo }
+ set { labelInfo = newValue }
+ }
+ var fileProgressView: UIProgressView? {
+ get { return progressView }
+ set { progressView = newValue }
+ }
+ var fileMoreImage: UIImageView? {
+ get { return imageMore }
+ set { imageMore = newValue }
+ }
+
override func awakeFromNib() {
super.awakeFromNib()
@@ -96,6 +98,9 @@ class NCTransferCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellP
separator.backgroundColor = NCBrandColor.shared.separator
separatorHeightConstraint.constant = 0.5
+
+ labelTitle.text = ""
+ labelInfo.text = ""
}
override func prepareForReuse() {
@@ -119,6 +124,11 @@ class NCTransferCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellP
delegate?.longPressListItem(with: objectId, gestureRecognizer: gestureRecognizer)
}
+ func hideButtonMore(_ status: Bool) {
+ imageMore.isHidden = status
+ buttonMore.isHidden = status
+ }
+
func setButtonMore(named: String, image: UIImage) {
namedButtonMore = named
imageMore.image = image
@@ -128,7 +138,10 @@ class NCTransferCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellP
target: self,
selector: #selector(touchUpInsideMore))
]
+ }
+ func writeInfoDateSize(date: NSDate, size: Int64) {
+ labelInfo.text = CCUtility.dateDiff(date as Date) + " · " + CCUtility.transformedSize(size)
}
}
diff --git a/iOSClient/Transfers/NCTransfers.swift b/iOSClient/Transfers/NCTransfers.swift
index 30827eb70..c56324a46 100644
--- a/iOSClient/Transfers/NCTransfers.swift
+++ b/iOSClient/Transfers/NCTransfers.swift
@@ -36,6 +36,9 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
titleCurrentFolder = NSLocalizedString("_transfers_", comment: "")
layoutKey = NCGlobal.shared.layoutViewTransfers
enableSearchBar = false
+ headerMenuButtonsCommand = false
+ headerMenuButtonsView = false
+ headerRichWorkspaceDisable = true
emptyImage = UIImage(named: "arrow.left.arrow.right")?.image(color: .gray, size: UIScreen.main.bounds.width)
emptyTitle = "_no_transfer_"
emptyDescription = "_no_transfer_sub_"
@@ -45,15 +48,8 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
super.viewDidLoad()
listLayout.itemHeight = 105
- collectionView?.collectionViewLayout = listLayout
+ NCUtility.shared.setLayoutForView(key: layoutKey, serverUrl: serverUrl, layout: NCGlobal.shared.layoutList)
self.navigationItem.title = titleCurrentFolder
- serverUrl = appDelegate.activeServerUrl
- }
-
- override func viewWillAppear(_ animated: Bool) {
- super.viewWillAppear(animated)
-
- collectionView?.collectionViewLayout = listLayout
}
override func setNavigationItem() {
@@ -131,12 +127,16 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
@objc func startTask(_ notification: Any) {
guard let metadata = metadataTemp else { return }
-
- metadata.status = NCGlobal.shared.metadataStatusInUpload
- metadata.session = NCCommunicationCommon.shared.sessionIdentifierUpload
-
- NCManageDatabase.shared.addMetadata(metadata)
- NCNetworking.shared.upload(metadata: metadata) { } completion: { _, _ in }
+ guard appDelegate.account == metadata.account else { return }
+ guard let networkingProcessUpload = appDelegate.networkingProcessUpload else { return }
+
+ networkingProcessUpload.extractFiles(from: metadata) { metadatas in
+ for metadata in metadatas {
+ if let metadata = NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusInUpload) {
+ NCNetworking.shared.upload(metadata: metadata)
+ }
+ }
+ }
}
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
@@ -154,12 +154,13 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
// MARK: - Collection View
- override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
- // nothing
+ @available(iOS 13.0, *)
+ override func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
+ return nil
}
- override func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
- return CGSize(width: collectionView.frame.width, height: 0)
+ override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
+ // nothing
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
@@ -175,7 +176,7 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
cell.fileUser = metadata.ownerId
cell.indexPath = indexPath
- cell.imageItem.image = nil
+ cell.imageItem.image = NCBrandColor.cacheImages.file
cell.imageItem.backgroundColor = nil
cell.labelTitle.text = metadata.fileNameView
@@ -190,29 +191,33 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
cell.progressView.progress = 0.0
- if FileManager().fileExists(atPath: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) {
- cell.imageItem.image = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag))
- } else if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && FileManager().fileExists(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)) {
- cell.imageItem.image = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView))
- }
-
- if cell.imageItem.image == nil {
- cell.imageItem.image = NCBrandColor.cacheImages.file
+ let filePath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
+ let iconImagePath = CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)!
+
+ if FileManager().fileExists(atPath: iconImagePath) {
+ cell.imageItem.image = UIImage(contentsOfFile:iconImagePath)
+ } else if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue, FileManager().fileExists(atPath: filePath) {
+ if let image = UIImage(contentsOfFile: filePath), let image = image.resizeImage(size: CGSize(width: NCGlobal.shared.sizeIcon, height: NCGlobal.shared.sizeIcon), isAspectRation: true), let data = image.jpegData(compressionQuality: 0.5) {
+ do {
+ try data.write(to: URL.init(fileURLWithPath: iconImagePath), options: .atomic)
+ cell.imageItem.image = image
+ } catch { }
+ }
+ } else if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue, FileManager().fileExists(atPath: filePath) {
+ if let image = NCUtility.shared.imageFromVideo(url: URL(fileURLWithPath: filePath), at: 0), let image = image.resizeImage(size: CGSize(width: NCGlobal.shared.sizeIcon, height: NCGlobal.shared.sizeIcon), isAspectRation: true), let data = image.jpegData(compressionQuality: 0.5) {
+ do {
+ try data.write(to: URL.init(fileURLWithPath: iconImagePath), options: .atomic)
+ cell.imageItem.image = image
+ } catch { }
+ }
+ } else {
+ cell.imageItem.image = UIImage(named: metadata.iconName)
}
cell.labelInfo.text = CCUtility.dateDiff(metadata.date as Date) + " · " + CCUtility.transformedSize(metadata.size)
- // Transfer
- var progress: Float = 0.0
- var totalBytes: Int64 = 0
- if let progressType = appDelegate.listProgress[metadata.ocId] {
- progress = progressType.progress
- totalBytes = progressType.totalBytes
- }
-
if metadata.status == NCGlobal.shared.metadataStatusDownloading || metadata.status == NCGlobal.shared.metadataStatusUploading {
cell.progressView.isHidden = false
- cell.progressView.progress = progress
} else {
cell.progressView.isHidden = true
}
@@ -229,11 +234,11 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
break
case NCGlobal.shared.metadataStatusDownloading:
cell.labelStatus.text = NSLocalizedString("_status_downloading_", comment: "")
- cell.labelInfo.text = CCUtility.transformedSize(metadata.size) + " - ↓ " + CCUtility.transformedSize(totalBytes)
+ cell.labelInfo.text = CCUtility.transformedSize(metadata.size) + " - ↓ …"
break
case NCGlobal.shared.metadataStatusWaitUpload:
cell.labelStatus.text = NSLocalizedString("_status_wait_upload_", comment: "")
- cell.labelInfo.text = CCUtility.transformedSize(metadata.size)
+ cell.labelInfo.text = ""
break
case NCGlobal.shared.metadataStatusInUpload:
cell.labelStatus.text = NSLocalizedString("_status_in_upload_", comment: "")
@@ -241,17 +246,25 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
break
case NCGlobal.shared.metadataStatusUploading:
cell.labelStatus.text = NSLocalizedString("_status_uploading_", comment: "")
- cell.labelInfo.text = CCUtility.transformedSize(metadata.size) + " - ↑ " + CCUtility.transformedSize(totalBytes)
+ cell.labelInfo.text = CCUtility.transformedSize(metadata.size) + " - ↑ …"
break
case NCGlobal.shared.metadataStatusUploadError:
cell.labelStatus.text = NSLocalizedString("_status_upload_error_", comment: "")
- cell.labelInfo.text = CCUtility.transformedSize(metadata.size)
+ cell.labelInfo.text = metadata.sessionError
break
default:
cell.labelStatus.text = ""
cell.labelInfo.text = ""
break
}
+ if self.appDelegate.account != metadata.account {
+ cell.labelInfo.text = NSLocalizedString("_waiting_for_", comment: "") + " " + NSLocalizedString("_user_", comment: "").lowercased() + " \(metadata.userId) " + NSLocalizedString("_in_", comment: "") + " \(metadata.urlBase)"
+ }
+ let isWiFi = NCNetworking.shared.networkReachability == NCCommunicationCommon.typeReachability.reachableEthernetOrWiFi
+ if metadata.session == NCNetworking.shared.sessionIdentifierBackgroundWWan && !isWiFi {
+ cell.labelInfo.text = NSLocalizedString("_waiting_for_", comment: "") + " " + NSLocalizedString("_reachable_wifi_", comment: "")
+ }
+
cell.accessibilityLabel = metadata.fileNameView + ", " + (cell.labelInfo.text ?? "")
// Remove last separator
@@ -266,14 +279,18 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
// MARK: - DataSource + NC Endpoint
- override func reloadDataSource() {
+ override func reloadDataSource(forced: Bool = true) {
super.reloadDataSource()
- metadatasSource = NCManageDatabase.shared.getAdvancedMetadatas(predicate: NSPredicate(format: "status != %i", NCGlobal.shared.metadataStatusNormal), page: 1, limit: 100, sorted: "sessionTaskIdentifier", ascending: false)
- self.dataSource = NCDataSource(metadatasSource: metadatasSource)
+ DispatchQueue.global().async {
+ let metadatas = NCManageDatabase.shared.getAdvancedMetadatas(predicate: NSPredicate(format: "status != %i", NCGlobal.shared.metadataStatusNormal), page: 1, limit: 100, sorted: "sessionTaskIdentifier", ascending: false)
+ self.dataSource = NCDataSource(metadatas: metadatas, account: self.appDelegate.account)
- refreshControl.endRefreshing()
- collectionView.reloadData()
+ DispatchQueue.main.async {
+ self.refreshControl.endRefreshing()
+ self.collectionView.reloadData()
+ }
+ }
}
override func reloadDataSourceNetwork(forced: Bool = false) {
diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell+NCTrashCellProtocol.swift
index 28b2fa8b6..2b8c1a982 100644
--- a/iOSClient/Trash/Cell/NCTrashListCell.swift
+++ b/iOSClient/Trash/Cell/NCTrashListCell+NCTrashCellProtocol.swift
@@ -25,14 +25,14 @@
import UIKit
-class NCTrashListCell: UICollectionViewCell, NCTrashCell {
+class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol {
@IBOutlet weak var imageItem: UIImageView!
@IBOutlet weak var imageItemLeftConstraint: NSLayoutConstraint!
@IBOutlet weak var imageSelect: UIImageView!
@IBOutlet weak var labelTitle: UILabel!
- @IBOutlet weak var labelInfo: UILabel?
+ @IBOutlet weak var labelInfo: UILabel!
@IBOutlet weak var imageRestore: UIImageView!
@IBOutlet weak var imageMore: UIImageView!
@@ -65,7 +65,7 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCell {
]
imageRestore.image = NCBrandColor.cacheImages.buttonRestore
- imageMore.image = NCUtility.shared.loadImage(named: "trash")
+ imageMore.image = NCBrandColor.cacheImages.buttonTrash
imageItem.layer.cornerRadius = 6
imageItem.layer.masksToBounds = true
@@ -124,30 +124,36 @@ protocol NCTrashListCellDelegate: AnyObject {
func tapMoreListItem(with objectId: String, image: UIImage?, sender: Any)
}
-protocol NCTrashCell {
+protocol NCTrashCellProtocol {
var objectId: String { get set }
var labelTitle: UILabel! { get set }
- var labelInfo: UILabel? { get set }
+ var labelInfo: UILabel! { get set }
var imageItem: UIImageView! { get set }
func selectMode(_ status: Bool)
func selected(_ status: Bool)
}
-extension NCTrashCell where Self: UICollectionViewCell {
+extension NCTrashCellProtocol where Self: UICollectionViewCell {
mutating func setupCellUI(tableTrash: tableTrash, image: UIImage?) {
self.objectId = tableTrash.fileId
self.labelTitle.text = tableTrash.trashbinFileName
self.labelTitle.textColor = NCBrandColor.shared.label
- let infoText: String
+ if self is NCTrashListCell {
+ self.labelInfo?.text = CCUtility.dateDiff(tableTrash.date as Date)
+ } else {
+ let dateFormatter = DateFormatter()
+ dateFormatter.dateStyle = .short
+ dateFormatter.timeStyle = .none
+ dateFormatter.locale = Locale.current
+ self.labelInfo?.text = dateFormatter.string(from: tableTrash.date as Date)
+ }
if tableTrash.directory {
self.imageItem.image = NCBrandColor.cacheImages.folder
- infoText = CCUtility.dateDiff(tableTrash.date as Date)
} else {
self.imageItem.image = image
- infoText = CCUtility.dateDiff(tableTrash.date as Date) + ", " + CCUtility.transformedSize(tableTrash.size)
+ self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + CCUtility.transformedSize(tableTrash.size)
}
- self.labelInfo?.text = infoText
- self.accessibilityLabel = tableTrash.trashbinFileName + ", " + infoText
+ self.accessibilityLabel = tableTrash.trashbinFileName + ", " + (self.labelInfo?.text ?? "")
}
}
diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift
index 8261bfc9b..4b1ce4ea3 100644
--- a/iOSClient/Trash/NCTrash+CollectionView.swift
+++ b/iOSClient/Trash/NCTrash+CollectionView.swift
@@ -53,37 +53,6 @@ extension NCTrash: UICollectionViewDelegate {
// MARK: UICollectionViewDataSource
extension NCTrash: UICollectionViewDataSource {
- func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
-
- if kind == UICollectionView.elementKindSectionHeader {
-
- guard let trashHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionHeaderMenu", for: indexPath) as? NCTrashSectionHeaderMenu
- else { return UICollectionReusableView() }
-
- if collectionView.collectionViewLayout == gridLayout {
- trashHeader.buttonSwitch.setImage(UIImage(named: "switchList")?.image(color: NCBrandColor.shared.gray, size: 25), for: .normal)
- trashHeader.buttonSwitch.accessibilityLabel = NSLocalizedString("_list_view_", comment: "")
- } else {
- trashHeader.buttonSwitch.setImage(UIImage(named: "switchGrid")?.image(color: NCBrandColor.shared.gray, size: 25), for: .normal)
- trashHeader.buttonSwitch.accessibilityLabel = NSLocalizedString("_grid_view_", comment: "")
- }
-
- trashHeader.delegate = self
- trashHeader.backgroundColor = NCBrandColor.shared.systemBackground
- trashHeader.separator.backgroundColor = NCBrandColor.shared.separator
- trashHeader.setStatusButton(datasource: datasource)
- trashHeader.setTitleSorted(datasourceTitleButton: layoutForView?.titleButtonHeader ?? "")
-
- return trashHeader
-
- } else {
- guard let trashFooter = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as? NCTrashSectionFooter
- else { return UICollectionReusableView() }
- trashFooter.setTitleLabelFooter(datasource: datasource)
- return trashFooter
- }
- }
-
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
emptyDataSet?.numberOfItemsInSection(datasource.count, section: section)
return datasource.count
@@ -108,9 +77,9 @@ extension NCTrash: UICollectionViewDataSource {
}
}
- var cell: NCTrashCell & UICollectionViewCell
+ var cell: NCTrashCellProtocol & UICollectionViewCell
- if collectionView.collectionViewLayout == listLayout {
+ if layoutForView?.layout == NCGlobal.shared.layoutList {
guard let listCell = collectionView.dequeueReusableCell(withReuseIdentifier: "listCell", for: indexPath) as? NCTrashListCell else { return UICollectionViewCell() }
listCell.delegate = self
cell = listCell
@@ -130,16 +99,100 @@ extension NCTrash: UICollectionViewDataSource {
return cell
}
+
+ func setTextFooter(datasource: [tableTrash]) -> String {
+
+ var folders: Int = 0, foldersText = ""
+ var files: Int = 0, filesText = ""
+ var size: Int64 = 0
+ var text = ""
+
+ for record: tableTrash in datasource {
+ if record.directory {
+ folders += 1
+ } else {
+ files += 1
+ size += record.size
+ }
+ }
+
+ if folders > 1 {
+ foldersText = "\(folders) " + NSLocalizedString("_folders_", comment: "")
+ } else if folders == 1 {
+ foldersText = "1 " + NSLocalizedString("_folder_", comment: "")
+ }
+
+ if files > 1 {
+ filesText = "\(files) " + NSLocalizedString("_files_", comment: "") + " " + CCUtility.transformedSize(size)
+ } else if files == 1 {
+ filesText = "1 " + NSLocalizedString("_file_", comment: "") + " " + CCUtility.transformedSize(size)
+ }
+
+ if foldersText.isEmpty {
+ text = filesText
+ } else if filesText.isEmpty {
+ text = foldersText
+ } else {
+ text = foldersText + ", " + filesText
+ }
+
+ return text
+ }
+
+ func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
+
+ if kind == UICollectionView.elementKindSectionHeader {
+
+ guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionHeaderMenu", for: indexPath) as? NCSectionHeaderMenu
+ else { return UICollectionReusableView() }
+
+ if layoutForView?.layout == NCGlobal.shared.layoutGrid {
+ header.setImageSwitchList()
+ header.buttonSwitch.accessibilityLabel = NSLocalizedString("_list_view_", comment: "")
+ } else {
+ header.setImageSwitchGrid()
+ header.buttonSwitch.accessibilityLabel = NSLocalizedString("_grid_view_", comment: "")
+ }
+
+ header.delegate = self
+ header.setStatusButtonsView(enable: !datasource.isEmpty)
+ header.setSortedTitle(layoutForView?.titleButtonHeader ?? "")
+ if isEditMode {
+ header.setButtonsCommand(heigt: NCGlobal.shared.heightButtonsCommand,
+ imageButton1: UIImage(named: "restore"), titleButton1: NSLocalizedString("_trash_restore_selected_", comment: ""),
+ imageButton2: UIImage(named: "trash"), titleButton2: NSLocalizedString("_trash_delete_selected_", comment: ""))
+ } else {
+ header.setButtonsCommand(heigt: NCGlobal.shared.heightButtonsCommand,
+ imageButton1: UIImage(named: "restore"), titleButton1: NSLocalizedString("_trash_restore_all_", comment: ""),
+ imageButton2: UIImage(named: "trash"), titleButton2: NSLocalizedString("_trash_delete_all_", comment: ""))
+ }
+ header.setButtonsView(heigt: NCGlobal.shared.heightButtonsView)
+ header.setRichWorkspaceHeight(0)
+ header.setSectionHeight(0)
+
+ return header
+
+ } else {
+
+ guard let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as? NCSectionFooter
+ else { return UICollectionReusableView() }
+
+ footer.setTitleLabel(setTextFooter(datasource: datasource))
+ footer.separatorIsHidden(true)
+
+ return footer
+ }
+ }
}
// MARK: UICollectionViewDelegateFlowLayout
extension NCTrash: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
- return CGSize(width: collectionView.frame.width, height: highHeader)
+ return CGSize(width: collectionView.frame.width, height: NCGlobal.shared.heightButtonsView + NCGlobal.shared.heightButtonsCommand)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
- return CGSize(width: collectionView.frame.width, height: highHeader)
+ return CGSize(width: collectionView.frame.width, height: NCGlobal.shared.endHeightFooter)
}
}
diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift
index 4382ec759..9c8ccd16b 100644
--- a/iOSClient/Trash/NCTrash.swift
+++ b/iOSClient/Trash/NCTrash.swift
@@ -27,9 +27,7 @@ import Realm
import UIKit
import NCCommunication
-class NCTrash: UIViewController, NCSelectableNavigationView, NCTrashListCellDelegate, NCTrashSectionHeaderMenuDelegate, NCEmptyDataSetDelegate, NCGridCellDelegate {
-
- var selectableDataSource: [RealmSwiftObject] { datasource }
+class NCTrash: UIViewController, NCSelectableNavigationView, NCTrashListCellDelegate, NCSectionHeaderMenuDelegate, NCEmptyDataSetDelegate, NCGridCellDelegate {
@IBOutlet weak var collectionView: UICollectionView!
@@ -37,6 +35,7 @@ class NCTrash: UIViewController, NCSelectableNavigationView, NCTrashListCellDele
var titleCurrentFolder = NSLocalizedString("_trash_view_", comment: "")
var blinkFileId: String?
var emptyDataSet: NCEmptyDataSet?
+ var selectableDataSource: [RealmSwiftObject] { datasource }
internal let appDelegate = (UIApplication.shared.delegate as? AppDelegate)!
@@ -47,7 +46,7 @@ class NCTrash: UIViewController, NCSelectableNavigationView, NCTrashListCellDele
var layoutForView: NCGlobal.layoutForViewType?
var listLayout: NCListLayout!
var gridLayout: NCGridLayout!
- let highHeader: CGFloat = 50
+
private let refreshControl = UIRefreshControl()
// MARK: - View Life Cycle
@@ -62,8 +61,8 @@ class NCTrash: UIViewController, NCSelectableNavigationView, NCTrashListCellDele
collectionView.register(UINib(nibName: "NCGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell")
// Header - Footer
- collectionView.register(UINib(nibName: "NCTrashSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu")
- collectionView.register(UINib(nibName: "NCTrashSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter")
+ collectionView.register(UINib(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu")
+ collectionView.register(UINib(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter")
collectionView.alwaysBounceVertical = true
collectionView.backgroundColor = NCBrandColor.shared.systemBackground
@@ -77,12 +76,9 @@ class NCTrash: UIViewController, NCSelectableNavigationView, NCTrashListCellDele
refreshControl.addTarget(self, action: #selector(loadListingTrash), for: .valueChanged)
// Empty
- emptyDataSet = NCEmptyDataSet(view: collectionView, offset: highHeader, delegate: self)
+ emptyDataSet = NCEmptyDataSet(view: collectionView, offset: NCGlobal.shared.heightButtonsView + NCGlobal.shared.heightButtonsCommand, delegate: self)
- NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSource), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSource), object: nil)
-
- changeTheming()
}
override func viewWillAppear(_ animated: Bool) {
@@ -100,10 +96,6 @@ class NCTrash: UIViewController, NCSelectableNavigationView, NCTrashListCellDele
collectionView.collectionViewLayout = gridLayout
}
- if trashPath.isEmpty {
- guard let userId = (appDelegate.userId as NSString).addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlFragmentAllowed) else { return }
- trashPath = appDelegate.urlBase + "/" + NCUtilityFileSystem.shared.getWebDAV(account: appDelegate.account) + "/trashbin/" + userId + "/trash/"
- }
setNavigationItem()
reloadDataSource()
}
@@ -121,10 +113,6 @@ class NCTrash: UIViewController, NCSelectableNavigationView, NCTrashListCellDele
}
}
- @objc func changeTheming() {
- collectionView.reloadData()
- }
-
// MARK: - Empty
func emptyDataSetView(_ view: NCEmptyView) {
@@ -135,37 +123,36 @@ class NCTrash: UIViewController, NCSelectableNavigationView, NCTrashListCellDele
// MARK: TAP EVENT
- func tapSwitchHeaderMenu(sender: Any) {
+ func tapButtonSwitch(_ sender: Any) {
if collectionView.collectionViewLayout == gridLayout {
+
// list layout
- UIView.animate(withDuration: 0.0, animations: {
- self.collectionView.collectionViewLayout.invalidateLayout()
- self.collectionView.setCollectionViewLayout(self.listLayout, animated: false, completion: { _ in
- self.collectionView.reloadData()
- })
- })
layoutForView?.layout = NCGlobal.shared.layoutList
NCUtility.shared.setLayoutForView(key: NCGlobal.shared.layoutViewTrash, serverUrl: "", layout: layoutForView?.layout)
+
+ self.collectionView.reloadData()
+ self.collectionView.collectionViewLayout.invalidateLayout()
+ self.collectionView.setCollectionViewLayout(self.listLayout, animated: true)
+
} else {
+
// grid layout
- UIView.animate(withDuration: 0.0, animations: {
- self.collectionView.collectionViewLayout.invalidateLayout()
- self.collectionView.setCollectionViewLayout(self.gridLayout, animated: false, completion: { _ in
- self.collectionView.reloadData()
- })
- })
layoutForView?.layout = NCGlobal.shared.layoutGrid
NCUtility.shared.setLayoutForView(key: NCGlobal.shared.layoutViewTrash, serverUrl: "", layout: layoutForView?.layout)
+
+ self.collectionView.reloadData()
+ self.collectionView.collectionViewLayout.invalidateLayout()
+ self.collectionView.setCollectionViewLayout(self.gridLayout, animated: true)
}
}
- func tapOrderHeaderMenu(sender: Any) {
+ func tapButtonOrder(_ sender: Any) {
let sortMenu = NCSortMenu()
sortMenu.toggleMenu(viewController: self, key: NCGlobal.shared.layoutViewTrash, sortButton: sender as? UIButton, serverUrl: "", hideDirectoryOnTop: true)
}
- func tapMoreHeaderMenu(sender: Any) {
+ func tapButtonMore(_ sender: Any) {
toggleMenuMoreHeader()
}
@@ -199,20 +186,54 @@ class NCTrash: UIViewController, NCSelectableNavigationView, NCTrashListCellDele
let buttonPosition = button.convert(CGPoint.zero, to: collectionView)
let indexPath = collectionView.indexPathForItem(at: buttonPosition)
collectionView(self.collectionView, didSelectItemAt: indexPath!)
- } // else: undefined sender
+ }
+ }
+
+ func tapButton1(_ sender: Any) {
+
+ if isEditMode {
+ if selectOcId.isEmpty { return }
+ self.selectOcId.forEach(self.restoreItem)
+ self.tapSelect()
+ } else {
+ if datasource.isEmpty { return }
+ datasource.forEach({ self.restoreItem(with: $0.fileId) })
+ }
+ }
+
+ func tapButton2(_ sender: Any) {
+
+ if isEditMode {
+ if selectOcId.isEmpty { return }
+ let alert = UIAlertController(title: NSLocalizedString("_trash_delete_selected_", comment: ""), message: "", preferredStyle: .alert)
+ alert.addAction(UIAlertAction(title: NSLocalizedString("_delete_", comment: ""), style: .destructive, handler: { _ in
+ self.selectOcId.forEach(self.deleteItem)
+ self.tapSelect()
+ }))
+ alert.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel, handler: { _ in }))
+ self.present(alert, animated: true, completion: nil)
+ } else {
+ if datasource.isEmpty { return }
+ let alert = UIAlertController(title: NSLocalizedString("_trash_delete_all_description_", comment: ""), message: "", preferredStyle: .alert)
+ alert.addAction(UIAlertAction(title: NSLocalizedString("_trash_delete_all_", comment: ""), style: .destructive, handler: { _ in
+ self.emptyTrash()
+ }))
+ alert.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel))
+ self.present(alert, animated: true, completion: nil)
+ }
}
func longPressGridItem(with objectId: String, gestureRecognizer: UILongPressGestureRecognizer) { }
func longPressMoreGridItem(with objectId: String, namedButtonMore: String, gestureRecognizer: UILongPressGestureRecognizer) { }
- @objc func reloadDataSource() {
+ // MARK: - DataSource
- layoutForView = NCUtility.shared.getLayoutForView(key: NCGlobal.shared.layoutViewTrash, serverUrl: "")
+ @objc func reloadDataSource(forced: Bool = true) {
+ layoutForView = NCUtility.shared.getLayoutForView(key: NCGlobal.shared.layoutViewTrash, serverUrl: "")
datasource.removeAll()
-
- guard let tashItems = NCManageDatabase.shared.getTrash(filePath: trashPath, sort: layoutForView?.sort, ascending: layoutForView?.ascending, account: appDelegate.account) else {
+ guard let trashPath = self.getTrashPath(), let tashItems = NCManageDatabase.shared.getTrash(filePath: trashPath, sort: layoutForView?.sort, ascending: layoutForView?.ascending, account: appDelegate.account) else {
return
}
@@ -235,6 +256,17 @@ class NCTrash: UIViewController, NCSelectableNavigationView, NCTrashListCellDele
}
}
}
+
+ func getTrashPath() -> String? {
+
+ if self.trashPath.isEmpty {
+ guard let userId = (appDelegate.userId as NSString).addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlFragmentAllowed) else { return nil }
+ let trashPath = appDelegate.urlBase + "/" + NCUtilityFileSystem.shared.getWebDAV(account: appDelegate.account) + "/trashbin/" + userId + "/trash/"
+ return trashPath
+ } else {
+ return self.trashPath
+ }
+ }
}
// MARK: - NC API & Algorithm
@@ -245,40 +277,35 @@ extension NCTrash {
NCCommunication.shared.listingTrash(showHiddenFiles: false, queue: NCCommunicationCommon.shared.backgroundQueue) { account, items, errorCode, errorDescription in
- if errorCode == 0 && account == self.appDelegate.account {
- NCManageDatabase.shared.deleteTrash(filePath: self.trashPath, account: self.appDelegate.account)
- NCManageDatabase.shared.addTrash(account: account, items: items)
- } else if errorCode != 0 {
+ DispatchQueue.main.async { self.refreshControl.endRefreshing() }
+
+ guard errorCode == 0, account == self.appDelegate.account, let trashPath = self.getTrashPath() else {
NCContentPresenter.shared.showError(description: errorDescription, errorCode: errorCode)
- } else {
- print("[LOG] It has been changed user during networking process, error.")
+ return
}
- DispatchQueue.main.async {
- self.refreshControl.endRefreshing()
- self.reloadDataSource()
- }
+ NCManageDatabase.shared.deleteTrash(filePath: trashPath, account: self.appDelegate.account)
+ NCManageDatabase.shared.addTrash(account: account, items: items)
+
+ DispatchQueue.main.async { self.reloadDataSource() }
}
}
func restoreItem(with fileId: String) {
- guard let tableTrash = NCManageDatabase.shared.getTrashItem(fileId: fileId, account: appDelegate.account) else {
- return
- }
-
+ guard let tableTrash = NCManageDatabase.shared.getTrashItem(fileId: fileId, account: appDelegate.account) else { return }
let fileNameFrom = tableTrash.filePath + tableTrash.fileName
let fileNameTo = appDelegate.urlBase + "/" + NCUtilityFileSystem.shared.getWebDAV(account: appDelegate.account) + "/trashbin/" + appDelegate.userId + "/restore/" + tableTrash.fileName
NCCommunication.shared.moveFileOrFolder(serverUrlFileNameSource: fileNameFrom, serverUrlFileNameDestination: fileNameTo, overwrite: true) { account, errorCode, errorDescription in
- if errorCode == 0 && account == self.appDelegate.account {
- NCManageDatabase.shared.deleteTrash(fileId: fileId, account: account)
- self.reloadDataSource()
- } else if errorCode != 0 {
+
+ guard errorCode == 0, account == self.appDelegate.account else {
NCContentPresenter.shared.showError(description: errorDescription, errorCode: errorCode)
- } else {
- print("[LOG] It has been changed user during networking process, error.")
+ return
}
+
+ NCManageDatabase.shared.deleteTrash(fileId: fileId, account: account)
+ self.reloadDataSource()
}
}
@@ -287,34 +314,31 @@ extension NCTrash {
let serverUrlFileName = appDelegate.urlBase + "/" + NCUtilityFileSystem.shared.getWebDAV(account: appDelegate.account) + "/trashbin/" + appDelegate.userId + "/trash"
NCCommunication.shared.deleteFileOrFolder(serverUrlFileName) { account, errorCode, errorDescription in
- if errorCode == 0 && account == self.appDelegate.account {
- NCManageDatabase.shared.deleteTrash(fileId: nil, account: self.appDelegate.account)
- } else if errorCode != 0 {
+
+ guard errorCode == 0, account == self.appDelegate.account else {
NCContentPresenter.shared.showError(description: errorDescription, errorCode: errorCode)
- } else {
- print("[LOG] It has been changed user during networking process, error.")
+ return
}
+
+ NCManageDatabase.shared.deleteTrash(fileId: nil, account: self.appDelegate.account)
self.reloadDataSource()
}
}
func deleteItem(with fileId: String) {
- guard let tableTrash = NCManageDatabase.shared.getTrashItem(fileId: fileId, account: appDelegate.account) else {
- return
- }
-
+ guard let tableTrash = NCManageDatabase.shared.getTrashItem(fileId: fileId, account: appDelegate.account) else { return }
let serverUrlFileName = tableTrash.filePath + tableTrash.fileName
NCCommunication.shared.deleteFileOrFolder(serverUrlFileName) { account, errorCode, errorDescription in
- if errorCode == 0 && account == self.appDelegate.account {
- NCManageDatabase.shared.deleteTrash(fileId: fileId, account: account)
- self.reloadDataSource()
- } else if errorCode != 0 {
+
+ guard errorCode == 0, account == self.appDelegate.account else {
NCContentPresenter.shared.showError(description: errorDescription, errorCode: errorCode)
- } else {
- print("[LOG] It has been changed user during networking process, error.")
+ return
}
+
+ NCManageDatabase.shared.deleteTrash(fileId: fileId, account: account)
+ self.reloadDataSource()
}
}
diff --git a/iOSClient/Trash/Section/NCTrashSectionHeaderFooter.swift b/iOSClient/Trash/Section/NCTrashSectionHeaderFooter.swift
deleted file mode 100644
index 0f36a0160..000000000
--- a/iOSClient/Trash/Section/NCTrashSectionHeaderFooter.swift
+++ /dev/null
@@ -1,139 +0,0 @@
-//
-// NCTrashSectionHeaderFooter.swift
-// Nextcloud
-//
-// Created by Marino Faggiana on 09/10/2018.
-// Copyright © 2018 Marino Faggiana. All rights reserved.
-//
-// Author Marino Faggiana <marino.faggiana@nextcloud.com>
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-import UIKit
-
-class NCTrashSectionHeaderMenu: UICollectionReusableView {
-
- @IBOutlet weak var buttonMore: UIButton!
- @IBOutlet weak var buttonSwitch: UIButton!
- @IBOutlet weak var buttonOrder: UIButton!
- @IBOutlet weak var buttonOrderWidthConstraint: NSLayoutConstraint!
- @IBOutlet weak var separator: UIView!
- @IBOutlet weak var separatorHeightConstraint: NSLayoutConstraint!
-
- weak var delegate: NCTrashSectionHeaderMenuDelegate?
-
- override func awakeFromNib() {
- super.awakeFromNib()
-
- buttonSwitch.setImage(UIImage(named: "switchList")!.image(color: NCBrandColor.shared.gray, size: 25), for: .normal)
-
- buttonOrder.setTitle("", for: .normal)
- buttonOrder.setTitleColor(NCBrandColor.shared.brandElement, for: .normal)
-
- buttonMore.setImage(UIImage(named: "more")!.image(color: NCBrandColor.shared.gray, size: 25), for: .normal)
-
- separator.backgroundColor = NCBrandColor.shared.separator
- separatorHeightConstraint.constant = 0.5
-
- backgroundColor = NCBrandColor.shared.systemBackground
- }
-
- func setTitleSorted(datasourceTitleButton: String) {
-
- let title = NSLocalizedString(datasourceTitleButton, comment: "")
- let size = title.size(withAttributes: [.font: buttonOrder.titleLabel?.font as Any])
-
- buttonOrder.setTitle(title, for: .normal)
- buttonOrderWidthConstraint.constant = size.width + 5
- }
-
- func setStatusButton(datasource: [tableTrash]) {
-
- if datasource.isEmpty {
- buttonSwitch.isEnabled = false
- buttonOrder.isEnabled = false
- buttonMore.isEnabled = false
- } else {
- buttonSwitch.isEnabled = true
- buttonOrder.isEnabled = true
- buttonMore.isEnabled = true
- }
- }
-
- @IBAction func touchUpInsideMore(_ sender: Any) {
- delegate?.tapMoreHeaderMenu(sender: sender)
- }
-
- @IBAction func touchUpInsideSwitch(_ sender: Any) {
- delegate?.tapSwitchHeaderMenu(sender: sender)
- }
-
- @IBAction func touchUpInsideOrder(_ sender: Any) {
- delegate?.tapOrderHeaderMenu(sender: sender)
- }
-}
-
-protocol NCTrashSectionHeaderMenuDelegate: AnyObject {
- func tapSwitchHeaderMenu(sender: Any)
- func tapMoreHeaderMenu(sender: Any)
- func tapOrderHeaderMenu(sender: Any)
-}
-
-class NCTrashSectionFooter: UICollectionReusableView {
-
- @IBOutlet weak var labelFooter: UILabel!
-
- override func awakeFromNib() {
- super.awakeFromNib()
-
- labelFooter.textColor = NCBrandColor.shared.gray
- }
-
- func setTitleLabelFooter(datasource: [tableTrash]) {
-
- var folders: Int = 0, foldersText = ""
- var files: Int = 0, filesText = ""
- var size: Int64 = 0
-
- for record: tableTrash in datasource {
- if record.directory {
- folders += 1
- } else {
- files += 1
- size += record.size
- }
- }
-
- if folders > 1 {
- foldersText = "\(folders) " + NSLocalizedString("_folders_", comment: "")
- } else if folders == 1 {
- foldersText = "1 " + NSLocalizedString("_folder_", comment: "")
- }
-
- if files > 1 {
- filesText = "\(files) " + NSLocalizedString("_files_", comment: "") + " " + CCUtility.transformedSize(size)
- } else if files == 1 {
- filesText = "1 " + NSLocalizedString("_file_", comment: "") + " " + CCUtility.transformedSize(size)
- }
-
- if foldersText.isEmpty {
- labelFooter.text = filesText
- } else if filesText.isEmpty {
- labelFooter.text = foldersText
- } else {
- labelFooter.text = foldersText + ", " + filesText
- }
- }
-}
diff --git a/iOSClient/Trash/Section/NCTrashSectionHeaderMenu.xib b/iOSClient/Trash/Section/NCTrashSectionHeaderMenu.xib
deleted file mode 100644
index 783c16a3b..000000000
--- a/iOSClient/Trash/Section/NCTrashSectionHeaderMenu.xib
+++ /dev/null
@@ -1,91 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
- <device id="retina4_7" orientation="portrait" appearance="light"/>
- <dependencies>
- <deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
- <capability name="Safe area layout guides" minToolsVersion="9.0"/>
- <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
- </dependencies>
- <objects>
- <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
- <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
- <collectionReusableView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" reuseIdentifier="sectionHeaderMenu" id="tys-A2-nDX" customClass="NCTrashSectionHeaderMenu" customModule="Nextcloud" customModuleProvider="target">
- <rect key="frame" x="0.0" y="0.0" width="375" height="50"/>
- <autoresizingMask key="autoresizingMask"/>
- <subviews>
- <button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1LD-cd-zhc" userLabel="buttonSwitch">
- <rect key="frame" x="12" y="12.5" width="25" height="25"/>
- <constraints>
- <constraint firstAttribute="width" constant="25" id="D76-X9-Tw9"/>
- <constraint firstAttribute="height" constant="25" id="izT-Ru-XYG"/>
- </constraints>
- <state key="normal" image="switchList"/>
- <connections>
- <action selector="touchUpInsideSwitch:" destination="tys-A2-nDX" eventType="touchUpInside" id="iT8-1j-fib"/>
- </connections>
- </button>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0bo-yl-t5k" userLabel="buttonOrder">
- <rect key="frame" x="55" y="11" width="230" height="28"/>
- <constraints>
- <constraint firstAttribute="width" constant="230" id="jvv-Ug-l3I"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <state key="normal" title="Sort by name (from A to Z)">
- <color key="titleColor" systemColor="darkTextColor"/>
- </state>
- <connections>
- <action selector="touchUpInsideOrder:" destination="tys-A2-nDX" eventType="touchUpInside" id="oiL-3O-hMQ"/>
- </connections>
- </button>
- <button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="D0O-wK-14O" userLabel="buttonMore">
- <rect key="frame" x="345" y="15" width="20" height="20"/>
- <constraints>
- <constraint firstAttribute="width" constant="20" id="aEr-j8-JDO"/>
- <constraint firstAttribute="height" constant="20" id="bvx-Uh-NWD"/>
- </constraints>
- <state key="normal" image="moreBig"/>
- <connections>
- <action selector="touchUpInsideMore:" destination="tys-A2-nDX" eventType="touchUpInside" id="Jyu-Mx-nWq"/>
- </connections>
- </button>
- <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LZu-Te-clJ" userLabel="Separator">
- <rect key="frame" x="0.0" y="48" width="375" height="1"/>
- <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- <color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- <constraints>
- <constraint firstAttribute="height" constant="1" id="VuP-sT-hUI"/>
- </constraints>
- </view>
- </subviews>
- <viewLayoutGuide key="safeArea" id="pm7-uW-mZE"/>
- <constraints>
- <constraint firstItem="D0O-wK-14O" firstAttribute="centerY" secondItem="tys-A2-nDX" secondAttribute="centerY" id="6w7-ws-gX3"/>
- <constraint firstAttribute="trailing" secondItem="LZu-Te-clJ" secondAttribute="trailing" id="7ww-Zl-sES"/>
- <constraint firstAttribute="trailing" secondItem="D0O-wK-14O" secondAttribute="trailing" constant="10" id="AsZ-tP-fP1"/>
- <constraint firstItem="LZu-Te-clJ" firstAttribute="leading" secondItem="tys-A2-nDX" secondAttribute="leading" id="ZEl-Ij-nt8"/>
- <constraint firstItem="1LD-cd-zhc" firstAttribute="leading" secondItem="tys-A2-nDX" secondAttribute="leading" constant="12" id="dHo-I3-Z1V"/>
- <constraint firstItem="1LD-cd-zhc" firstAttribute="centerY" secondItem="tys-A2-nDX" secondAttribute="centerY" id="hbd-cO-eBq"/>
- <constraint firstItem="0bo-yl-t5k" firstAttribute="centerY" secondItem="tys-A2-nDX" secondAttribute="centerY" id="kSZ-op-97F"/>
- <constraint firstAttribute="bottom" secondItem="LZu-Te-clJ" secondAttribute="bottom" constant="1" id="tJp-qc-NGO"/>
- <constraint firstItem="0bo-yl-t5k" firstAttribute="leading" secondItem="1LD-cd-zhc" secondAttribute="trailing" constant="18" id="zlZ-IN-gGx"/>
- </constraints>
- <connections>
- <outlet property="buttonMore" destination="D0O-wK-14O" id="eEx-3R-zCS"/>
- <outlet property="buttonOrder" destination="0bo-yl-t5k" id="Kbw-BG-73C"/>
- <outlet property="buttonOrderWidthConstraint" destination="jvv-Ug-l3I" id="E6N-z6-2VC"/>
- <outlet property="buttonSwitch" destination="1LD-cd-zhc" id="Ec2-cM-CoY"/>
- <outlet property="separator" destination="LZu-Te-clJ" id="EwO-za-LxT"/>
- <outlet property="separatorHeightConstraint" destination="VuP-sT-hUI" id="xVh-Se-bJq"/>
- </connections>
- <point key="canvasLocation" x="140" y="154"/>
- </collectionReusableView>
- </objects>
- <resources>
- <image name="moreBig" width="50" height="50"/>
- <image name="switchList" width="25" height="25"/>
- <systemColor name="darkTextColor">
- <color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- </systemColor>
- </resources>
-</document>
diff --git a/iOSClient/UserStatus/NCUserStatus.storyboard b/iOSClient/UserStatus/NCUserStatus.storyboard
index 19cc728a5..f5900201f 100644
--- a/iOSClient/UserStatus/NCUserStatus.storyboard
+++ b/iOSClient/UserStatus/NCUserStatus.storyboard
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="QH7-hC-pPW">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="QH7-hC-pPW">
<device id="retina6_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@@ -236,7 +236,7 @@
</constraints>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" rowHeight="45" id="laP-fj-qDh">
- <rect key="frame" x="0.0" y="24.333333969116211" width="408" height="45"/>
+ <rect key="frame" x="0.0" y="44.666666030883789" width="408" height="45"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="laP-fj-qDh" id="HIM-ev-wMc">
<rect key="frame" x="0.0" y="0.0" width="408" height="45"/>
@@ -333,23 +333,22 @@
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="3CT-dJ-sEj">
- <rect key="frame" x="10" y="67" width="192.66666666666666" height="30"/>
- <color key="backgroundColor" systemColor="systemGray6Color"/>
+ <rect key="frame" x="10" y="57" width="192.66666666666666" height="40"/>
<constraints>
- <constraint firstAttribute="height" constant="30" id="1F4-Cv-RzK"/>
+ <constraint firstAttribute="height" constant="40" id="1F4-Cv-RzK"/>
</constraints>
- <fontDescription key="fontDescription" type="boldSystem" pointSize="14"/>
+ <fontDescription key="fontDescription" type="system" pointSize="14"/>
<state key="normal" title="clear status message"/>
<connections>
<action selector="actionClearStatusMessage:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="kSK-3g-AiY"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="3xN-e7-N0L">
- <rect key="frame" x="225.33333333333337" y="67" width="192.66666666666663" height="30"/>
+ <rect key="frame" x="225.33333333333337" y="57" width="192.66666666666663" height="40"/>
<constraints>
- <constraint firstAttribute="height" constant="30" id="66i-0j-Qrn"/>
+ <constraint firstAttribute="height" constant="40" id="66i-0j-Qrn"/>
</constraints>
- <fontDescription key="fontDescription" type="boldSystem" pointSize="14"/>
+ <fontDescription key="fontDescription" type="system" pointSize="14"/>
<state key="normal" title="set status message"/>
<connections>
<action selector="actionSetStatusMessage:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="p47-hL-BCM"/>
@@ -360,9 +359,9 @@
<constraints>
<constraint firstAttribute="trailing" secondItem="isA-Km-19L" secondAttribute="trailing" constant="10" id="6Tt-c6-ue6"/>
<constraint firstItem="isA-Km-19L" firstAttribute="leading" secondItem="rha-b0-jMR" secondAttribute="trailing" constant="10" id="GfS-dA-0gf"/>
- <constraint firstItem="3xN-e7-N0L" firstAttribute="top" secondItem="rha-b0-jMR" secondAttribute="bottom" constant="40" id="KVL-2d-xDr"/>
+ <constraint firstItem="3xN-e7-N0L" firstAttribute="top" secondItem="rha-b0-jMR" secondAttribute="bottom" constant="30" id="KVL-2d-xDr"/>
<constraint firstItem="rha-b0-jMR" firstAttribute="leading" secondItem="LVo-6E-efl" secondAttribute="leading" constant="10" id="L1H-XE-sur"/>
- <constraint firstItem="3CT-dJ-sEj" firstAttribute="top" secondItem="rha-b0-jMR" secondAttribute="bottom" constant="40" id="P6x-uB-lne"/>
+ <constraint firstItem="3CT-dJ-sEj" firstAttribute="top" secondItem="rha-b0-jMR" secondAttribute="bottom" constant="30" id="P6x-uB-lne"/>
<constraint firstItem="3CT-dJ-sEj" firstAttribute="leading" secondItem="LVo-6E-efl" secondAttribute="leading" constant="10" id="ceW-Ca-9iB"/>
<constraint firstAttribute="trailing" secondItem="3xN-e7-N0L" secondAttribute="trailing" constant="10" id="egg-HN-e1j"/>
<constraint firstItem="rha-b0-jMR" firstAttribute="top" secondItem="LVo-6E-efl" secondAttribute="top" constant="10" id="mZV-JR-YrU"/>
diff --git a/iOSClient/UserStatus/NCUserStatus.swift b/iOSClient/UserStatus/NCUserStatus.swift
index bd0cda98d..5312cac52 100644
--- a/iOSClient/UserStatus/NCUserStatus.swift
+++ b/iOSClient/UserStatus/NCUserStatus.swift
@@ -77,6 +77,9 @@ class NCUserStatus: UIViewController {
self.navigationItem.title = NSLocalizedString("_online_status_", comment: "")
+ view.backgroundColor = NCBrandColor.shared.systemBackground
+ tableView.backgroundColor = NCBrandColor.shared.systemBackground
+
buttonCancel.title = NSLocalizedString("_close_", comment: "")
onlineButton.layer.cornerRadius = 10
@@ -148,7 +151,7 @@ class NCUserStatus: UIViewController {
clearStatusMessageAfterText.addGestureRecognizer(tap)
clearStatusMessageAfterText.text = " " + NSLocalizedString("_dont_clear_", comment: "")
- clearStatusMessageButton.layer.cornerRadius = 15
+ clearStatusMessageButton.layer.cornerRadius = 20
clearStatusMessageButton.layer.masksToBounds = true
clearStatusMessageButton.layer.borderWidth = 0.5
clearStatusMessageButton.layer.borderColor = UIColor.darkGray.cgColor
@@ -156,7 +159,7 @@ class NCUserStatus: UIViewController {
clearStatusMessageButton.setTitle(NSLocalizedString("_clear_status_message_", comment: ""), for: .normal)
clearStatusMessageButton.setTitleColor(NCBrandColor.shared.label, for: .normal)
- setStatusMessageButton.layer.cornerRadius = 15
+ setStatusMessageButton.layer.cornerRadius = 20
setStatusMessageButton.layer.masksToBounds = true
setStatusMessageButton.backgroundColor = NCBrandColor.shared.brand
setStatusMessageButton.setTitle(NSLocalizedString("_set_status_message_", comment: ""), for: .normal)
@@ -165,12 +168,6 @@ class NCUserStatus: UIViewController {
getStatus()
}
- override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
- super.traitCollectionDidChange(previousTraitCollection)
-
- changeTheming()
- }
-
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
@@ -193,16 +190,6 @@ class NCUserStatus: UIViewController {
}
}
- // MARK: - Theming
-
- @objc func changeTheming() {
-
- view.backgroundColor = NCBrandColor.shared.systemBackground
- tableView.backgroundColor = NCBrandColor.shared.systemBackground
-
- tableView.reloadData()
- }
-
// MARK: ACTION
@IBAction func actionCancel(_ sender: UIBarButtonItem) {
diff --git a/iOSClient/Utility/CCUtility.h b/iOSClient/Utility/CCUtility.h
index 2d50ba80d..96ed5e538 100644
--- a/iOSClient/Utility/CCUtility.h
+++ b/iOSClient/Utility/CCUtility.h
@@ -148,9 +148,6 @@
+ (NSData *)getDatabaseEncryptionKey;
-+ (BOOL)getDisableLocalCacheAfterUpload;
-+ (void)setDisableLocalCacheAfterUpload:(BOOL)disable;
-
+ (BOOL)getLivePhoto;
+ (void)setLivePhoto:(BOOL)set;
@@ -168,9 +165,6 @@
+ (BOOL)getAudioMute;
+ (void)setAudioMute:(BOOL)set;
-+ (BOOL)getAutomaticDownloadImage;
-+ (void)setAutomaticDownloadImage:(BOOL)set;
-
+ (BOOL)getAccountRequest;
+ (void)setAccountRequest:(BOOL)set;
@@ -186,6 +180,12 @@
+ (BOOL)getRemovePhotoCameraRoll;
+ (void)setRemovePhotoCameraRoll:(BOOL)set;
++ (BOOL)getPresentErrorITMS90076;
++ (void)setPresentErrorITMS90076:(BOOL)set;
+
++ (BOOL)getPlayerPlay;
++ (void)setPlayerPlay:(BOOL)set;
+
// ===== Varius =====
+ (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL;
@@ -243,9 +243,6 @@
+ (NSString *)getMimeType:(NSString *)fileNameView;
-+ (void)extractImageVideoFromAssetLocalIdentifierForUpload:(tableMetadata *)metadataForUpload completion:(void(^)(tableMetadata *newMetadata, NSString* fileNamePath))completion;
-+ (void)extractLivePhotoAsset:(PHAsset*)asset filePath:(NSString *)filePath withCompletion:(void (^)(NSURL* url))completion;
-
// ===== E2E Encrypted =====
+ (NSString *)generateRandomIdentifier;
diff --git a/iOSClient/Utility/CCUtility.m b/iOSClient/Utility/CCUtility.m
index edc4b55b7..089365bf0 100644
--- a/iOSClient/Utility/CCUtility.m
+++ b/iOSClient/Utility/CCUtility.m
@@ -556,17 +556,6 @@
[UICKeyChainStore setData:data forKey:@"databaseEncryptionKey" service:NCGlobal.shared.serviceShareKeyChain];
}
-+ (BOOL)getDisableLocalCacheAfterUpload
-{
- return [[UICKeyChainStore stringForKey:@"disableLocalCacheAfterUpload" service:NCGlobal.shared.serviceShareKeyChain] boolValue];
-}
-
-+ (void)setDisableLocalCacheAfterUpload:(BOOL)disable
-{
- NSString *sDisable = (disable) ? @"true" : @"false";
- [UICKeyChainStore setString:sDisable forKey:@"disableLocalCacheAfterUpload" service:NCGlobal.shared.serviceShareKeyChain];
-}
-
+ (BOOL)getLivePhoto
{
NSString *valueString = [UICKeyChainStore stringForKey:@"livePhoto" service:NCGlobal.shared.serviceShareKeyChain];
@@ -659,17 +648,6 @@
[UICKeyChainStore setString:sSet forKey:@"audioMute" service:NCGlobal.shared.serviceShareKeyChain];
}
-+ (BOOL)getAutomaticDownloadImage
-{
- return [[UICKeyChainStore stringForKey:@"automaticDownloadImage" service:NCGlobal.shared.serviceShareKeyChain] boolValue];
-}
-
-+ (void)setAutomaticDownloadImage:(BOOL)set
-{
- NSString *sSet = (set) ? @"true" : @"false";
- [UICKeyChainStore setString:sSet forKey:@"automaticDownloadImage" service:NCGlobal.shared.serviceShareKeyChain];
-}
-
+ (BOOL)getAccountRequest
{
return [[UICKeyChainStore stringForKey:@"accountRequest" service:NCGlobal.shared.serviceShareKeyChain] boolValue];
@@ -745,17 +723,39 @@
[UICKeyChainStore setString:sSet forKey:@"removePhotoCameraRoll" service:NCGlobal.shared.serviceShareKeyChain];
}
++ (BOOL)getPresentErrorITMS90076
+{
+ return [[UICKeyChainStore stringForKey:@"errorITMS90076" service:NCGlobal.shared.serviceShareKeyChain] boolValue];
+}
+
++ (void)setPresentErrorITMS90076:(BOOL)set
+{
+ NSString *sSet = (set) ? @"true" : @"false";
+ [UICKeyChainStore setString:sSet forKey:@"errorITMS90076" service:NCGlobal.shared.serviceShareKeyChain];
+}
+
++ (BOOL)getPlayerPlay
+{
+ return [[UICKeyChainStore stringForKey:@"playerPlay" service:NCGlobal.shared.serviceShareKeyChain] boolValue];
+}
+
++ (void)setPlayerPlay:(BOOL)set
+{
+ NSString *sSet = (set) ? @"true" : @"false";
+ [UICKeyChainStore setString:sSet forKey:@"playerPlay" service:NCGlobal.shared.serviceShareKeyChain];
+}
+
#pragma --------------------------------------------------------------------------------------------
#pragma mark ===== Various =====
#pragma --------------------------------------------------------------------------------------------
+ (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
-{
- assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);
-
+{
NSError *error = nil;
BOOL success = [URL setResourceValue:[NSNumber numberWithBool: YES] forKey: NSURLIsExcludedFromBackupKey error: &error];
- if(!success){
+ if(success) {
+ NSLog(@"Excluding %@ from backup", [URL lastPathComponent]);
+ } else {
NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error);
}
@@ -1034,17 +1034,17 @@
path = NSTemporaryDirectory();
if (![[NSFileManager defaultManager] fileExistsAtPath:path])
[[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
-
- // create Directory Background
- path = [[dirGroup URLByAppendingPathComponent:NCGlobal.shared.appBackground] path];
- if (![[NSFileManager defaultManager] fileExistsAtPath:path])
- [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
-
+
// Directory Excluded From Backup
[CCUtility addSkipBackupAttributeToItemAtURL:[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]];
[CCUtility addSkipBackupAttributeToItemAtURL:[[CCUtility getDirectoryGroup] URLByAppendingPathComponent:NCGlobal.shared.directoryProviderStorage]];
+ [CCUtility addSkipBackupAttributeToItemAtURL:[[CCUtility getDirectoryGroup] URLByAppendingPathComponent:NCGlobal.shared.appApplicationSupport]];
+
+ [CCUtility addSkipBackupAttributeToItemAtURL:[[CCUtility getDirectoryGroup] URLByAppendingPathComponent:NCGlobal.shared.appCertificates]];
+ [CCUtility addSkipBackupAttributeToItemAtURL:[[CCUtility getDirectoryGroup] URLByAppendingPathComponent:NCGlobal.shared.appDatabaseNextcloud]];
+ [CCUtility addSkipBackupAttributeToItemAtURL:[[CCUtility getDirectoryGroup] URLByAppendingPathComponent:NCGlobal.shared.appScan]];
[CCUtility addSkipBackupAttributeToItemAtURL:[[CCUtility getDirectoryGroup] URLByAppendingPathComponent:NCGlobal.shared.appUserData]];
-
+
#ifdef DEBUG
NSLog(@"[LOG] Copy DB on Documents directory");
NSString *atPathDB = [NSString stringWithFormat:@"%@/nextcloud.realm", [[dirGroup URLByAppendingPathComponent:[[NCGlobal shared] appDatabaseNextcloud]] path]];
@@ -1150,14 +1150,22 @@
+ (BOOL)fileProviderStorageExists:(tableMetadata *)metadata
{
- NSString *fileNamePath = [self getDirectoryProviderStorageOcId:metadata.ocId fileNameView:metadata.fileNameView];
- if (![[NSFileManager defaultManager] fileExistsAtPath:fileNamePath]) {
- return false;
- }
+ NSString *fileNameViewPath = [self getDirectoryProviderStorageOcId:metadata.ocId fileNameView:metadata.fileNameView];
+ NSString *fileNamePath = [self getDirectoryProviderStorageOcId:metadata.ocId fileNameView:metadata.fileName];
+ BOOL isFolderEncrypted = [self isFolderEncrypted:metadata.serverUrl e2eEncrypted:metadata.e2eEncrypted account:metadata.account urlBase:metadata.urlBase];
- unsigned long long fileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:fileNamePath error:nil] fileSize];
- if (fileSize > 0) return true;
- else return false;
+ unsigned long long fileNameViewSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:fileNameViewPath error:nil] fileSize];
+ unsigned long long fileNameSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:fileNamePath error:nil] fileSize];
+
+ if (isFolderEncrypted == true) {
+ if (fileNameSize == metadata.size && fileNameViewSize > 0) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return fileNameViewSize == metadata.size;
+ }
}
+ (int64_t)fileProviderStorageSize:(NSString *)ocId fileNameView:(NSString *)fileNameView
@@ -1344,164 +1352,6 @@
return path;
}
-+ (void)extractImageVideoFromAssetLocalIdentifierForUpload:(tableMetadata *)metadataForUpload completion:(void(^)(tableMetadata *metadata, NSString* fileNamePath))completion
-{
- if (metadataForUpload == nil) {
- return completion(nil, nil);
- }
-
- tableMetadata *metadata = [[NCManageDatabase shared] copyObjectWithMetadata:metadataForUpload];
-
- PHFetchResult *result = [PHAsset fetchAssetsWithLocalIdentifiers:@[metadata.assetLocalIdentifier] options:nil];
- if (!result.count) {
- return completion(nil, nil);
- }
-
- PHAsset *asset = result[0];
- NSDate *creationDate = asset.creationDate;
- NSDate *modificationDate = asset.modificationDate;
-
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
-
- // IMAGE
- if (asset.mediaType == PHAssetMediaTypeImage) {
-
- PHImageRequestOptions *options = [PHImageRequestOptions new];
- options.networkAccessAllowed = YES;
- options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
- options.synchronous = YES;
- options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
-
- NSLog(@"cacheAsset: %f", progress);
-
- if (error) {
- [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:NCGlobal.shared.notificationCenterUploadedFile object:nil userInfo:@{@"ocId": metadata.ocId, @"errorCode": @(error.code), @"errorDescription": [NSString stringWithFormat:@"Image request iCloud failed [%@]", error.description]}];
- return completion(nil, nil);
- }
- };
-
- NSString *extensionAsset = [[[asset valueForKey:@"filename"] pathExtension] uppercaseString];
-
- //raw image will always ignore any edits made to the photo if compatibility is false
- if ([extensionAsset isEqualToString:@"DNG"]) {
- options.version = PHImageRequestOptionsVersionOriginal;
- }
-
- [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
-
- NSError *error = nil;
- NSString *fileName = metadata.fileNameView;
-
- if (([extensionAsset isEqualToString:@"HEIC"] || [extensionAsset isEqualToString:@"DNG"]) && [CCUtility getFormatCompatibility]) {
-
- CIImage *ciImage = [CIImage imageWithData:imageData];
- CIContext *context = [CIContext context];
- imageData = [context JPEGRepresentationOfImage:ciImage colorSpace:ciImage.colorSpace options:@{}];
-
- NSString *fileNameJPEG = [[metadata.fileName lastPathComponent] stringByDeletingPathExtension];
- fileName = [fileNameJPEG stringByAppendingString:@".jpg"];
- metadata.contentType = @"image/jpeg";
- metadata.ext = @"jpg";
- }
-
- NSString *fileNamePath = [NSTemporaryDirectory() stringByAppendingString:fileName];
-
- [[NSFileManager defaultManager]removeItemAtPath:fileNamePath error:nil];
- [imageData writeToFile:fileNamePath options:NSDataWritingAtomic error:&error];
-
- if (metadata.e2eEncrypted) {
- metadata.fileNameView = fileName;
- } else {
- metadata.fileNameView = fileName;
- metadata.fileName = fileName;
- }
-
- metadata.creationDate = creationDate;
- metadata.date = modificationDate;
- metadata.size = [[NCUtilityFileSystem shared] getFileSizeWithFilePath:fileNamePath];
-
- dispatch_async(dispatch_get_main_queue(), ^{
- completion(metadata, fileNamePath);
- });
- }];
- }
-
- // VIDEO
- if (asset.mediaType == PHAssetMediaTypeVideo) {
-
- PHVideoRequestOptions *options = [PHVideoRequestOptions new];
- options.networkAccessAllowed = YES;
- options.version = PHVideoRequestOptionsVersionOriginal;
- options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
-
- NSLog(@"cacheAsset: %f", progress);
-
- if (error) {
- [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:NCGlobal.shared.notificationCenterUploadedFile object:nil userInfo:@{@"ocId": metadata.ocId, @"errorCode": @(error.code), @"errorDescription": [NSString stringWithFormat:@"Video request iCloud failed [%@]", error.description]}];
- completion(nil, nil);
- }
- };
-
- [[PHImageManager defaultManager] requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {
-
- if ([asset isKindOfClass:[AVURLAsset class]]) {
-
- NSString *fileNamePath = [NSTemporaryDirectory() stringByAppendingString:metadata.fileNameView];
- NSURL *fileNamePathURL = [[NSURL alloc] initFileURLWithPath:fileNamePath];
- NSError *error = nil;
- //NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys: modificationDate, NSFileModificationDate, creationDate, NSFileCreationDate, NULL];
-
- [[NSFileManager defaultManager] removeItemAtURL:fileNamePathURL error:nil];
- [[NSFileManager defaultManager] copyItemAtURL:[(AVURLAsset *)asset URL] toURL:fileNamePathURL error:&error];
- //[[NSFileManager defaultManager] setAttributes: attributes ofItemAtPath:fileNamePath error:nil];
-
- dispatch_async(dispatch_get_main_queue(), ^{
-
- if (error) {
- [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:NCGlobal.shared.notificationCenterUploadedFile object:nil userInfo:@{@"ocId": metadata.ocId, @"errorCode": @(error.code), @"errorDescription": [NSString stringWithFormat:@"Video request iCloud failed [%@]", error.description]}];
- completion(nil, nil);
- } else {
- metadata.creationDate = creationDate;
- metadata.date = modificationDate;
- metadata.size = [[NCUtilityFileSystem shared] getFileSizeWithFilePath:fileNamePath];
- completion(metadata, fileNamePath);
- }
- });
- }
- }];
- }
- });
-}
-
-+ (void)extractLivePhotoAsset:(PHAsset*)asset filePath:(NSString *)filePath withCompletion:(void (^)(NSURL* url))completion
-{
- [CCUtility removeFileAtPath:filePath];
- NSURL *fileUrl = [NSURL fileURLWithPath:filePath];
- PHLivePhotoRequestOptions *options = [PHLivePhotoRequestOptions new];
- options.deliveryMode = PHImageRequestOptionsDeliveryModeFastFormat;
- options.networkAccessAllowed = YES;
-
- [[PHImageManager defaultManager] requestLivePhotoForAsset:asset targetSize:[UIScreen mainScreen].bounds.size contentMode:PHImageContentModeDefault options:options resultHandler:^(PHLivePhoto * _Nullable livePhoto, NSDictionary * _Nullable info) {
- if (livePhoto) {
- NSArray *assetResources = [PHAssetResource assetResourcesForLivePhoto:livePhoto];
- PHAssetResource *videoResource = nil;
- for(PHAssetResource *resource in assetResources){
- if (resource.type == PHAssetResourceTypePairedVideo) {
- videoResource = resource;
- break;
- }
- }
- if(videoResource){
- [[PHAssetResourceManager defaultManager] writeDataForAssetResource:videoResource toFile:fileUrl options:nil completionHandler:^(NSError * _Nullable error) {
- if (!error) {
- completion(fileUrl);
- } else { completion(nil); }
- }];
- } else { completion(nil); }
- } else { completion(nil); }
- }];
-}
-
#pragma --------------------------------------------------------------------------------------------
#pragma mark ===== E2E Encrypted =====
#pragma --------------------------------------------------------------------------------------------
@@ -1533,7 +1383,7 @@
if (directory.e2eEncrypted == true) {
return true;
}
- serverUrl = [[NCUtilityFileSystem shared] deletingLastPathComponentWithAccount:account serverUrl:serverUrl];
+ serverUrl = [[NCUtilityFileSystem shared] deletingLastPathComponentWithAccount:account serverUrl:serverUrl];
directory = [[NCManageDatabase shared] getTableDirectoryWithPredicate:[NSPredicate predicateWithFormat:@"account == %@ AND serverUrl == %@", account, serverUrl]];
}
diff --git a/iOSClient/Utility/NCActivityIndicator.swift b/iOSClient/Utility/NCActivityIndicator.swift
new file mode 100644
index 000000000..8af4760e3
--- /dev/null
+++ b/iOSClient/Utility/NCActivityIndicator.swift
@@ -0,0 +1,148 @@
+//
+// NCActivityIndicator.swift
+// Nextcloud
+//
+// Created by Marino Faggiana on 11/08/22.
+// Copyright © 2022 Marino Faggiana. All rights reserved.
+//
+// Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+import Foundation
+import UIKit
+
+class NCActivityIndicator: NSObject {
+ @objc static let shared: NCActivityIndicator = {
+ let instance = NCActivityIndicator()
+ return instance
+ }()
+
+ private var activityIndicator: UIActivityIndicatorView?
+ private var viewActivityIndicator: UIView?
+ private var viewBackgroundActivityIndicator: UIView?
+
+ @objc func startActivity(backgroundView: UIView?, style: UIActivityIndicatorView.Style) {
+ start(backgroundView: backgroundView, style: style)
+ }
+
+ func start(backgroundView: UIView? = nil, bottom: CGFloat? = nil, top: CGFloat? = nil, style: UIActivityIndicatorView.Style = .whiteLarge) {
+
+ if self.activityIndicator != nil { stop() }
+
+ DispatchQueue.main.async {
+
+ self.activityIndicator = UIActivityIndicatorView(style: style)
+ guard let activityIndicator = self.activityIndicator, self.viewBackgroundActivityIndicator == nil else { return }
+
+ activityIndicator.color = NCBrandColor.shared.label
+ activityIndicator.hidesWhenStopped = true
+ activityIndicator.translatesAutoresizingMaskIntoConstraints = false
+
+ var sizeActivityIndicator = activityIndicator.frame.height
+ if backgroundView == nil {
+ sizeActivityIndicator += 50
+ }
+
+ self.viewActivityIndicator = UIView(frame: CGRect(x: 0, y: 0, width: sizeActivityIndicator, height: sizeActivityIndicator))
+ self.viewActivityIndicator?.translatesAutoresizingMaskIntoConstraints = false
+ self.viewActivityIndicator?.layer.cornerRadius = 10
+ self.viewActivityIndicator?.layer.masksToBounds = true
+ self.viewActivityIndicator?.backgroundColor = .clear
+
+ #if !EXTENSION
+ if backgroundView == nil {
+ if let window = UIApplication.shared.keyWindow {
+ self.viewBackgroundActivityIndicator?.removeFromSuperview()
+ self.viewBackgroundActivityIndicator = NCViewActivityIndicator(frame: window.bounds)
+ window.addSubview(self.viewBackgroundActivityIndicator!)
+ self.viewBackgroundActivityIndicator?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+ self.viewBackgroundActivityIndicator?.backgroundColor = .clear
+ }
+ } else {
+ self.viewBackgroundActivityIndicator = backgroundView
+ }
+ #else
+ self.viewBackgroundActivityIndicator = backgroundView
+ #endif
+
+ // VIEW ACTIVITY INDICATOR
+
+ guard let viewActivityIndicator = self.viewActivityIndicator else { return }
+ viewActivityIndicator.addSubview(activityIndicator)
+
+ if backgroundView == nil {
+ let blurEffect = UIBlurEffect(style: .regular)
+ let blurEffectView = UIVisualEffectView(effect: blurEffect)
+ blurEffectView.frame = viewActivityIndicator.frame
+ viewActivityIndicator.insertSubview(blurEffectView, at: 0)
+ }
+
+ NSLayoutConstraint.activate([
+ viewActivityIndicator.widthAnchor.constraint(equalToConstant: sizeActivityIndicator),
+ viewActivityIndicator.heightAnchor.constraint(equalToConstant: sizeActivityIndicator),
+ activityIndicator.centerXAnchor.constraint(equalTo: viewActivityIndicator.centerXAnchor),
+ activityIndicator.centerYAnchor.constraint(equalTo: viewActivityIndicator.centerYAnchor)
+ ])
+
+ // BACKGROUD VIEW ACTIVITY INDICATOR
+
+ guard let viewBackgroundActivityIndicator = self.viewBackgroundActivityIndicator else { return }
+ viewBackgroundActivityIndicator.addSubview(viewActivityIndicator)
+
+ if let constant = bottom {
+ viewActivityIndicator.bottomAnchor.constraint(equalTo: viewBackgroundActivityIndicator.bottomAnchor, constant: constant).isActive = true
+ } else if let constant = top {
+ viewActivityIndicator.topAnchor.constraint(equalTo: viewBackgroundActivityIndicator.topAnchor, constant: constant).isActive = true
+ } else {
+ viewActivityIndicator.centerYAnchor.constraint(equalTo: viewBackgroundActivityIndicator.centerYAnchor).isActive = true
+ }
+ viewActivityIndicator.centerXAnchor.constraint(equalTo: viewBackgroundActivityIndicator.centerXAnchor).isActive = true
+
+ activityIndicator.startAnimating()
+ }
+ }
+
+ @objc func stop() {
+
+ DispatchQueue.main.async {
+
+ self.activityIndicator?.stopAnimating()
+ self.activityIndicator?.removeFromSuperview()
+ self.activityIndicator = nil
+
+ self.viewActivityIndicator?.removeFromSuperview()
+ self.viewActivityIndicator = nil
+
+ if self.viewBackgroundActivityIndicator is NCViewActivityIndicator {
+ self.viewBackgroundActivityIndicator?.removeFromSuperview()
+ }
+ self.viewBackgroundActivityIndicator = nil
+ }
+ }
+}
+
+class NCViewActivityIndicator: UIView {
+
+ // MARK: - View Life Cycle
+
+ override init(frame: CGRect) {
+ super.init(frame: frame)
+ }
+
+ required init?(coder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+}
diff --git a/iOSClient/Utility/NCContentPresenter.swift b/iOSClient/Utility/NCContentPresenter.swift
index ffe6c5396..79061d600 100644
--- a/iOSClient/Utility/NCContentPresenter.swift
+++ b/iOSClient/Utility/NCContentPresenter.swift
@@ -137,29 +137,37 @@ class NCContentPresenter: NSObject {
if SwiftEntryKit.isCurrentlyDisplaying(entryNamed: text) { return }
- var attributes = EKAttributes.topNote
+ DispatchQueue.main.async {
+ var attributes = EKAttributes.topNote
- attributes.windowLevel = .normal
- attributes.displayDuration = delay
- attributes.name = text
- if let color = color {
- attributes.entryBackground = .color(color: EKColor(color))
- }
- if let type = type {
- attributes.entryBackground = .color(color: EKColor(getBackgroundColorFromType(type)))
+ attributes.windowLevel = .normal
+ attributes.displayDuration = delay
+ attributes.name = text
+ if let color = color {
+ attributes.entryBackground = .color(color: EKColor(color))
+ }
+ if let type = type {
+ attributes.entryBackground = .color(color: EKColor(self.getBackgroundColorFromType(type)))
+ }
+ attributes.precedence = .override(priority: priority, dropEnqueuedEntries: dropEnqueuedEntries)
+
+ let style = EKProperty.LabelStyle(font: MainFont.light.with(size: 14), color: .white, alignment: .center)
+ let labelContent = EKProperty.LabelContent(text: text, style: style)
+
+ if let image = image {
+ let imageContent = EKProperty.ImageContent(image: image, size: CGSize(width: 17, height: 17))
+ let contentView = EKImageNoteMessageView(with: labelContent, imageContent: imageContent)
+ SwiftEntryKit.display(entry: contentView, using: attributes)
+ } else {
+ let contentView = EKNoteMessageView(with: labelContent)
+ SwiftEntryKit.display(entry: contentView, using: attributes)
+ }
}
- attributes.precedence = .override(priority: priority, dropEnqueuedEntries: dropEnqueuedEntries)
-
- let style = EKProperty.LabelStyle(font: MainFont.light.with(size: 14), color: .white, alignment: .center)
- let labelContent = EKProperty.LabelContent(text: text, style: style)
+ }
- if let image = image {
- let imageContent = EKProperty.ImageContent(image: image, size: CGSize(width: 17, height: 17))
- let contentView = EKImageNoteMessageView(with: labelContent, imageContent: imageContent)
- DispatchQueue.main.async { SwiftEntryKit.display(entry: contentView, using: attributes) }
- } else {
- let contentView = EKNoteMessageView(with: labelContent)
- DispatchQueue.main.async { SwiftEntryKit.display(entry: contentView, using: attributes) }
+ func dismiss(after: TimeInterval = 0) {
+ DispatchQueue.main.asyncAfter(deadline: .now() + after) {
+ SwiftEntryKit.dismiss()
}
}
diff --git a/iOSClient/Utility/NCUserBaseUrl.swift b/iOSClient/Utility/NCUserBaseUrl.swift
index 8bb5e6576..f92b2ae9f 100644
--- a/iOSClient/Utility/NCUserBaseUrl.swift
+++ b/iOSClient/Utility/NCUserBaseUrl.swift
@@ -1,5 +1,5 @@
//
-// NCUtility.swift
+// NCUserBaseUrl.swift
// Nextcloud
//
// Created by Henrik Storch on 22.11.21.
@@ -27,10 +27,14 @@ import Foundation
var user: String { get }
var urlBase: String { get }
var account: String { get }
+ var userId: String { get }
}
public extension NCUserBaseUrl {
var userBaseUrl: String {
user + "-" + (URL(string: urlBase)?.host ?? "")
}
+ var userAccount: String {
+ user + " " + urlBase
+ }
}
diff --git a/iOSClient/Utility/NCUtility+Image.swift b/iOSClient/Utility/NCUtility+Image.swift
index a56f96e91..ae79f54db 100644
--- a/iOSClient/Utility/NCUtility+Image.swift
+++ b/iOSClient/Utility/NCUtility+Image.swift
@@ -33,7 +33,7 @@ extension NCUtility {
}
if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue && !metadata.hasPreview {
- NCUtility.shared.createImageFrom(fileName: metadata.fileNameView, ocId: metadata.ocId, etag: metadata.etag, classFile: metadata.classFile)
+ NCUtility.shared.createImageFrom(fileNameView: metadata.fileNameView, ocId: metadata.ocId, etag: metadata.etag, classFile: metadata.classFile)
}
if CCUtility.fileProviderStoragePreviewIconExists(metadata.ocId, etag: metadata.etag) {
@@ -62,7 +62,7 @@ extension NCUtility {
if ext == "GIF" {
if !FileManager().fileExists(atPath: previewPath) {
- NCUtility.shared.createImageFrom(fileName: metadata.fileNameView, ocId: metadata.ocId, etag: metadata.etag, classFile: metadata.classFile)
+ NCUtility.shared.createImageFrom(fileNameView: metadata.fileNameView, ocId: metadata.ocId, etag: metadata.etag, classFile: metadata.classFile)
}
image = UIImage.animatedImage(withAnimatedGIFURL: URL(fileURLWithPath: imagePath))
} else if ext == "SVG" {
@@ -82,7 +82,7 @@ extension NCUtility {
return nil
}
} else {
- NCUtility.shared.createImageFrom(fileName: metadata.fileNameView, ocId: metadata.ocId, etag: metadata.etag, classFile: metadata.classFile)
+ NCUtility.shared.createImageFrom(fileNameView: metadata.fileNameView, ocId: metadata.ocId, etag: metadata.etag, classFile: metadata.classFile)
image = UIImage(contentsOfFile: imagePath)
}
}
diff --git a/iOSClient/Utility/NCUtility.swift b/iOSClient/Utility/NCUtility.swift
index 191615981..a2fb5c331 100644
--- a/iOSClient/Utility/NCUtility.swift
+++ b/iOSClient/Utility/NCUtility.swift
@@ -28,8 +28,8 @@ import NCCommunication
import PDFKit
import Accelerate
import CoreMedia
-
-// MARK: - NCUtility
+import Queuer
+import Photos
class NCUtility: NSObject {
@objc static let shared: NCUtility = {
@@ -37,13 +37,9 @@ class NCUtility: NSObject {
return instance
}()
- private var activityIndicator: UIActivityIndicatorView?
- private var viewActivityIndicator: UIView?
- private var viewBackgroundActivityIndicator: UIView?
-
func setLayoutForView(key: String, serverUrl: String, layoutForView: NCGlobal.layoutForViewType) {
- let string = layoutForView.layout + "|" + layoutForView.sort + "|" + "\(layoutForView.ascending)" + "|" + layoutForView.groupBy + "|" + "\(layoutForView.directoryOnTop)" + "|" + layoutForView.titleButtonHeader + "|" + "\(layoutForView.itemForLine)" + "|" + layoutForView.imageBackgroud + "|" + layoutForView.imageBackgroudContentMode
+ let string = layoutForView.layout + "|" + layoutForView.sort + "|" + "\(layoutForView.ascending)" + "|" + layoutForView.groupBy + "|" + "\(layoutForView.directoryOnTop)" + "|" + layoutForView.titleButtonHeader + "|" + "\(layoutForView.itemForLine)"
var keyStore = key
if serverUrl != "" {
@@ -63,20 +59,10 @@ class NCUtility: NSObject {
}
}
- func setBackgroundImageForView(key: String, serverUrl: String, imageBackgroud: String, imageBackgroudContentMode: String) {
-
- var layoutForView: NCGlobal.layoutForViewType = NCUtility.shared.getLayoutForView(key: key, serverUrl: serverUrl)
-
- layoutForView.imageBackgroud = imageBackgroud
- layoutForView.imageBackgroudContentMode = imageBackgroudContentMode
-
- setLayoutForView(key: key, serverUrl: serverUrl, layoutForView: layoutForView)
- }
-
func getLayoutForView(key: String, serverUrl: String, sort: String = "fileName", ascending: Bool = true, titleButtonHeader: String = "_sorted_by_name_a_z_") -> (NCGlobal.layoutForViewType) {
var keyStore = key
- var layoutForView: NCGlobal.layoutForViewType = NCGlobal.layoutForViewType(layout: NCGlobal.shared.layoutList, sort: sort, ascending: ascending, groupBy: "none", directoryOnTop: true, titleButtonHeader: titleButtonHeader, itemForLine: 3, imageBackgroud: "", imageBackgroudContentMode: "")
+ var layoutForView: NCGlobal.layoutForViewType = NCGlobal.layoutForViewType(layout: NCGlobal.shared.layoutList, sort: sort, ascending: ascending, groupBy: "none", directoryOnTop: true, titleButtonHeader: titleButtonHeader, itemForLine: 3)
if serverUrl != "" {
keyStore = serverUrl
@@ -97,13 +83,6 @@ class NCUtility: NSObject {
layoutForView.directoryOnTop = NSString(string: array[4]).boolValue
layoutForView.titleButtonHeader = array[5]
layoutForView.itemForLine = Int(NSString(string: array[6]).intValue)
- // version 2
- if array.count > 8 {
- layoutForView.imageBackgroud = array[7]
- layoutForView.imageBackgroudContentMode = array[8]
- // layoutForView.lightColorBackground = array[9] WAS STRING
- // layoutForView.darkColorBackground = array[10] WAS STRING
- }
}
return layoutForView
@@ -400,6 +379,150 @@ class NCUtility: NSObject {
// MARK: -
+ func extractImageVideoFromAssetLocalIdentifier(metadata: tableMetadata, modifyMetadataForUpload: Bool, completion: @escaping (_ metadata: tableMetadata?, _ fileNamePath: String?, _ error: Bool) -> ()) {
+
+ var fileNamePath: String?
+ let metadata = tableMetadata.init(value: metadata)
+ let chunckSize = CCUtility.getChunkSize() * 1000000
+ var compatibilityFormat: Bool = false
+
+ func callCompletion(error: Bool) {
+ if error {
+ completion(nil, nil, true)
+ } else {
+ var metadataReturn = metadata
+ if modifyMetadataForUpload {
+ metadata.chunk = chunckSize != 0 && metadata.size > chunckSize
+ metadata.e2eEncrypted = CCUtility.isFolderEncrypted(metadata.serverUrl, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase)
+ metadata.isExtractFile = true
+ if let metadata = NCManageDatabase.shared.addMetadata(metadata) {
+ metadataReturn = metadata
+ }
+ }
+ completion(metadataReturn, fileNamePath, error)
+ }
+ }
+
+ let fetchAssets = PHAsset.fetchAssets(withLocalIdentifiers: [metadata.assetLocalIdentifier], options: nil)
+ guard fetchAssets.count > 0, let asset = fetchAssets.firstObject, let extensionAsset = (asset.value(forKey: "filename") as? NSString)?.pathExtension.uppercased() else {
+ return callCompletion(error: true)
+ }
+
+ if asset.mediaType == PHAssetMediaType.image && (extensionAsset == "HEIC" || extensionAsset == "DNG") && CCUtility.getFormatCompatibility() {
+ let fileName = (metadata.fileNameView as NSString).deletingPathExtension + ".jpg"
+ metadata.contentType = "image/jpeg"
+ metadata.ext = "jpg"
+ fileNamePath = NSTemporaryDirectory() + fileName
+ metadata.fileNameView = fileName
+ if !metadata.e2eEncrypted {
+ metadata.fileName = fileName
+ }
+ compatibilityFormat = true
+ } else {
+ fileNamePath = NSTemporaryDirectory() + metadata.fileNameView
+ }
+ guard let fileNamePath = fileNamePath, let creationDate = asset.creationDate, let modificationDate = asset.modificationDate else {
+ return callCompletion(error: true)
+ }
+
+ if asset.mediaType == PHAssetMediaType.image {
+
+ let options = PHImageRequestOptions()
+ options.isNetworkAccessAllowed = true
+ options.deliveryMode = PHImageRequestOptionsDeliveryMode.highQualityFormat
+ options.isSynchronous = true
+ if extensionAsset == "DNG" {
+ options.version = PHImageRequestOptionsVersion.original
+ }
+ options.progressHandler = { (progress, error, stop, info) in
+ print(progress)
+ if error != nil { return callCompletion(error: true) }
+ }
+
+ PHImageManager.default().requestImageData(for: asset, options: options) { data, dataUI, orientation, info in
+ guard var data = data else { return callCompletion(error: true) }
+ if compatibilityFormat {
+ guard let ciImage = CIImage.init(data: data), let colorSpace = ciImage.colorSpace, let dataJPEG = CIContext().jpegRepresentation(of: ciImage, colorSpace: colorSpace) else { return callCompletion(error: true) }
+ data = dataJPEG
+ }
+ NCUtilityFileSystem.shared.deleteFile(filePath: fileNamePath)
+ do {
+ try data.write(to: URL(fileURLWithPath: fileNamePath), options: .atomic)
+ } catch {
+ return callCompletion(error: true)
+ }
+ metadata.creationDate = creationDate as NSDate
+ metadata.date = modificationDate as NSDate
+ metadata.size = NCUtilityFileSystem.shared.getFileSize(filePath: fileNamePath)
+ return callCompletion(error: false)
+ }
+
+ } else if asset.mediaType == PHAssetMediaType.video {
+
+ let options = PHVideoRequestOptions()
+ options.isNetworkAccessAllowed = true
+ options.version = PHVideoRequestOptionsVersion.current
+ options.progressHandler = { (progress, error, stop, info) in
+ print(progress)
+ if error != nil { return callCompletion(error: true) }
+ }
+
+ PHImageManager.default().requestAVAsset(forVideo: asset, options: options) { asset, audioMix, info in
+ guard let asset = asset as? AVURLAsset else { return callCompletion(error: true) }
+ NCUtilityFileSystem.shared.deleteFile(filePath: fileNamePath)
+ do {
+ try FileManager.default.copyItem(at: asset.url, to: URL(fileURLWithPath: fileNamePath))
+ } catch {
+ return callCompletion(error: true)
+ }
+ metadata.creationDate = creationDate as NSDate
+ metadata.date = modificationDate as NSDate
+ metadata.size = NCUtilityFileSystem.shared.getFileSize(filePath: fileNamePath)
+ return callCompletion(error: false)
+ }
+ } else {
+ return callCompletion(error: true)
+ }
+ }
+
+ func createMetadataLivePhotoFromMetadata(_ metadata: tableMetadata, asset: PHAsset?, completion: @escaping (_ metadata: tableMetadata?) -> ()) {
+
+ guard let asset = asset else { return completion(nil) }
+ let options = PHLivePhotoRequestOptions()
+ options.deliveryMode = PHImageRequestOptionsDeliveryMode.fastFormat
+ options.isNetworkAccessAllowed = true
+ let chunckSize = CCUtility.getChunkSize() * 1000000
+ let ocId = NSUUID().uuidString
+ let fileName = (metadata.fileName as NSString).deletingPathExtension + ".mov"
+ let fileNamePath = CCUtility.getDirectoryProviderStorageOcId(ocId, fileNameView: fileName)!
+
+ PHImageManager.default().requestLivePhoto(for: asset, targetSize: UIScreen.main.bounds.size, contentMode: PHImageContentMode.default, options: options) { livePhoto, info in
+ guard let livePhoto = livePhoto else { return completion(nil) }
+ var videoResource: PHAssetResource?
+ for resource in PHAssetResource.assetResources(for: livePhoto) {
+ if resource.type == PHAssetResourceType.pairedVideo {
+ videoResource = resource
+ break
+ }
+ }
+ guard let videoResource = videoResource else { return completion(nil) }
+ NCUtilityFileSystem.shared.deleteFile(filePath: fileNamePath)
+ PHAssetResourceManager.default().writeData(for: videoResource, toFile: URL(fileURLWithPath: fileNamePath), options: nil) { error in
+ if error != nil { return completion(nil) }
+ let metadataLivePhoto = NCManageDatabase.shared.createMetadata(account: metadata.account, user: metadata.user, userId: metadata.userId, fileName: fileName, fileNameView: fileName, ocId: ocId, serverUrl: metadata.serverUrl, urlBase: metadata.urlBase, url: "", contentType: "", isLivePhoto: true)
+ metadataLivePhoto.classFile = NCCommunicationCommon.typeClassFile.video.rawValue
+ metadataLivePhoto.e2eEncrypted = metadata.e2eEncrypted
+ metadataLivePhoto.isExtractFile = true
+ metadataLivePhoto.session = metadata.session
+ metadataLivePhoto.sessionSelector = metadata.sessionSelector
+ metadataLivePhoto.size = NCUtilityFileSystem.shared.getFileSize(filePath: fileNamePath)
+ metadataLivePhoto.status = metadata.status
+ metadataLivePhoto.chunk = chunckSize != 0 && metadata.size > chunckSize
+ return completion(NCManageDatabase.shared.addMetadata(metadataLivePhoto))
+ }
+ }
+ }
+
func imageFromVideo(url: URL, at time: TimeInterval) -> UIImage? {
let asset = AVURLAsset(url: url)
@@ -444,16 +567,15 @@ class NCUtility: NSObject {
}
}
- func createImageFrom(fileName: String, ocId: String, etag: String, classFile: String) {
+ func createImageFrom(fileNameView: String, ocId: String, etag: String, classFile: String) {
var originalImage, scaleImagePreview, scaleImageIcon: UIImage?
- let fileNamePath = CCUtility.getDirectoryProviderStorageOcId(ocId, fileNameView: fileName)!
+ let fileNamePath = CCUtility.getDirectoryProviderStorageOcId(ocId, fileNameView: fileNameView)!
let fileNamePathPreview = CCUtility.getDirectoryProviderStoragePreviewOcId(ocId, etag: etag)!
let fileNamePathIcon = CCUtility.getDirectoryProviderStorageIconOcId(ocId, etag: etag)!
- if FileManager().fileExists(atPath: fileNamePathPreview) && FileManager().fileExists(atPath: fileNamePathIcon) { return }
- if CCUtility.fileProviderStorageSize(ocId, fileNameView: fileName) != 0 { return }
+ if CCUtility.fileProviderStorageSize(ocId, fileNameView: fileNameView) > 0 && FileManager().fileExists(atPath: fileNamePathPreview) && FileManager().fileExists(atPath: fileNamePathIcon) { return }
if classFile != NCCommunicationCommon.typeClassFile.image.rawValue && classFile != NCCommunicationCommon.typeClassFile.video.rawValue { return }
if classFile == NCCommunicationCommon.typeClassFile.image.rawValue {
@@ -478,10 +600,14 @@ class NCUtility: NSObject {
}
}
- @objc func getVersionApp() -> String {
+ @objc func getVersionApp(withBuild: Bool = true) -> String {
if let dictionary = Bundle.main.infoDictionary {
if let version = dictionary["CFBundleShortVersionString"], let build = dictionary["CFBundleVersion"] {
- return "\(version).\(build)"
+ if withBuild {
+ return "\(version).\(build)"
+ } else {
+ return "\(version)"
+ }
}
}
return ""
@@ -576,104 +702,6 @@ class NCUtility: NSObject {
return avatarImage
}
- // MARK: -
-
- @objc func startActivityIndicator(backgroundView: UIView?, blurEffect: Bool, bottom: CGFloat = 0, style: UIActivityIndicatorView.Style = .whiteLarge) {
-
- if self.activityIndicator != nil {
- stopActivityIndicator()
- }
-
- DispatchQueue.main.async {
-
- self.activityIndicator = UIActivityIndicatorView(style: style)
- guard let activityIndicator = self.activityIndicator else { return }
- if self.viewBackgroundActivityIndicator != nil { return }
-
- activityIndicator.color = NCBrandColor.shared.label
- activityIndicator.hidesWhenStopped = true
- activityIndicator.translatesAutoresizingMaskIntoConstraints = false
-
- let sizeActivityIndicator = activityIndicator.frame.height + 50
-
- self.viewActivityIndicator = UIView(frame: CGRect(x: 0, y: 0, width: sizeActivityIndicator, height: sizeActivityIndicator))
- self.viewActivityIndicator?.translatesAutoresizingMaskIntoConstraints = false
- self.viewActivityIndicator?.layer.cornerRadius = 10
- self.viewActivityIndicator?.layer.masksToBounds = true
- self.viewActivityIndicator?.backgroundColor = .clear
-
- #if !EXTENSION
- if backgroundView == nil {
- if let window = UIApplication.shared.keyWindow {
- self.viewBackgroundActivityIndicator?.removeFromSuperview()
- self.viewBackgroundActivityIndicator = NCViewActivityIndicator(frame: window.bounds)
- window.addSubview(self.viewBackgroundActivityIndicator!)
- self.viewBackgroundActivityIndicator?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
- self.viewBackgroundActivityIndicator?.backgroundColor = .clear
- }
- } else {
- self.viewBackgroundActivityIndicator = backgroundView
- }
- #else
- self.viewBackgroundActivityIndicator = backgroundView
- #endif
-
- // VIEW ACTIVITY INDICATOR
-
- guard let viewActivityIndicator = self.viewActivityIndicator else { return }
- viewActivityIndicator.addSubview(activityIndicator)
-
- if blurEffect {
- let blurEffect = UIBlurEffect(style: .regular)
- let blurEffectView = UIVisualEffectView(effect: blurEffect)
- blurEffectView.frame = viewActivityIndicator.frame
- viewActivityIndicator.insertSubview(blurEffectView, at: 0)
- }
-
- NSLayoutConstraint.activate([
- viewActivityIndicator.widthAnchor.constraint(equalToConstant: sizeActivityIndicator),
- viewActivityIndicator.heightAnchor.constraint(equalToConstant: sizeActivityIndicator),
- activityIndicator.centerXAnchor.constraint(equalTo: viewActivityIndicator.centerXAnchor),
- activityIndicator.centerYAnchor.constraint(equalTo: viewActivityIndicator.centerYAnchor)
- ])
-
- // BACKGROUD VIEW ACTIVITY INDICATOR
-
- guard let viewBackgroundActivityIndicator = self.viewBackgroundActivityIndicator else { return }
- viewBackgroundActivityIndicator.addSubview(viewActivityIndicator)
-
- var verticalConstant: CGFloat = 0
- if bottom > 0 {
- verticalConstant = (viewBackgroundActivityIndicator.frame.size.height / 2) - bottom
- }
-
- NSLayoutConstraint.activate([
- viewActivityIndicator.centerXAnchor.constraint(equalTo: viewBackgroundActivityIndicator.centerXAnchor),
- viewActivityIndicator.centerYAnchor.constraint(equalTo: viewBackgroundActivityIndicator.centerYAnchor, constant: verticalConstant)
- ])
-
- activityIndicator.startAnimating()
- }
- }
-
- @objc func stopActivityIndicator() {
-
- DispatchQueue.main.async {
-
- self.activityIndicator?.stopAnimating()
- self.activityIndicator?.removeFromSuperview()
- self.activityIndicator = nil
-
- self.viewActivityIndicator?.removeFromSuperview()
- self.viewActivityIndicator = nil
-
- if self.viewBackgroundActivityIndicator is NCViewActivityIndicator {
- self.viewBackgroundActivityIndicator?.removeFromSuperview()
- }
- self.viewBackgroundActivityIndicator = nil
- }
- }
-
/*
Facebook's comparison algorithm:
*/
@@ -889,19 +917,29 @@ class NCUtility: NSObject {
return UIDevice.current.systemVersion.compare(version,
options: NSString.CompareOptions.numeric) == ComparisonResult.orderedAscending
}
-}
-
-// MARK: -
-class NCViewActivityIndicator: UIView {
+ func getAvatarFromIconUrl(metadata: tableMetadata) -> String? {
- // MARK: - View Life Cycle
-
- override init(frame: CGRect) {
- super.init(frame: frame)
+ var ownerId: String?
+ if metadata.iconUrl.contains("http") && metadata.iconUrl.contains("avatar") {
+ let splitIconUrl = metadata.iconUrl.components(separatedBy: "/")
+ var found:Bool = false
+ for item in splitIconUrl {
+ if found {
+ ownerId = item
+ break
+ }
+ if item == "avatar" { found = true}
+ }
+ }
+ return ownerId
}
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
+ // https://stackoverflow.com/questions/25471114/how-to-validate-an-e-mail-address-in-swift
+ func isValidEmail(_ email: String) -> Bool {
+
+ let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
+ let emailPred = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
+ return emailPred.evaluate(with: email)
}
}
diff --git a/iOSClient/Utility/NCUtilityFileSystem.swift b/iOSClient/Utility/NCUtilityFileSystem.swift
index 94ad7ff48..9dedc0951 100644
--- a/iOSClient/Utility/NCUtilityFileSystem.swift
+++ b/iOSClient/Utility/NCUtilityFileSystem.swift
@@ -165,15 +165,18 @@ class NCUtilityFileSystem: NSObject {
return home
}
- @objc func getPath(metadata: tableMetadata) -> String {
+ @objc func getPath(metadata: tableMetadata, withFileName: Bool) -> String {
- return metadata.path.replacingOccurrences(of: "/remote.php/dav/files/"+metadata.user, with: "") + metadata.fileName
+ var path = metadata.path.replacingOccurrences(of: "/remote.php/dav/files/"+metadata.user, with: "")
+ if withFileName { path += metadata.fileName }
+ return path
}
@objc func deletingLastPathComponent(account: String, serverUrl: String) -> String {
+
if getHomeServer(account: account) == serverUrl { return serverUrl }
let fileName = (serverUrl as NSString).lastPathComponent
- let serverUrl = serverUrl.replacingOccurrences(of: "/"+fileName, with: "", options: String.CompareOptions.backwards, range: nil)
+ let serverUrl = serverUrl.replacingOccurrences(of: "/" + fileName, with: "", options: String.CompareOptions.backwards, range: nil)
return serverUrl
}
diff --git a/iOSClient/Utility/ParallelWorker.swift b/iOSClient/Utility/ParallelWorker.swift
index 1dfc269ed..c8bf7a917 100644
--- a/iOSClient/Utility/ParallelWorker.swift
+++ b/iOSClient/Utility/ParallelWorker.swift
@@ -56,6 +56,8 @@ class ParallelWorker {
hud.detailTextLabel.text = NSLocalizedString("_tap_to_cancel_", comment: "")
hud.tapOnHUDViewBlock = { hud in
self.isCancelled = true
+ // Cancel all download
+ NCNetworking.shared.cancelAllDownloadTransfer()
hud.dismiss()
}
self.hud = hud
diff --git a/iOSClient/Utility/ThreadSafeDictionary.swift b/iOSClient/Utility/ThreadSafeDictionary.swift
new file mode 100644
index 000000000..c06e0c476
--- /dev/null
+++ b/iOSClient/Utility/ThreadSafeDictionary.swift
@@ -0,0 +1,65 @@
+//
+// ThreadSafeDictionary.swift
+//
+// Created by Shashank on 29/10/20.
+//
+
+class ThreadSafeDictionary<V: Hashable, T>: Collection {
+
+ private var dictionary: [V: T]
+ private let concurrentQueue = DispatchQueue(label: "Dictionary Barrier Queue", attributes: .concurrent)
+
+ var startIndex: Dictionary<V, T>.Index {
+ self.concurrentQueue.sync {
+ return self.dictionary.startIndex
+ }
+ }
+
+ var endIndex: Dictionary<V, T>.Index {
+ self.concurrentQueue.sync {
+ return self.dictionary.endIndex
+ }
+ }
+
+ init(dict: [V: T] = [V: T]()) {
+ self.dictionary = dict
+ }
+
+ func index(after i: Dictionary<V, T>.Index) -> Dictionary<V, T>.Index {
+ self.concurrentQueue.sync {
+ return self.dictionary.index(after: i)
+ }
+ }
+
+ subscript(key: V) -> T? {
+ get {
+ self.concurrentQueue.sync {
+ return self.dictionary[key]
+ }
+ }
+ set(newValue) {
+ self.concurrentQueue.async(flags: .barrier) {[weak self] in
+ self?.dictionary[key] = newValue
+ }
+ }
+ }
+
+ subscript(index: Dictionary<V, T>.Index) -> Dictionary<V, T>.Element {
+ self.concurrentQueue.sync {
+ return self.dictionary[index]
+ }
+ }
+
+ func removeValue(forKey key: V) {
+ self.concurrentQueue.async(flags: .barrier) {[weak self] in
+ self?.dictionary.removeValue(forKey: key)
+ }
+ }
+
+ func removeAll() {
+ self.concurrentQueue.async(flags: .barrier) {[weak self] in
+ self?.dictionary.removeAll()
+ }
+ }
+
+}
diff --git a/iOSClient/Viewer/NCViewer.swift b/iOSClient/Viewer/NCViewer.swift
index 1e36d2490..af4c7b3cc 100644
--- a/iOSClient/Viewer/NCViewer.swift
+++ b/iOSClient/Viewer/NCViewer.swift
@@ -23,6 +23,7 @@
import UIKit
import NCCommunication
+import QuickLook
class NCViewer: NSObject {
@objc static let shared: NCViewer = {
@@ -43,6 +44,15 @@ class NCViewer: NSObject {
var editor = editor
var xxxxxxx = NCCommunicationCommon.shared.getInternalTypeIdentifier(typeIdentifier: metadata.contentType)
+ // URL
+ if metadata.classFile == NCCommunicationCommon.typeClassFile.url.rawValue {
+
+ if let url = URL(string: metadata.url) {
+ UIApplication.shared.open(url)
+ }
+ return
+ }
+
// IMAGE AUDIO VIDEO
if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue {
@@ -91,10 +101,10 @@ class NCViewer: NSObject {
if metadata.url == "" {
- NCUtility.shared.startActivityIndicator(backgroundView: viewController.view, blurEffect: true)
+ NCActivityIndicator.shared.start(backgroundView: viewController.view)
NCCommunication.shared.createUrlRichdocuments(fileID: metadata.fileId) { account, url, errorCode, errorDescription in
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
if errorCode == 0 && account == self.appDelegate.account && url != nil {
@@ -156,10 +166,10 @@ class NCViewer: NSObject {
customUserAgent = NCUtility.shared.getCustomUserAgentNCText()
}
- NCUtility.shared.startActivityIndicator(backgroundView: viewController.view, blurEffect: true)
+ NCActivityIndicator.shared.start(backgroundView: viewController.view)
NCCommunication.shared.NCTextOpenFile(fileNamePath: fileNamePath, editor: editor, customUserAgent: customUserAgent) { account, url, errorCode, errorMessage in
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
if errorCode == 0 && account == self.appDelegate.account && url != nil {
@@ -205,13 +215,17 @@ class NCViewer: NSObject {
}
}
- // OTHER
- let fileNamePath = NSTemporaryDirectory() + metadata.fileNameView
-
- CCUtility.copyFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView), toPath: fileNamePath)
-
- let viewerQuickLook = NCViewerQuickLook(with: URL(fileURLWithPath: fileNamePath), isEditingEnabled: false, metadata: metadata)
- viewController.present(viewerQuickLook, animated: true)
+ // QLPreview
+ let item = URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView))
+ if QLPreviewController.canPreview(item as QLPreviewItem) {
+ let fileNamePath = NSTemporaryDirectory() + metadata.fileNameView
+ CCUtility.copyFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView), toPath: fileNamePath)
+ let viewerQuickLook = NCViewerQuickLook(with: URL(fileURLWithPath: fileNamePath), isEditingEnabled: false, metadata: metadata)
+ viewController.present(viewerQuickLook, animated: true)
+ } else {
+ // Document Interaction Controller
+ NCFunctionCenter.shared.openDocumentController(metadata: metadata)
+ }
}
}
diff --git a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCKTVHTTPCache.swift b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCKTVHTTPCache.swift
index 27ca0708e..e54762e11 100644
--- a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCKTVHTTPCache.swift
+++ b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCKTVHTTPCache.swift
@@ -110,7 +110,7 @@ class NCKTVHTTPCache: NSObject {
NCManageDatabase.shared.addLocalFile(metadata: metadata)
KTVHTTPCache.cacheDelete(with: videoURL)
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl])
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": metadata.serverUrl])
}
}
diff --git a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift
index 60032e9ec..ee99737cf 100644
--- a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift
+++ b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift
@@ -186,7 +186,7 @@ class NCPlayer: NSObject {
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterShowPlayerToolBar, userInfo: ["ocId":self.metadata.ocId, "enableTimerAutoHide": false])
}
self.activateObserver()
- if self.autoPlay {
+ if self.autoPlay || CCUtility.getPlayerPlay() {
self.player?.play()
}
self.isStartPlayer = true
diff --git a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift
index 297b111a1..9dcbe70ac 100644
--- a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift
+++ b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift
@@ -427,10 +427,12 @@ class NCPlayerToolBar: UIView {
@IBAction func tapPlayerPause(_ sender: Any) {
if ncplayer?.player?.timeControlStatus == .playing {
+ CCUtility.setPlayerPlay(false)
ncplayer?.playerPause()
ncplayer?.saveCurrentTime()
timerAutoHide?.invalidate()
} else if ncplayer?.player?.timeControlStatus == .paused {
+ CCUtility.setPlayerPlay(true)
ncplayer?.playerPlay()
startTimerAutoHide()
} else if ncplayer?.player?.timeControlStatus == .waitingToPlayAtSpecifiedRate {
@@ -485,27 +487,11 @@ class NCPlayerToolBar: UIView {
@IBAction func tapForward(_ sender: Any) {
skip(seconds: 10)
-
- /*
- if metadata?.classFile == NCCommunicationCommon.typeClassFile.video.rawValue {
- skip(seconds: 10)
- } else if metadata?.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
- forward()
- }
- */
}
@IBAction func tapBack(_ sender: Any) {
skip(seconds: -10)
-
- /*
- if metadata?.classFile == NCCommunicationCommon.typeClassFile.video.rawValue {
- skip(seconds: -10)
- } else if metadata?.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
- backward()
- }
- */
}
@IBAction func tapSubtitle(_ sender: Any) {
diff --git a/iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift b/iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift
index 92ffb8ceb..824c82972 100644
--- a/iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift
+++ b/iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift
@@ -24,6 +24,8 @@
import UIKit
import SVGKit
import NCCommunication
+import EasyTipView
+import SwiftUI
class NCViewerMedia: UIViewController {
@@ -38,6 +40,7 @@ class NCViewerMedia: UIViewController {
@IBOutlet weak var detailView: NCViewerMediaDetailView!
private var _autoPlay: Bool = false
+ private var tipView: EasyTipView?
let appDelegate = UIApplication.shared.delegate as! AppDelegate
weak var viewerMediaPage: NCViewerMediaPage?
@@ -73,6 +76,7 @@ class NCViewerMedia: UIViewController {
deinit {
print("deinit NCViewerMedia")
+ self.tipView?.dismiss()
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterOpenMediaDetail), object: nil)
}
@@ -111,7 +115,23 @@ class NCViewerMedia: UIViewController {
self.ncplayer = NCPlayer.init(url: url, autoPlay: self.autoPlay, isProxy: urlVideo.isProxy, imageVideoContainer: self.imageVideoContainer, playerToolBar: self.playerToolBar, metadata: self.metadata, detailView: self.detailView, viewController: self)
}
}
-
+
+ // TIP
+ var preferences = EasyTipView.Preferences()
+ preferences.drawing.foregroundColor = .white
+ preferences.drawing.backgroundColor = NCBrandColor.shared.nextcloud
+ preferences.drawing.textAlignment = .left
+ preferences.drawing.arrowPosition = .top
+ preferences.drawing.cornerRadius = 10
+
+ preferences.animating.dismissTransform = CGAffineTransform(translationX: 0, y: 100)
+ preferences.animating.showInitialTransform = CGAffineTransform(translationX: 0, y: -100)
+ preferences.animating.showInitialAlpha = 0
+ preferences.animating.showDuration = 0.5
+ preferences.animating.dismissDuration = 0
+
+ tipView = EasyTipView(text: NSLocalizedString("_tip_open_mediadetail_", comment: ""), preferences: preferences, delegate: self)
+
detailViewTopConstraint.constant = 0
detailView.hide()
@@ -172,16 +192,25 @@ class NCViewerMedia: UIViewController {
viewerMediaPage?.clearCommandCenter()
}
+ // TIP
+ if !NCManageDatabase.shared.tipExists(NCGlobal.shared.tipNCViewerMediaDetailView), let view = self.navigationController?.navigationBar {
+ self.tipView?.show(forView: view)
+ }
+
NotificationCenter.default.addObserver(self, selector: #selector(openDetail(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterOpenMediaDetail), object: nil)
}
- override func viewDidDisappear(_ animated: Bool) {
- super.viewDidDisappear(animated)
+ override func viewWillDisappear(_ animated: Bool) {
+ super.viewWillDisappear(animated)
+
+ self.tipView?.dismiss()
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
+ self.tipView?.dismiss()
+
coordinator.animate(alongsideTransition: { context in
// back to the original size
self.scrollView.zoom(to: CGRect(x: 0, y: 0, width: self.scrollView.bounds.width, height: self.scrollView.bounds.height), animated: false)
@@ -199,90 +228,36 @@ class NCViewerMedia: UIViewController {
func reloadImage() {
if let metadata = NCManageDatabase.shared.getMetadataFromOcId(metadata.ocId) {
self.metadata = metadata
- loadImage(metadata: metadata) { _, image in
- self.image = image
- // do not update if is present the videoLayer
- let numSublayers = self.imageVideoContainer.layer.sublayers?.count
- if numSublayers == nil {
- self.imageVideoContainer.image = image
- }
- }
+ loadImage(metadata: metadata)
}
}
- func loadImage(metadata: tableMetadata, completion: @escaping (_ ocId: String, _ image: UIImage?) -> Void) {
-
- // Download preview
- if metadata.hasPreview && !CCUtility.fileProviderStoragePreviewIconExists(metadata.ocId, etag: metadata.etag) {
-
- var etagResource: String?
- let fileNamePath = CCUtility.returnFileNamePath(fromFileName: metadata.fileName, serverUrl: metadata.serverUrl, urlBase: metadata.urlBase, account: metadata.account)!
- let fileNamePreviewLocalPath = CCUtility.getDirectoryProviderStoragePreviewOcId(metadata.ocId, etag: metadata.etag)!
- let fileNameIconLocalPath = CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)!
- if FileManager.default.fileExists(atPath: fileNameIconLocalPath) && FileManager.default.fileExists(atPath: fileNamePreviewLocalPath) {
- etagResource = metadata.etagResource
- }
+ func loadImage(metadata: tableMetadata) {
- NCCommunication.shared.downloadPreview(
- fileNamePathOrFileId: fileNamePath,
- fileNamePreviewLocalPath: fileNamePreviewLocalPath,
- widthPreview: NCGlobal.shared.sizePreview,
- heightPreview: NCGlobal.shared.sizePreview,
- fileNameIconLocalPath: fileNameIconLocalPath,
- sizeIcon: NCGlobal.shared.sizeIcon, etag: etagResource,
- queue: NCCommunicationCommon.shared.backgroundQueue) { _, _, imageIcon, _, etag, errorCode, _ in
-
- if errorCode == 0 && imageIcon != nil {
- NCManageDatabase.shared.setMetadataEtagResource(ocId: metadata.ocId, etagResource: etag)
- }
+ // Download image
+ if !CCUtility.fileProviderStorageExists(metadata) && metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && metadata.session == "" {
- // Download file max resolution
- downloadFile(metadata: metadata)
- // Download file live photo
- if metadata.livePhoto { downloadFileLivePhoto(metadata: metadata) }
+ if metadata.livePhoto {
+ let fileName = (metadata.fileNameView as NSString).deletingPathExtension + ".mov"
+ if let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileNameView LIKE[c] %@", metadata.account, metadata.serverUrl, fileName)), !CCUtility.fileProviderStorageExists(metadata) {
+ NCNetworking.shared.download(metadata: metadata, selector: "") { _ in }
}
- } else {
-
- // Download file max resolution
- downloadFile(metadata: metadata)
- // Download file live photo
- if metadata.livePhoto { downloadFileLivePhoto(metadata: metadata) }
- }
-
- // Download file max resolution
- func downloadFile(metadata: tableMetadata) {
-
- let isFolderEncrypted = CCUtility.isFolderEncrypted(metadata.serverUrl, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase)
- let ext = CCUtility.getExtension(metadata.fileNameView)
-
- if (CCUtility.getAutomaticDownloadImage() || (metadata.contentType == "image/heic" && metadata.hasPreview == false) || ext == "GIF" || ext == "SVG" || isFolderEncrypted) && (metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && !CCUtility.fileProviderStorageExists(metadata) && metadata.session == "") {
-
- NCNetworking.shared.download(metadata: metadata, selector: "") { _ in
-
- DispatchQueue.main.async {
- let image = getImageMetadata(metadata)
- completion(metadata.ocId, image)
- }
- }
-
- } else {
+ }
- DispatchQueue.main.async {
- let image = getImageMetadata(metadata)
- completion(metadata.ocId, image)
+ NCNetworking.shared.download(metadata: metadata, selector: "") { _ in
+ let image = getImageMetadata(metadata)
+ if self.metadata.ocId == metadata.ocId && self.imageVideoContainer.layer.sublayers?.count == nil {
+ self.image = image
+ self.imageVideoContainer.image = image
}
}
}
- // Download Live Photo
- func downloadFileLivePhoto(metadata: tableMetadata) {
-
- let fileName = (metadata.fileNameView as NSString).deletingPathExtension + ".mov"
-
- if let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileNameView LIKE[c] %@", metadata.account, metadata.serverUrl, fileName)), !CCUtility.fileProviderStorageExists(metadata) {
-
- NCNetworking.shared.download(metadata: metadata, selector: "") { _ in }
- }
+ // Get image
+ let image = getImageMetadata(metadata)
+ if self.metadata.ocId == metadata.ocId && self.imageVideoContainer.layer.sublayers?.count == nil {
+ self.image = image
+ self.imageVideoContainer.image = image
}
func getImageMetadata(_ metadata: tableMetadata) -> UIImage? {
@@ -292,7 +267,7 @@ class NCViewerMedia: UIViewController {
}
if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue && !metadata.hasPreview {
- NCUtility.shared.createImageFrom(fileName: metadata.fileNameView, ocId: metadata.ocId, etag: metadata.etag, classFile: metadata.classFile)
+ NCUtility.shared.createImageFrom(fileNameView: metadata.fileNameView, ocId: metadata.ocId, etag: metadata.etag, classFile: metadata.classFile)
}
if CCUtility.fileProviderStoragePreviewIconExists(metadata.ocId, etag: metadata.etag) {
@@ -322,7 +297,7 @@ class NCViewerMedia: UIViewController {
if ext == "GIF" {
if !FileManager().fileExists(atPath: previewPath) {
- NCUtility.shared.createImageFrom(fileName: metadata.fileNameView, ocId: metadata.ocId, etag: metadata.etag, classFile: metadata.classFile)
+ NCUtility.shared.createImageFrom(fileNameView: metadata.fileNameView, ocId: metadata.ocId, etag: metadata.etag, classFile: metadata.classFile)
}
image = UIImage.animatedImage(withAnimatedGIFURL: URL(fileURLWithPath: imagePath))
} else if ext == "SVG" {
@@ -342,7 +317,7 @@ class NCViewerMedia: UIViewController {
return nil
}
} else {
- NCUtility.shared.createImageFrom(fileName: metadata.fileNameView, ocId: metadata.ocId, etag: metadata.etag, classFile: metadata.classFile)
+ NCUtility.shared.createImageFrom(fileNameView: metadata.fileNameView, ocId: metadata.ocId, etag: metadata.etag, classFile: metadata.classFile)
image = UIImage(contentsOfFile: imagePath)
}
}
@@ -445,6 +420,8 @@ extension NCViewerMedia {
private func openDetail() {
+ self.dismissTip()
+
CCUtility.setExif(metadata) { latitude, longitude, location, date, lensModel in
if latitude != -1 && latitude != 0 && longitude != -1 && longitude != 0 {
@@ -561,6 +538,21 @@ extension NCViewerMedia: NCViewerMediaDetailViewDelegate {
}
}
+extension NCViewerMedia: EasyTipViewDelegate {
+
+ // TIP
+ func easyTipViewDidTap(_ tipView: EasyTipView) {
+ NCManageDatabase.shared.addTip(NCGlobal.shared.tipNCViewerMediaDetailView)
+ }
+
+ func easyTipViewDidDismiss(_ tipView: EasyTipView) { }
+
+ func dismissTip() {
+ NCManageDatabase.shared.addTip(NCGlobal.shared.tipNCViewerMediaDetailView)
+ self.tipView?.dismiss()
+ }
+}
+
// MARK: -
class imageVideoContainerView: UIImageView {
diff --git a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift
index 15bd22701..5bccecde7 100644
--- a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift
+++ b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift
@@ -79,7 +79,12 @@ class NCViewerMediaDetailView: UIView {
self.mapView = nil
}
- func show(metadata: tableMetadata, image: UIImage?, textColor: UIColor?, mediaMetadata: NCImageMetadata, ncplayer: NCPlayer?, delegate: NCViewerMediaDetailViewDelegate?) {
+ func show(metadata: tableMetadata,
+ image: UIImage?,
+ textColor: UIColor?,
+ mediaMetadata: NCImageMetadata,
+ ncplayer: NCPlayer?,
+ delegate: NCViewerMediaDetailViewDelegate?) {
self.metadata = metadata
self.latitude = mediaMetadata.latitude
diff --git a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.storyboard b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.storyboard
index 329daf6cc..a9377104d 100644
--- a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.storyboard
+++ b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.storyboard
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="ne8-hS-cp3">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="ne8-hS-cp3">
<device id="retina5_5" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
diff --git a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.swift b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.swift
index 253073658..9ca9f6140 100644
--- a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.swift
+++ b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.swift
@@ -83,7 +83,6 @@ class NCViewerMediaPage: UIViewController {
let viewerMedia = getViewerMedia(index: currentIndex, metadata: metadatas[currentIndex])
pageViewController.setViewControllers([viewerMedia], direction: .forward, animated: true, completion: nil)
- NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(viewUnload), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMenuDetailClose), object: nil)
progressView.tintColor = NCBrandColor.shared.brandElement
@@ -97,35 +96,19 @@ class NCViewerMediaPage: UIViewController {
NotificationCenter.default.addObserver(self, selector: #selector(downloadedFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDownloadedFile), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(triggerProgressTask(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterProgressTask), object: nil)
+ NotificationCenter.default.addObserver(self, selector: #selector(uploadStartFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadStartFile), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(uploadedFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadedFile), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(hidePlayerToolBar(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterHidePlayerToolBar), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(showPlayerToolBar(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterShowPlayerToolBar), object: nil)
-
+
NotificationCenter.default.addObserver(self, selector: #selector(reloadMediaPage(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadMediaPage), object: nil)
-
+
NotificationCenter.default.addObserver(self, selector: #selector(applicationDidBecomeActive(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidBecomeActive), object: nil)
}
deinit {
-
- print("deinit NCViewerMediaPage")
- }
-
- override func viewDidDisappear(_ animated: Bool) {
- super.viewDidDisappear(animated)
-
- if let ncplayer = currentViewController.ncplayer, ncplayer.isPlay() {
- ncplayer.playerPause()
- ncplayer.saveCurrentTime()
- }
- currentViewController.playerToolBar?.stopTimerAutoHide()
- clearCommandCenter()
- metadatas.removeAll()
- ncplayerLivePhoto = nil
-
- // Remove Observer
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDeleteFile), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterRenameFile), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMoveFile), object: nil)
@@ -133,6 +116,7 @@ class NCViewerMediaPage: UIViewController {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDownloadedFile), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterProgressTask), object: nil)
+ NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadStartFile), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadedFile), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterHidePlayerToolBar), object: nil)
@@ -143,6 +127,17 @@ class NCViewerMediaPage: UIViewController {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidBecomeActive), object: nil)
}
+ override func viewDidDisappear(_ animated: Bool) {
+ super.viewDidDisappear(animated)
+
+ if let ncplayer = currentViewController.ncplayer, ncplayer.isPlay() {
+ ncplayer.playerPause()
+ ncplayer.saveCurrentTime()
+ }
+ currentViewController.playerToolBar?.stopTimerAutoHide()
+ clearCommandCenter()
+ }
+
override var preferredStatusBarStyle: UIStatusBarStyle {
if currentScreenMode == .normal {
@@ -227,82 +222,91 @@ class NCViewerMediaPage: UIViewController {
@objc func triggerProgressTask(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let progressNumber = userInfo["progress"] as? NSNumber {
- let progress = progressNumber.floatValue
- if progress == 1 {
- self.progressView.progress = 0
- } else {
- self.progressView.progress = progress
- }
- }
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let progressNumber = userInfo["progress"] as? NSNumber
+ else { return }
+
+ let progress = progressNumber.floatValue
+ if progress == 1 {
+ self.progressView.progress = 0
+ } else {
+ self.progressView.progress = progress
}
}
+ @objc func uploadStartFile(_ notification: NSNotification) {
+
+ /*
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let serverUrl = userInfo["serverUrl"] as? String,
+ let fileName = userInfo["fileName"] as? String,
+ let sessionSelector = userInfo["sessionSelector"] as? String
+ else { return }
+ */
+ }
+
@objc func uploadedFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["ocId"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId), let errorCode = userInfo["errorCode"] as? Int {
- if errorCode == 0, let index = metadatas.firstIndex(where: {$0.ocId == metadata.ocId}) {
- metadatas[index] = metadata
- if currentViewController.metadata.ocId == ocId {
- currentViewController.reloadImage()
- } else {
- modifiedOcId.append(ocId)
- }
- }
- }
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ let errorCode = userInfo["errorCode"] as? Int,
+ errorCode == 0,
+ let index = metadatas.firstIndex(where: {$0.ocId == ocId}),
+ let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId)
+ else {
+ return
+ }
+
+ metadatas[index] = metadata
+ if currentViewController.metadata.ocId == ocId {
+ currentViewController.reloadImage()
+ } else {
+ modifiedOcId.append(ocId)
}
}
@objc func deleteFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["ocId"] as? String {
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String
+ else { return }
- let metadatas = self.metadatas.filter { $0.ocId != ocId }
- if self.metadatas.count == metadatas.count { return }
- self.metadatas = metadatas
+ let metadatas = self.metadatas.filter { $0.ocId != ocId }
+ if self.metadatas.count == metadatas.count { return }
+ self.metadatas = metadatas
- if ocId == currentViewController.metadata.ocId {
- shiftCurrentPage()
- }
- }
+ if ocId == currentViewController.metadata.ocId {
+ shiftCurrentPage()
}
}
@objc func renameFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["ocId"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
-
- if let index = metadatas.firstIndex(where: {$0.ocId == metadata.ocId}) {
- metadatas[index] = metadata
- if index == currentIndex {
- navigationItem.title = metadata.fileNameView
- currentViewController.metadata = metadata
- self.currentViewController.metadata = metadata
- }
- }
- }
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ let index = metadatas.firstIndex(where: {$0.ocId == ocId}),
+ let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId)
+ else { return }
+
+ metadatas[index] = metadata
+ if index == currentIndex {
+ navigationItem.title = metadata.fileNameView
+ currentViewController.metadata = metadata
+ self.currentViewController.metadata = metadata
}
}
@objc func moveFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["ocId"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String
+ else { return }
- if metadatas.firstIndex(where: {$0.ocId == metadata.ocId}) != nil {
- deleteFile(notification)
- }
- }
+ if metadatas.firstIndex(where: {$0.ocId == ocId}) != nil {
+ deleteFile(notification)
}
}
- @objc func changeTheming() {
- }
-
@objc func hidePlayerToolBar(_ notification: NSNotification) {
if let userInfo = notification.userInfo as NSDictionary?, let ocId = userInfo["ocId"] as? String {
@@ -383,26 +387,6 @@ class NCViewerMediaPage: UIViewController {
}
}
- // AUDIO < >
- /*
- if metadata?.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
-
- MPRemoteCommandCenter.shared().nextTrackCommand.isEnabled = true
- appDelegate.nextTrackCommand = MPRemoteCommandCenter.shared().nextTrackCommand.addTarget { event in
-
- self.forward()
- return .success
- }
-
- MPRemoteCommandCenter.shared().previousTrackCommand.isEnabled = true
- appDelegate.previousTrackCommand = MPRemoteCommandCenter.shared().previousTrackCommand.addTarget { event in
-
- self.backward()
- return .success
- }
- }
- */
-
nowPlayingInfo[MPMediaItemPropertyTitle] = metadata.fileNameView
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = ncplayer.durationTime.seconds
if let image = currentViewController.image {
diff --git a/iOSClient/Viewer/NCViewerNextcloudText/NCViewerNextcloudText.swift b/iOSClient/Viewer/NCViewerNextcloudText/NCViewerNextcloudText.swift
index f44cd3018..f6e1ae548 100644
--- a/iOSClient/Viewer/NCViewerNextcloudText/NCViewerNextcloudText.swift
+++ b/iOSClient/Viewer/NCViewerNextcloudText/NCViewerNextcloudText.swift
@@ -117,14 +117,13 @@ class NCViewerNextcloudText: UIViewController, WKNavigationDelegate, WKScriptMes
@objc func favoriteFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["ocId"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ ocId == self.metadata.ocId,
+ let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId)
+ else { return }
- if metadata.ocId == self.metadata.ocId {
- self.metadata = metadata
- }
- }
- }
+ self.metadata = metadata
}
@objc func keyboardDidShow(notification: Notification) {
@@ -195,7 +194,7 @@ class NCViewerNextcloudText: UIViewController, WKNavigationDelegate, WKScriptMes
}
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
}
}
diff --git a/iOSClient/Viewer/NCViewerPDF/NCViewerPDF.swift b/iOSClient/Viewer/NCViewerPDF/NCViewerPDF.swift
index a188fcb93..76ec451d7 100644
--- a/iOSClient/Viewer/NCViewerPDF/NCViewerPDF.swift
+++ b/iOSClient/Viewer/NCViewerPDF/NCViewerPDF.swift
@@ -190,6 +190,7 @@ class NCViewerPDF: UIViewController, NCViewerPDFSearchDelegate {
NotificationCenter.default.addObserver(self, selector: #selector(deleteFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDeleteFile), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(renameFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterRenameFile), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(moveFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMoveFile), object: nil)
+ NotificationCenter.default.addObserver(self, selector: #selector(uploadStartFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadStartFile), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(uploadedFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadedFile), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(viewUnload), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMenuDetailClose), object: nil)
@@ -266,65 +267,82 @@ class NCViewerPDF: UIViewController, NCViewerPDFSearchDelegate {
// MARK: - NotificationCenter
+ @objc func uploadStartFile(_ notification: NSNotification) {
+
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let serverUrl = userInfo["serverUrl"] as? String,
+ serverUrl == self.metadata.serverUrl,
+ let fileName = userInfo["fileName"] as? String,
+ fileName == self.metadata.fileName
+ else { return }
+
+ NCActivityIndicator.shared.start()
+ }
+
@objc func uploadedFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["ocId"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId), let errorCode = userInfo["errorCode"] as? Int {
- if errorCode == 0 && metadata.ocId == self.metadata.ocId {
- pdfDocument = PDFDocument(url: URL(fileURLWithPath: filePath))
- pdfView.document = pdfDocument
- pdfView.layoutDocumentView()
- }
- }
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let serverUrl = userInfo["serverUrl"] as? String,
+ serverUrl == self.metadata.serverUrl,
+ let fileName = userInfo["fileName"] as? String,
+ fileName == self.metadata.fileName,
+ let errorCode = userInfo["errorCode"] as? Int
+ else {
+ return
+ }
+
+ NCActivityIndicator.shared.stop()
+
+ if errorCode == 0 {
+ pdfDocument = PDFDocument(url: URL(fileURLWithPath: filePath))
+ pdfView.document = pdfDocument
+ pdfView.layoutDocumentView()
}
}
@objc func favoriteFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["ocId"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ ocId == self.metadata.ocId,
+ let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId)
+ else { return }
- if metadata.ocId == self.metadata.ocId {
- self.metadata = metadata
- }
- }
- }
+ self.metadata = metadata
}
@objc func moveFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["ocId"] as? String, let ocIdNew = userInfo["ocIdNew"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId), let metadataNew = NCManageDatabase.shared.getMetadataFromOcId(ocIdNew) {
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ ocId == self.metadata.ocId,
+ let ocIdNew = userInfo["ocIdNew"] as? String,
+ let metadataNew = NCManageDatabase.shared.getMetadataFromOcId(ocIdNew)
+ else { return }
- if metadata.ocId == self.metadata.ocId {
- self.metadata = metadataNew
- }
- }
- }
+ self.metadata = metadataNew
}
@objc func deleteFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["OcId"] as? String {
- if ocId == self.metadata.ocId {
- viewUnload()
- }
- }
- }
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ ocId == self.metadata.ocId
+ else { return }
+
+ viewUnload()
}
@objc func renameFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["ocId"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ ocId == self.metadata.ocId,
+ let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId)
+ else { return }
- if metadata.ocId == self.metadata.ocId {
- self.metadata = metadata
- navigationItem.title = metadata.fileNameView
- }
- }
- }
+ self.metadata = metadata
+ navigationItem.title = metadata.fileNameView
}
@objc func searchText() {
@@ -388,6 +406,7 @@ class NCViewerPDF: UIViewController, NCViewerPDFSearchDelegate {
}
@objc func gestureOpenPdfThumbnail(_ recognizer: UIScreenEdgePanGestureRecognizer) {
+ guard let pdfDocument = pdfView.document, !pdfDocument.isLocked else { return }
if UIDevice.current.userInterfaceIdiom == .phone && self.pdfThumbnailScrollView.isHidden {
if let tipView = self.tipView {
@@ -479,7 +498,7 @@ class NCViewerPDF: UIViewController, NCViewerPDFSearchDelegate {
pdfSelection.pages.forEach { page in
let highlight = PDFAnnotation(bounds: pdfSelection.bounds(for: page), forType: .highlight, withProperties: nil)
highlight.endLineStyle = .square
- highlight.color = .yellow
+ highlight.color = NCBrandColor.shared.annotationColor
page.addAnnotation(highlight)
}
if let page = pdfSelection.pages.first {
diff --git a/iOSClient/Viewer/NCViewerPDF/NCViewerPDFSearch.swift b/iOSClient/Viewer/NCViewerPDF/NCViewerPDFSearch.swift
index cda6cbf65..99be8ffe1 100644
--- a/iOSClient/Viewer/NCViewerPDF/NCViewerPDFSearch.swift
+++ b/iOSClient/Viewer/NCViewerPDF/NCViewerPDFSearch.swift
@@ -91,7 +91,7 @@ class NCViewerPDFSearch: UITableViewController, UISearchBarDelegate, PDFDocument
let nsRange = NSString(string: extendSelection.string!).range(of: pdfSelection.string!, options: String.CompareOptions.caseInsensitive)
if nsRange.location != NSNotFound {
- let attributedSubString = NSAttributedString(string: NSString(string: extendSelection.string!).substring(with: nsRange), attributes: [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 17)])
+ let attributedSubString = NSAttributedString(string: NSString(string: extendSelection.string!).substring(with: nsRange), attributes: [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 17), NSAttributedString.Key.foregroundColor : NCBrandColor.shared.annotationColor])
let attributedString = NSMutableAttributedString(string: extendSelection.string!)
attributedString.replaceCharacters(in: nsRange, with: attributedSubString)
cell.searchResultTextLabel.attributedText = attributedString
diff --git a/iOSClient/Viewer/NCViewerProviderContextMenu.swift b/iOSClient/Viewer/NCViewerProviderContextMenu.swift
index 67a653fdc..58727b470 100644
--- a/iOSClient/Viewer/NCViewerProviderContextMenu.swift
+++ b/iOSClient/Viewer/NCViewerProviderContextMenu.swift
@@ -58,7 +58,7 @@ class NCViewerProviderContextMenu: UIViewController {
imageFolder = image.image(color: NCBrandColor.shared.brandElement, size: sizeIcon*2)
}
- imageView.image = imageFolder
+ imageView.image = imageFolder.colorizeFolder(metadata: metadata)
imageView.frame = resize(CGSize(width: sizeIcon, height: sizeIcon))
} else {
@@ -173,46 +173,48 @@ class NCViewerProviderContextMenu: UIViewController {
@objc func downloadStartFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["ocId"] as? String {
- if ocId == self.metadata?.ocId || ocId == self.metadataLivePhoto?.ocId {
- NCUtility.shared.startActivityIndicator(backgroundView: self.view, blurEffect: false)
- }
- }
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String
+ else { return }
+
+ if ocId == self.metadata?.ocId || ocId == self.metadataLivePhoto?.ocId {
+ NCActivityIndicator.shared.start(backgroundView: self.view)
}
}
@objc func downloadedFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["ocId"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId), let errorCode = userInfo["errorCode"] as? Int {
- if errorCode == 0 && metadata.ocId == self.metadata?.ocId {
- if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue {
- viewImage(metadata: metadata)
- } else if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue {
- viewVideo(metadata: metadata)
- } else if metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
- playSound(metadata: metadata)
- }
- }
- if errorCode == 0 && metadata.ocId == self.metadataLivePhoto?.ocId {
- viewVideo(metadata: metadata)
- }
- if ocId == self.metadata?.ocId || ocId == self.metadataLivePhoto?.ocId {
- NCUtility.shared.stopActivityIndicator()
- }
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ let errorCode = userInfo["errorCode"] as? Int,
+ let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId)
+ else { return }
+
+ if errorCode == 0 && metadata.ocId == self.metadata?.ocId {
+ if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue {
+ viewImage(metadata: metadata)
+ } else if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue {
+ viewVideo(metadata: metadata)
+ } else if metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
+ playSound(metadata: metadata)
}
}
+ if errorCode == 0 && metadata.ocId == self.metadataLivePhoto?.ocId {
+ viewVideo(metadata: metadata)
+ }
+ if ocId == self.metadata?.ocId || ocId == self.metadataLivePhoto?.ocId {
+ NCActivityIndicator.shared.stop()
+ }
}
@objc func downloadCancelFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["ocId"] as? String {
- if ocId == self.metadata?.ocId || ocId == self.metadataLivePhoto?.ocId {
- NCUtility.shared.stopActivityIndicator()
- }
- }
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String
+ else { return }
+
+ if ocId == self.metadata?.ocId || ocId == self.metadataLivePhoto?.ocId {
+ NCActivityIndicator.shared.stop()
}
}
diff --git a/iOSClient/Viewer/NCViewerQuickLook/NCViewerQuickLook.swift b/iOSClient/Viewer/NCViewerQuickLook/NCViewerQuickLook.swift
index cff53169d..95f3ea68b 100644
--- a/iOSClient/Viewer/NCViewerQuickLook/NCViewerQuickLook.swift
+++ b/iOSClient/Viewer/NCViewerQuickLook/NCViewerQuickLook.swift
@@ -147,11 +147,14 @@ extension NCViewerQuickLook: QLPreviewControllerDataSource, QLPreviewControllerD
serverUrl: metadata.serverUrl,
urlBase: metadata.urlBase,
url: url.path,
- contentType: "",
- livePhoto: false)
+ contentType: "")
metadataForUpload.session = NCNetworking.shared.sessionIdentifierBackground
- metadataForUpload.sessionSelector = NCGlobal.shared.selectorUploadFile
+ if override {
+ metadataForUpload.sessionSelector = NCGlobal.shared.selectorUploadFileNODelete
+ } else {
+ metadataForUpload.sessionSelector = NCGlobal.shared.selectorUploadFile
+ }
metadataForUpload.size = size
metadataForUpload.status = NCGlobal.shared.metadataStatusWaitUpload
(UIApplication.shared.delegate as? AppDelegate)?.networkingProcessUpload?.createProcessUploads(metadatas: [metadataForUpload])
diff --git a/iOSClient/Viewer/NCViewerRichdocument/NCViewerRichdocument.swift b/iOSClient/Viewer/NCViewerRichdocument/NCViewerRichdocument.swift
index afd3e4519..cbc7e9663 100644
--- a/iOSClient/Viewer/NCViewerRichdocument/NCViewerRichdocument.swift
+++ b/iOSClient/Viewer/NCViewerRichdocument/NCViewerRichdocument.swift
@@ -124,14 +124,13 @@ class NCViewerRichdocument: UIViewController, WKNavigationDelegate, WKScriptMess
@objc func favoriteFile(_ notification: NSNotification) {
- if let userInfo = notification.userInfo as NSDictionary? {
- if let ocId = userInfo["ocId"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ ocId == self.metadata.ocId,
+ let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId)
+ else { return }
- if metadata.ocId == self.metadata.ocId {
- self.metadata = metadata
- }
- }
- }
+ self.metadata = metadata
}
@objc func keyboardDidShow(notification: Notification) {
@@ -193,7 +192,7 @@ class NCViewerRichdocument: UIViewController, WKNavigationDelegate, WKScriptMess
guard let url = URL(string: urlString) else { return }
let fileNameLocalPath = CCUtility.getDirectoryUserData() + "/" + metadata.fileNameWithoutExt
- NCUtility.shared.startActivityIndicator(backgroundView: view, blurEffect: true)
+ NCActivityIndicator.shared.start(backgroundView: view)
NCCommunication.shared.download(serverUrlFileName: url, fileNameLocalPath: fileNameLocalPath, requestHandler: { _ in
@@ -203,7 +202,7 @@ class NCViewerRichdocument: UIViewController, WKNavigationDelegate, WKScriptMess
}, completionHandler: { account, _, _, _, allHeaderFields, error, errorCode, errorDescription in
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
if errorCode == 0 && account == self.metadata.account {
@@ -333,7 +332,7 @@ class NCViewerRichdocument: UIViewController, WKNavigationDelegate, WKScriptMess
}
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
- NCUtility.shared.stopActivityIndicator()
+ NCActivityIndicator.shared.stop()
}
}