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:
authormarinofaggiana <ios@nextcloud.com>2022-05-24 12:06:19 +0300
committermarinofaggiana <ios@nextcloud.com>2022-05-24 12:06:19 +0300
commite2e52363b045d31542c49c5e12bf517362b69df2 (patch)
treeb3eedb5770b50c5b797031df0f2f751823b134c8
parent0611600b1c899f5dafddff6120f4a26e69055299 (diff)
parent8499b9da1e82c849fb0940f607e319b42845daca (diff)
Merge branch 'develop'4.4.0
-rw-r--r--.github/workflows/lint.yml10
-rw-r--r--.github/workflows/xcode.yml6
-rw-r--r--.swiftlint.yml19
-rw-r--r--Cartfile2
-rw-r--r--Cartfile.resolved2
-rw-r--r--File Provider Extension/FileProviderItem.swift8
-rw-r--r--Nextcloud.xcodeproj/project.pbxproj288
-rwxr-xr-xNextcloud.xcodeproj/xcshareddata/xcschemes/File Provider Extension.xcscheme2
-rwxr-xr-xNextcloud.xcodeproj/xcshareddata/xcschemes/Nextcloud.xcscheme2
-rwxr-xr-xNextcloud.xcodeproj/xcshareddata/xcschemes/Share.xcscheme2
-rw-r--r--NextcloudTests/SharePermissionTest.swift136
-rw-r--r--NextcloudTests/UserAgentTests.swift64
-rw-r--r--Share/NCShareExtension+Files.swift25
-rw-r--r--Share/NCShareExtension.swift36
-rw-r--r--iOSClient/Activity/NCActivity.storyboard58
-rw-r--r--iOSClient/Activity/NCActivity.swift67
-rw-r--r--iOSClient/Activity/NCActivityCommentView.swift59
-rw-r--r--iOSClient/Activity/NCActivityCommentView.xib60
-rw-r--r--iOSClient/AppDelegate.swift127
-rw-r--r--iOSClient/Brand/Intro/NCIntroCollectionViewCell.xib20
-rw-r--r--iOSClient/Brand/Intro/NCIntroViewController.swift2
-rwxr-xr-xiOSClient/Brand/LaunchScreen.storyboard18
-rwxr-xr-xiOSClient/Brand/NCBrand.swift14
-rwxr-xr-xiOSClient/Brand/iOSClient.entitlements12
-rwxr-xr-xiOSClient/Brand/iOSClient.plist41
-rw-r--r--iOSClient/Data/NCDatabase.swift20
-rw-r--r--iOSClient/Data/NCElementsJSON.swift3
-rw-r--r--iOSClient/Data/NCManageDatabase+Account.swift15
-rw-r--r--iOSClient/Data/NCManageDatabase+Activity.swift18
-rw-r--r--iOSClient/Data/NCManageDatabase+Metadata.swift (renamed from iOSClient/Data/NCManageDatabse+Metadata.swift)55
-rw-r--r--iOSClient/Data/NCManageDatabase+Video.swift152
-rw-r--r--iOSClient/Data/NCManageDatabase.swift164
-rw-r--r--iOSClient/Diagnostics/NCCapabilitiesViewController.storyboard62
-rw-r--r--iOSClient/Diagnostics/NCCapabilitiesViewController.swift16
-rw-r--r--iOSClient/Extensions/DateFormatter+Extension.swift33
-rw-r--r--iOSClient/Extensions/String+Extensions.swift7
-rw-r--r--iOSClient/Extensions/UIAlertController+Extension.swift91
-rw-r--r--iOSClient/Extensions/UIApplication+Orientation.swift2
-rw-r--r--iOSClient/Extensions/UIDevice+Extensions.swift37
-rw-r--r--iOSClient/Extensions/UIFont+Extension.swift31
-rw-r--r--iOSClient/Extensions/UIToolbar+Extension.swift77
-rw-r--r--iOSClient/Font/Inconsolata/Inconsolata-Black.ttfbin0 -> 98048 bytes
-rw-r--r--iOSClient/Font/Inconsolata/Inconsolata-Bold.ttfbin0 -> 98260 bytes
-rw-r--r--iOSClient/Font/Inconsolata/Inconsolata-ExtraBold.ttfbin0 -> 98268 bytes
-rw-r--r--iOSClient/Font/Inconsolata/Inconsolata-ExtraLight.ttfbin0 -> 98108 bytes
-rw-r--r--iOSClient/Font/Inconsolata/Inconsolata-Light.ttfbin0 -> 97956 bytes
-rw-r--r--iOSClient/Font/Inconsolata/Inconsolata-Medium.ttfbin0 -> 98304 bytes
-rw-r--r--iOSClient/Font/Inconsolata/Inconsolata-Regular.ttfbin0 -> 97864 bytes
-rw-r--r--iOSClient/Font/Inconsolata/Inconsolata-SemiBold.ttfbin0 -> 98400 bytes
-rw-r--r--iOSClient/Images.xcassets/captions.bubble.imageset/Contents.json (renamed from iOSClient/Images.xcassets/pdf-vertical.imageset/Contents.json)2
-rw-r--r--iOSClient/Images.xcassets/captions.bubble.imageset/subtitles-outline.svg (renamed from iOSClient/Images.xcassets/pdf-horizontal.imageset/swap-horizontal-variant.svg)2
-rw-r--r--iOSClient/Images.xcassets/circle_fill.imageset/Contents.json (renamed from iOSClient/Images.xcassets/circle.fill.imageset/Contents.json)0
-rw-r--r--iOSClient/Images.xcassets/circle_fill.imageset/circle.pdf (renamed from iOSClient/Images.xcassets/circle.fill.imageset/circle.pdf)bin3231 -> 3231 bytes
-rw-r--r--iOSClient/Images.xcassets/closeVideo.imageset/Contents.json15
-rw-r--r--iOSClient/Images.xcassets/closeVideo.imageset/closeVideo.pdfbin1087 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/edit.imageset/Contents.json15
-rw-r--r--iOSClient/Images.xcassets/edit.imageset/edit.pdfbin949 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/eye.imageset/Contents.json (renamed from iOSClient/Images.xcassets/userStatusOnline.imageset/Contents.json)2
-rw-r--r--iOSClient/Images.xcassets/eye.imageset/eye.svg1
-rw-r--r--iOSClient/Images.xcassets/lock_open.imageset/Contents.json (renamed from iOSClient/Images.xcassets/lock.open.imageset/Contents.json)0
-rw-r--r--iOSClient/Images.xcassets/lock_open.imageset/lock-open-variant-outline.svg (renamed from iOSClient/Images.xcassets/lock.open.imageset/lock-open-variant-outline.svg)0
-rw-r--r--iOSClient/Images.xcassets/moreLock.imageset/Contents.json (renamed from iOSClient/Images.xcassets/pdf-horizontal.imageset/Contents.json)2
-rw-r--r--iOSClient/Images.xcassets/moreLock.imageset/menu-locked-filled.svg72
-rw-r--r--iOSClient/Images.xcassets/pdf-vertical.imageset/swap-vertical-variant.svg1
-rw-r--r--iOSClient/Images.xcassets/photoEditorCancel.imageset/Contents.json23
-rw-r--r--iOSClient/Images.xcassets/photoEditorCancel.imageset/photoEditorCancel.pngbin387 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/photoEditorCancel.imageset/photoEditorCancel@2x.pngbin697 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/photoEditorCancel.imageset/photoEditorCancel@3x.pngbin1190 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/photoEditorClear.imageset/Contents.json23
-rw-r--r--iOSClient/Images.xcassets/photoEditorClear.imageset/photoEditorClear.pngbin500 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/photoEditorClear.imageset/photoEditorClear@2x.pngbin938 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/photoEditorClear.imageset/photoEditorClear@3x.pngbin1465 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/photoEditorCrop.imageset/Contents.json23
-rw-r--r--iOSClient/Images.xcassets/photoEditorCrop.imageset/photoEditorCrop.pngbin212 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/photoEditorCrop.imageset/photoEditorCrop@2x.pngbin262 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/photoEditorCrop.imageset/photoEditorCrop@3x.pngbin447 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/photoEditorDone.imageset/Contents.json23
-rw-r--r--iOSClient/Images.xcassets/photoEditorDone.imageset/photoEditorDone.pngbin451 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/photoEditorDone.imageset/photoEditorDone@2x.pngbin819 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/photoEditorDone.imageset/photoEditorDone@3x.pngbin1340 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/photoEditorDraw.imageset/Contents.json23
-rw-r--r--iOSClient/Images.xcassets/photoEditorDraw.imageset/photoEditorDraw.pngbin479 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/photoEditorDraw.imageset/photoEditorDraw@2x.pngbin1029 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/photoEditorDraw.imageset/photoEditorDraw@3x.pngbin1543 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/photoEditorText.imageset/Contents.json23
-rw-r--r--iOSClient/Images.xcassets/photoEditorText.imageset/photoEditorText.pngbin521 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/photoEditorText.imageset/photoEditorText@2x.pngbin970 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/photoEditorText.imageset/photoEditorText@3x.pngbin1574 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/tabBarFavorites.imageset/Contents.json15
-rw-r--r--iOSClient/Images.xcassets/tabBarFavorites.imageset/tabBarFavorites.pdfbin57667 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/tabBarMedia.imageset/Contents.json15
-rw-r--r--iOSClient/Images.xcassets/tabBarMedia.imageset/tabBarMedia.pdfbin58260 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/userStatusOnline.imageset/online.pdfbin3493 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/visiblePassword.imageset/Contents.json23
-rw-r--r--iOSClient/Images.xcassets/visiblePassword.imageset/visiblePassword.pngbin1920 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/visiblePassword.imageset/visiblePassword@2x.pngbin1775 -> 0 bytes
-rw-r--r--iOSClient/Images.xcassets/visiblePassword.imageset/visiblePassword@3x.pngbin6206 -> 0 bytes
-rw-r--r--iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift7
-rw-r--r--iOSClient/Main/Collection Common/NCCollectionViewCommon.swift41
-rw-r--r--iOSClient/Main/Collection Common/NCGridCell.swift23
-rwxr-xr-xiOSClient/Main/Collection Common/NCListCell.swift27
-rw-r--r--iOSClient/Main/Collection Common/NCSelectableNavigationView.swift14
-rw-r--r--iOSClient/Main/Create cloud/NCCreateFormUploadAssets.swift1
-rw-r--r--iOSClient/Main/Create cloud/NCCreateFormUploadConflict.swift2
-rw-r--r--iOSClient/Main/Create cloud/NCCreateFormUploadDocuments.swift9
-rw-r--r--iOSClient/Main/Create cloud/NCCreateFormUploadScanDocument.swift8
-rw-r--r--iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift1
-rw-r--r--iOSClient/Main/NCFunctionCenter.swift71
-rw-r--r--iOSClient/Main/NCMainTabBar.swift4
-rw-r--r--iOSClient/Media/NCMedia.swift9
-rw-r--r--iOSClient/Menu/AppDelegate+Menu.swift25
-rw-r--r--iOSClient/Menu/NCCollectionViewCommon+Menu.swift86
-rw-r--r--iOSClient/Menu/NCMedia+Menu.swift6
-rw-r--r--iOSClient/Menu/NCMenu+FloatingPanel.swift17
-rw-r--r--iOSClient/Menu/NCMenu.storyboard39
-rw-r--r--iOSClient/Menu/NCMenu.swift24
-rw-r--r--iOSClient/Menu/NCMenuAction.swift63
-rw-r--r--iOSClient/Menu/NCShare+Menu.swift121
-rw-r--r--iOSClient/Menu/NCViewer+Menu.swift56
-rw-r--r--iOSClient/NCGlobal.swift10
-rw-r--r--iOSClient/Networking/NCAutoUpload.swift81
-rw-r--r--iOSClient/Networking/NCNetworking.swift180
-rw-r--r--iOSClient/Networking/NCNetworkingChunkedUpload.swift6
-rw-r--r--iOSClient/Networking/NCNetworkingProcessUpload.swift23
-rw-r--r--iOSClient/Select/NCSelect.storyboard9
-rw-r--r--iOSClient/Select/NCSelect.swift51
-rw-r--r--iOSClient/Settings/Acknowledgements.m5
-rw-r--r--iOSClient/Settings/Acknowledgements.rtf63
-rwxr-xr-xiOSClient/Settings/CCAdvanced.m29
-rw-r--r--iOSClient/Settings/CCManageAutoUpload.m106
-rw-r--r--iOSClient/Settings/NCManageAutoUploadFileName.swift6
-rw-r--r--iOSClient/Settings/NCSettings.m4
-rw-r--r--iOSClient/Share/Advanced/NCShareAdvancePermission.swift192
-rw-r--r--iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.swift66
-rw-r--r--iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.xib65
-rw-r--r--iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.swift51
-rw-r--r--iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.xib67
-rw-r--r--iOSClient/Share/Advanced/NCShareCells.swift304
-rw-r--r--iOSClient/Share/Advanced/NCShareNewUserAddComment.swift95
-rwxr-xr-xiOSClient/Share/NCSearchUserDropDownCell.xib (renamed from iOSClient/Share/NCShareUserDropDownCell.xib)6
-rw-r--r--iOSClient/Share/NCShare+Helper.swift109
-rw-r--r--iOSClient/Share/NCShare+NCCellDelegate.swift69
-rw-r--r--iOSClient/Share/NCShare.storyboard239
-rw-r--r--iOSClient/Share/NCShare.swift455
-rw-r--r--iOSClient/Share/NCShareCommentsCell.swift16
-rw-r--r--iOSClient/Share/NCShareCommon.swift128
-rw-r--r--iOSClient/Share/NCShareHeaderView.xib60
-rw-r--r--iOSClient/Share/NCShareLinkCell.swift62
-rwxr-xr-xiOSClient/Share/NCShareLinkCell.xib114
-rw-r--r--iOSClient/Share/NCShareLinkFolderMenuView.xib318
-rw-r--r--iOSClient/Share/NCShareLinkMenuView.swift484
-rw-r--r--iOSClient/Share/NCShareLinkMenuView.xib274
-rw-r--r--iOSClient/Share/NCShareNetworking.swift52
-rw-r--r--iOSClient/Share/NCSharePaging.swift180
-rw-r--r--iOSClient/Share/NCShareQuickStatusMenu.swift66
-rw-r--r--iOSClient/Share/NCShareUserCell.swift127
-rw-r--r--iOSClient/Share/NCShareUserFolderMenuView.xib226
-rw-r--r--iOSClient/Share/NCShareUserMenuView.swift398
-rw-r--r--iOSClient/Share/NCShareUserMenuView.xib160
-rw-r--r--iOSClient/Supporting Files/af.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/af.lproj/Localizable.stringsbin102626 -> 106806 bytes
-rw-r--r--iOSClient/Supporting Files/ar.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/ar.lproj/Localizable.stringsbin99786 -> 104208 bytes
-rw-r--r--iOSClient/Supporting Files/ast.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/ast.lproj/Localizable.stringsbin102738 -> 107106 bytes
-rw-r--r--iOSClient/Supporting Files/az.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/az.lproj/Localizable.stringsbin102274 -> 106500 bytes
-rw-r--r--iOSClient/Supporting Files/be.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/be.lproj/Localizable.stringsbin102070 -> 106250 bytes
-rw-r--r--iOSClient/Supporting Files/bg_BG.lproj/InfoPlist.stringsbin1704 -> 2034 bytes
-rw-r--r--iOSClient/Supporting Files/bg_BG.lproj/Localizable.stringsbin108066 -> 112782 bytes
-rw-r--r--iOSClient/Supporting Files/bn_BD.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/bn_BD.lproj/Localizable.stringsbin102212 -> 106412 bytes
-rw-r--r--iOSClient/Supporting Files/br.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/br.lproj/Localizable.stringsbin106536 -> 110822 bytes
-rw-r--r--iOSClient/Supporting Files/bs.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/bs.lproj/Localizable.stringsbin102204 -> 106476 bytes
-rw-r--r--iOSClient/Supporting Files/ca.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/ca.lproj/Localizable.stringsbin109132 -> 113582 bytes
-rw-r--r--iOSClient/Supporting Files/cs-CZ.lproj/Localizable.stringsbin105022 -> 109294 bytes
-rw-r--r--iOSClient/Supporting Files/cy_GB.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/cy_GB.lproj/Localizable.stringsbin102176 -> 106432 bytes
-rw-r--r--iOSClient/Supporting Files/da.lproj/InfoPlist.stringsbin1736 -> 1736 bytes
-rw-r--r--iOSClient/Supporting Files/da.lproj/Localizable.stringsbin102404 -> 106766 bytes
-rw-r--r--iOSClient/Supporting Files/de.lproj/Localizable.stringsbin111576 -> 116136 bytes
-rw-r--r--iOSClient/Supporting Files/el.lproj/InfoPlist.stringsbin1704 -> 1888 bytes
-rw-r--r--iOSClient/Supporting Files/el.lproj/Localizable.stringsbin112160 -> 117476 bytes
-rw-r--r--iOSClient/Supporting Files/en-GB.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/en-GB.lproj/Localizable.stringsbin102014 -> 106270 bytes
-rw-r--r--iOSClient/Supporting Files/en.lproj/InfoPlist.strings4
-rw-r--r--iOSClient/Supporting Files/en.lproj/Localizable.strings61
-rw-r--r--iOSClient/Supporting Files/eo.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/eo.lproj/Localizable.stringsbin102628 -> 106914 bytes
-rw-r--r--iOSClient/Supporting Files/es-419.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/es-419.lproj/Localizable.stringsbin105896 -> 110312 bytes
-rw-r--r--iOSClient/Supporting Files/es-AR.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/es-AR.lproj/Localizable.stringsbin104836 -> 109306 bytes
-rw-r--r--iOSClient/Supporting Files/es-CL.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/es-CL.lproj/Localizable.stringsbin106522 -> 110944 bytes
-rw-r--r--iOSClient/Supporting Files/es-CO.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/es-CO.lproj/Localizable.stringsbin106522 -> 110952 bytes
-rw-r--r--iOSClient/Supporting Files/es-CR.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/es-CR.lproj/Localizable.stringsbin106522 -> 110942 bytes
-rw-r--r--iOSClient/Supporting Files/es-DO.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/es-DO.lproj/Localizable.stringsbin106522 -> 110950 bytes
-rw-r--r--iOSClient/Supporting Files/es-EC.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/es-EC.lproj/Localizable.stringsbin106528 -> 110948 bytes
-rw-r--r--iOSClient/Supporting Files/es-GT.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/es-GT.lproj/Localizable.stringsbin106522 -> 110942 bytes
-rw-r--r--iOSClient/Supporting Files/es-HN.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/es-HN.lproj/Localizable.stringsbin105884 -> 110304 bytes
-rw-r--r--iOSClient/Supporting Files/es-MX.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/es-MX.lproj/Localizable.stringsbin106634 -> 111128 bytes
-rw-r--r--iOSClient/Supporting Files/es-NI.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/es-NI.lproj/Localizable.stringsbin105884 -> 110294 bytes
-rw-r--r--iOSClient/Supporting Files/es-PA.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/es-PA.lproj/Localizable.stringsbin105884 -> 110294 bytes
-rw-r--r--iOSClient/Supporting Files/es-PE.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/es-PE.lproj/Localizable.stringsbin105884 -> 110294 bytes
-rw-r--r--iOSClient/Supporting Files/es-PR.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/es-PR.lproj/Localizable.stringsbin105884 -> 110294 bytes
-rw-r--r--iOSClient/Supporting Files/es-PY.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/es-PY.lproj/Localizable.stringsbin105910 -> 110320 bytes
-rw-r--r--iOSClient/Supporting Files/es-SV.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/es-SV.lproj/Localizable.stringsbin106522 -> 110942 bytes
-rw-r--r--iOSClient/Supporting Files/es-UY.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/es-UY.lproj/Localizable.stringsbin105884 -> 110318 bytes
-rw-r--r--iOSClient/Supporting Files/es.lproj/InfoPlist.stringsbin1828 -> 1814 bytes
-rw-r--r--iOSClient/Supporting Files/es.lproj/Localizable.stringsbin109540 -> 113708 bytes
-rw-r--r--iOSClient/Supporting Files/et_EE.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/et_EE.lproj/Localizable.stringsbin102452 -> 106706 bytes
-rw-r--r--iOSClient/Supporting Files/eu.lproj/InfoPlist.stringsbin1704 -> 1916 bytes
-rw-r--r--iOSClient/Supporting Files/eu.lproj/Localizable.stringsbin108572 -> 113150 bytes
-rw-r--r--iOSClient/Supporting Files/fa.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/fa.lproj/Localizable.stringsbin102678 -> 107034 bytes
-rw-r--r--iOSClient/Supporting Files/fi-FI.lproj/InfoPlist.stringsbin1704 -> 1688 bytes
-rw-r--r--iOSClient/Supporting Files/fi-FI.lproj/Localizable.stringsbin104706 -> 108998 bytes
-rw-r--r--iOSClient/Supporting Files/fo.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/fo.lproj/Localizable.stringsbin102002 -> 106174 bytes
-rw-r--r--iOSClient/Supporting Files/fr.lproj/InfoPlist.stringsbin2110 -> 1856 bytes
-rw-r--r--iOSClient/Supporting Files/fr.lproj/Localizable.stringsbin113700 -> 117844 bytes
-rw-r--r--iOSClient/Supporting Files/gd.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/gd.lproj/Localizable.stringsbin101986 -> 107690 bytes
-rw-r--r--iOSClient/Supporting Files/gl.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/gl.lproj/Localizable.stringsbin108968 -> 113324 bytes
-rw-r--r--iOSClient/Supporting Files/he.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/he.lproj/Localizable.stringsbin100262 -> 104242 bytes
-rw-r--r--iOSClient/Supporting Files/hi_IN.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/hi_IN.lproj/Localizable.stringsbin101986 -> 106160 bytes
-rw-r--r--iOSClient/Supporting Files/hr.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/hr.lproj/Localizable.stringsbin107044 -> 111286 bytes
-rw-r--r--iOSClient/Supporting Files/hsb.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/hsb.lproj/Localizable.stringsbin101988 -> 106164 bytes
-rw-r--r--iOSClient/Supporting Files/hu.lproj/InfoPlist.stringsbin1826 -> 1852 bytes
-rw-r--r--iOSClient/Supporting Files/hu.lproj/Localizable.stringsbin105780 -> 111692 bytes
-rw-r--r--iOSClient/Supporting Files/hy.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/hy.lproj/Localizable.stringsbin102248 -> 106450 bytes
-rw-r--r--iOSClient/Supporting Files/ia.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/ia.lproj/Localizable.stringsbin102636 -> 106880 bytes
-rw-r--r--iOSClient/Supporting Files/id.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/id.lproj/Localizable.stringsbin102626 -> 106966 bytes
-rw-r--r--iOSClient/Supporting Files/ig.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/ig.lproj/Localizable.stringsbin101986 -> 106148 bytes
-rw-r--r--iOSClient/Supporting Files/is.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/is.lproj/Localizable.stringsbin104004 -> 108416 bytes
-rw-r--r--iOSClient/Supporting Files/it.lproj/InfoPlist.stringsbin1904 -> 1812 bytes
-rw-r--r--iOSClient/Supporting Files/it.lproj/Localizable.stringsbin109094 -> 113536 bytes
-rw-r--r--iOSClient/Supporting Files/ja-JP.lproj/InfoPlist.stringsbin1704 -> 1156 bytes
-rw-r--r--iOSClient/Supporting Files/ja-JP.lproj/Localizable.stringsbin86668 -> 88866 bytes
-rw-r--r--iOSClient/Supporting Files/ka-GE.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/ka-GE.lproj/Localizable.stringsbin104668 -> 109032 bytes
-rw-r--r--iOSClient/Supporting Files/ka.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/ka.lproj/Localizable.stringsbin101982 -> 106164 bytes
-rw-r--r--iOSClient/Supporting Files/kab.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/kab.lproj/Localizable.stringsbin102008 -> 106224 bytes
-rw-r--r--iOSClient/Supporting Files/kk.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/kk.lproj/Localizable.stringsbin101986 -> 106160 bytes
-rw-r--r--iOSClient/Supporting Files/km.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/km.lproj/Localizable.stringsbin102194 -> 106402 bytes
-rw-r--r--iOSClient/Supporting Files/kn.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/kn.lproj/Localizable.stringsbin102402 -> 106644 bytes
-rw-r--r--iOSClient/Supporting Files/ko.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/ko.lproj/Localizable.stringsbin83594 -> 88148 bytes
-rw-r--r--iOSClient/Supporting Files/la.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/la.lproj/Localizable.stringsbin101976 -> 106150 bytes
-rw-r--r--iOSClient/Supporting Files/lb.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/lb.lproj/Localizable.stringsbin102288 -> 106538 bytes
-rw-r--r--iOSClient/Supporting Files/lo.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/lo.lproj/Localizable.stringsbin100282 -> 104580 bytes
-rw-r--r--iOSClient/Supporting Files/lt_LT.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/lt_LT.lproj/Localizable.stringsbin104500 -> 108934 bytes
-rw-r--r--iOSClient/Supporting Files/lv.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/lv.lproj/Localizable.stringsbin102874 -> 107178 bytes
-rw-r--r--iOSClient/Supporting Files/mk.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/mk.lproj/Localizable.stringsbin103112 -> 107492 bytes
-rw-r--r--iOSClient/Supporting Files/mn.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/mn.lproj/Localizable.stringsbin102654 -> 106896 bytes
-rw-r--r--iOSClient/Supporting Files/mr.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/mr.lproj/Localizable.stringsbin101986 -> 106134 bytes
-rw-r--r--iOSClient/Supporting Files/ms_MY.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/ms_MY.lproj/Localizable.stringsbin102080 -> 106264 bytes
-rw-r--r--iOSClient/Supporting Files/my.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/my.lproj/Localizable.stringsbin102008 -> 106340 bytes
-rw-r--r--iOSClient/Supporting Files/nb-NO.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/nb-NO.lproj/Localizable.stringsbin102982 -> 107262 bytes
-rw-r--r--iOSClient/Supporting Files/ne.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/ne.lproj/Localizable.stringsbin102000 -> 106174 bytes
-rw-r--r--iOSClient/Supporting Files/nl.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/nl.lproj/Localizable.stringsbin107250 -> 111474 bytes
-rw-r--r--iOSClient/Supporting Files/nn_NO.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/nn_NO.lproj/Localizable.stringsbin102066 -> 106306 bytes
-rw-r--r--iOSClient/Supporting Files/oc.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/oc.lproj/Localizable.stringsbin102474 -> 107164 bytes
-rw-r--r--iOSClient/Supporting Files/pl.lproj/InfoPlist.stringsbin1802 -> 1792 bytes
-rw-r--r--iOSClient/Supporting Files/pl.lproj/Localizable.stringsbin106532 -> 110928 bytes
-rw-r--r--iOSClient/Supporting Files/ps.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/ps.lproj/Localizable.stringsbin102006 -> 106188 bytes
-rw-r--r--iOSClient/Supporting Files/pt-BR.lproj/InfoPlist.stringsbin1820 -> 1864 bytes
-rw-r--r--iOSClient/Supporting Files/pt-BR.lproj/Localizable.stringsbin107342 -> 111830 bytes
-rw-r--r--iOSClient/Supporting Files/pt-PT.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/pt-PT.lproj/Localizable.stringsbin105744 -> 110254 bytes
-rw-r--r--iOSClient/Supporting Files/ro.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/ro.lproj/Localizable.stringsbin104846 -> 109270 bytes
-rw-r--r--iOSClient/Supporting Files/ru.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/ru.lproj/Localizable.stringsbin106904 -> 111444 bytes
-rw-r--r--iOSClient/Supporting Files/sc.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/sc.lproj/Localizable.stringsbin111536 -> 115784 bytes
-rw-r--r--iOSClient/Supporting Files/si.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/si.lproj/Localizable.stringsbin102824 -> 107074 bytes
-rw-r--r--iOSClient/Supporting Files/sk-SK.lproj/InfoPlist.stringsbin1814 -> 1792 bytes
-rw-r--r--iOSClient/Supporting Files/sk-SK.lproj/Localizable.stringsbin106168 -> 110388 bytes
-rw-r--r--iOSClient/Supporting Files/sl.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/sl.lproj/Localizable.stringsbin107618 -> 111982 bytes
-rw-r--r--iOSClient/Supporting Files/sq.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/sq.lproj/Localizable.stringsbin103510 -> 107894 bytes
-rw-r--r--iOSClient/Supporting Files/sr.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/sr.lproj/Localizable.stringsbin103594 -> 107886 bytes
-rw-r--r--iOSClient/Supporting Files/sr@latin.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/sr@latin.lproj/Localizable.stringsbin102198 -> 106470 bytes
-rw-r--r--iOSClient/Supporting Files/sv.lproj/InfoPlist.stringsbin1696 -> 1688 bytes
-rw-r--r--iOSClient/Supporting Files/sv.lproj/Localizable.stringsbin103716 -> 108108 bytes
-rw-r--r--iOSClient/Supporting Files/sw.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/sw.lproj/Localizable.stringsbin101986 -> 106160 bytes
-rw-r--r--iOSClient/Supporting Files/ta.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/ta.lproj/Localizable.stringsbin102288 -> 106476 bytes
-rw-r--r--iOSClient/Supporting Files/th_TH.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/th_TH.lproj/Localizable.stringsbin102348 -> 106568 bytes
-rw-r--r--iOSClient/Supporting Files/tk.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/tk.lproj/Localizable.stringsbin102014 -> 106840 bytes
-rw-r--r--iOSClient/Supporting Files/tr.lproj/InfoPlist.stringsbin1936 -> 1942 bytes
-rw-r--r--iOSClient/Supporting Files/tr.lproj/Localizable.stringsbin105730 -> 110194 bytes
-rw-r--r--iOSClient/Supporting Files/ug.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/ug.lproj/Localizable.stringsbin102126 -> 106334 bytes
-rw-r--r--iOSClient/Supporting Files/uk.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/uk.lproj/Localizable.stringsbin103006 -> 107530 bytes
-rw-r--r--iOSClient/Supporting Files/ur_PK.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/ur_PK.lproj/Localizable.stringsbin102028 -> 106198 bytes
-rw-r--r--iOSClient/Supporting Files/uz.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/uz.lproj/Localizable.stringsbin102414 -> 106642 bytes
-rw-r--r--iOSClient/Supporting Files/vi.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/vi.lproj/Localizable.stringsbin102536 -> 107004 bytes
-rw-r--r--iOSClient/Supporting Files/zh-Hans.lproj/InfoPlist.stringsbin848 -> 1212 bytes
-rw-r--r--iOSClient/Supporting Files/zh-Hans.lproj/Localizable.stringsbin76320 -> 79466 bytes
-rw-r--r--iOSClient/Supporting Files/zh-Hant-TW.lproj/InfoPlist.stringsbin1704 -> 1696 bytes
-rw-r--r--iOSClient/Supporting Files/zh-Hant-TW.lproj/Localizable.stringsbin79016 -> 83444 bytes
-rw-r--r--iOSClient/Supporting Files/zh_HK.lproj/Localizable.stringsbin76696 -> 79802 bytes
-rwxr-xr-xiOSClient/Transfers/NCTransferCell.swift9
-rw-r--r--iOSClient/Transfers/NCTransfers.swift1
-rw-r--r--iOSClient/Trash/Cell/NCTrashListCell.swift25
-rw-r--r--iOSClient/Trash/NCTrash+CollectionView.swift2
-rw-r--r--iOSClient/Utility/CCUtility.h8
-rw-r--r--iOSClient/Utility/CCUtility.m66
-rw-r--r--iOSClient/Utility/NCAskAuthorization.swift38
-rw-r--r--iOSClient/Utility/NCUserBaseUrl.swift1
-rw-r--r--iOSClient/Utility/NCUtility+Image.swift91
-rw-r--r--iOSClient/Utility/NCUtility.swift106
-rw-r--r--iOSClient/Utility/NCUtilityFileSystem.swift14
-rw-r--r--iOSClient/Viewer/NCViewer.swift9
-rw-r--r--iOSClient/Viewer/NCViewerMedia/NCPlayer/NCKTVHTTPCache.swift20
-rw-r--r--iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift326
-rw-r--r--iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift130
-rw-r--r--iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.xib178
-rw-r--r--iOSClient/Viewer/NCViewerMedia/NCPlayer/NCSubtitle/NCSubtitlePlayer.swift405
-rw-r--r--iOSClient/Viewer/NCViewerMedia/NCPlayer/NCSubtitle/NCSubtitles.swift150
-rw-r--r--iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift85
-rw-r--r--iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift100
-rw-r--r--iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.storyboard174
-rw-r--r--iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.swift69
-rw-r--r--iOSClient/Viewer/NCViewerNextcloudText/NCViewerNextcloudText.swift6
-rw-r--r--iOSClient/Viewer/NCViewerPDF/NCViewerPDF.swift394
-rw-r--r--iOSClient/Viewer/NCViewerPDF/NCViewerPDFSearch.swift3
-rw-r--r--iOSClient/Viewer/NCViewerQuickLook/NCViewerQuickLook.swift179
392 files changed, 5748 insertions, 4682 deletions
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index e52d39172..887141563 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -9,16 +9,18 @@ on:
- master
- develop
pull_request:
+ types: [synchronize, opened, reopened, ready_for_review]
branches:
- master
- - develop
+ - develop
jobs:
Lint:
runs-on: ubuntu-latest
-
+ if: github.event.pull_request.draft == false
+
steps:
- uses: actions/checkout@v2
-
+
- name: GitHub Action for SwiftLint
- uses: norio-nomura/action-swiftlint@3.1.0
+ uses: norio-nomura/action-swiftlint@3.1.0 \ No newline at end of file
diff --git a/.github/workflows/xcode.yml b/.github/workflows/xcode.yml
index 65c3ff88d..02d4facef 100644
--- a/.github/workflows/xcode.yml
+++ b/.github/workflows/xcode.yml
@@ -1,11 +1,12 @@
name: Build
-on:
+on:
push:
- branches:
+ branches:
- master
- develop
pull_request:
+ types: [synchronize, opened, reopened, ready_for_review]
branches:
- master
- develop
@@ -13,6 +14,7 @@ on:
jobs:
XCBuild:
runs-on: macOS-11
+ if: github.event.pull_request.draft == false
env:
PROJECT: Nextcloud.xcodeproj
DESTINATION: platform=iOS Simulator,name=iPhone 11
diff --git a/.swiftlint.yml b/.swiftlint.yml
index fd76de49a..ac6e392d4 100644
--- a/.swiftlint.yml
+++ b/.swiftlint.yml
@@ -10,10 +10,14 @@ empty_count:
severity: warning
line_length:
- # warning: 120
+ # warning: 120, error: 200
warning: 250
error: 250
+function_body_length:
+ # warning: 40
+ warning: 60
+
type_body_length:
# error: 350
error: 500
@@ -48,7 +52,8 @@ excluded:
- iOSClient/Data/NCManageDatabase+Account.swift
- iOSClient/Data/NCManageDatabase+Activity.swift
- iOSClient/Data/NCManageDatabase.swift
- - iOSClient/Data/NCManageDatabse+Metadata.swift
+ - iOSClient/Data/NCManageDatabase+Metadata.swift
+ - iOSClient/Data/NCManageDatabase+Video.swift
- iOSClient/Diagnostics/NCCapabilitiesViewController.swift
- iOSClient/EmptyView/NCEmptyDataSet.swift
- iOSClient/Extensions/UIColor+Extensions.swift
@@ -105,16 +110,8 @@ excluded:
- iOSClient/Select/NCSelect.swift
- iOSClient/Settings/NCEndToEndInitialize.swift
- iOSClient/Settings/NCManageAutoUploadFileName.swift
- - iOSClient/Share/NCShare.swift
- - iOSClient/Share/NCShareCommentsCell.swift
- iOSClient/Share/NCShareCommon.swift
- - iOSClient/Share/NCShareLinkCell.swift
- - iOSClient/Share/NCShareLinkMenuView.swift
- iOSClient/Share/NCShareNetworking.swift
- - iOSClient/Share/NCSharePaging.swift
- - iOSClient/Share/NCShareQuickStatusMenu.swift
- - iOSClient/Share/NCShareUserCell.swift
- - iOSClient/Share/NCShareUserMenuView.swift
- iOSClient/Shares/NCShares.swift
- iOSClient/Transfers/NCTransferCell.swift
- iOSClient/Transfers/NCTransfers.swift
@@ -130,13 +127,11 @@ excluded:
- iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift
- iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift
- iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift
- - iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift
- iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.swift
- iOSClient/Viewer/NCViewerNextcloudText/NCViewerNextcloudText.swift
- iOSClient/Viewer/NCViewerPDF/NCViewerPDF.swift
- iOSClient/Viewer/NCViewerPDF/NCViewerPDFSearch.swift
- iOSClient/Viewer/NCViewerProviderContextMenu.swift
- - iOSClient/Viewer/NCViewerQuickLook/NCViewerQuickLook.swift
- iOSClient/Viewer/NCViewerRichdocument/NCViewerRichdocument.swift
diff --git a/Cartfile b/Cartfile
index 75e1cbfe8..32f8159f0 100644
--- a/Cartfile
+++ b/Cartfile
@@ -1,3 +1,3 @@
-github "https://github.com/marinofaggiana/KTVHTTPCache" "2.0.2"
+github "https://github.com/marinofaggiana/KTVHTTPCache" "2.0.5"
github "https://github.com/marinofaggiana/TOPasscodeViewController" "master"
github "krzyzanowskim/OpenSSL" \ No newline at end of file
diff --git a/Cartfile.resolved b/Cartfile.resolved
index 013ceec7d..ce55f69c1 100644
--- a/Cartfile.resolved
+++ b/Cartfile.resolved
@@ -1,3 +1,3 @@
github "krzyzanowskim/OpenSSL" "1.1.1300"
-github "marinofaggiana/KTVHTTPCache" "2.0.2"
+github "marinofaggiana/KTVHTTPCache" "2.0.5"
github "marinofaggiana/TOPasscodeViewController" "a1b9d1058b2648e636525fc368e220a0cfddb42a"
diff --git a/File Provider Extension/FileProviderItem.swift b/File Provider Extension/FileProviderItem.swift
index ea00cf1a5..28f752099 100644
--- a/File Provider Extension/FileProviderItem.swift
+++ b/File Provider Extension/FileProviderItem.swift
@@ -60,11 +60,13 @@ class FileProviderItem: NSObject, NSFileProviderItem {
}
var capabilities: NSFileProviderItemCapabilities {
- if metadata.directory {
+ guard !metadata.directory else {
return [ .allowsAddingSubItems, .allowsContentEnumerating, .allowsReading, .allowsDeleting, .allowsRenaming ]
- } else {
- return [ .allowsWriting, .allowsReading, .allowsDeleting, .allowsRenaming, .allowsReparenting ]
}
+ guard !metadata.lock else {
+ return [ .allowsReading ]
+ }
+ return [ .allowsWriting, .allowsReading, .allowsDeleting, .allowsRenaming, .allowsReparenting ]
}
var isTrashed: Bool {
diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj
index ad0185bcb..0bd1dd77b 100644
--- a/Nextcloud.xcodeproj/project.pbxproj
+++ b/Nextcloud.xcodeproj/project.pbxproj
@@ -18,6 +18,8 @@
371B5A2E23D0B04500FAFAE9 /* NCMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371B5A2D23D0B04500FAFAE9 /* NCMenu.swift */; };
3781B9B023DB2B7E006B4B1D /* AppDelegate+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3781B9AF23DB2B7E006B4B1D /* AppDelegate+Menu.swift */; };
8491B1CD273BBA82001C8C5B /* UIViewController+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8491B1CC273BBA82001C8C5B /* UIViewController+Menu.swift */; };
+ AF1A9B6427D0CA1E00F17A9E /* UIAlertController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1A9B6327D0CA1E00F17A9E /* UIAlertController+Extension.swift */; };
+ AF1A9B6527D0CC0500F17A9E /* UIAlertController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1A9B6327D0CA1E00F17A9E /* UIAlertController+Extension.swift */; };
AF22B206277B4E4C00DAB0CC /* NCCreateFormUploadConflict.swift in Sources */ = {isa = PBXBuildFile; fileRef = F704B5E42430AA8000632F5F /* NCCreateFormUploadConflict.swift */; };
AF22B207277B4E4C00DAB0CC /* NCCreateFormUploadConflict.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F704B5E22430AA6F00632F5F /* NCCreateFormUploadConflict.storyboard */; };
AF22B208277B4E4C00DAB0CC /* NCCreateFormUploadConflictCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F704B5E82430C0B800632F5F /* NCCreateFormUploadConflictCell.swift */; };
@@ -29,21 +31,25 @@
AF2D7C7E2742559100ADF566 /* NCShareUserCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF2D7C7D2742559100ADF566 /* NCShareUserCell.swift */; };
AF36077127BFA4E8001A243D /* ParallelWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF36077027BFA4E8001A243D /* ParallelWorker.swift */; };
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 */; };
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 */; };
AF4BF617275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */; };
- AF4BF61927562A4B0081CEEF /* NCManageDatabse+Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF61827562A4B0081CEEF /* NCManageDatabse+Metadata.swift */; };
- AF4BF61A27562A4B0081CEEF /* NCManageDatabse+Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF61827562A4B0081CEEF /* NCManageDatabse+Metadata.swift */; };
- AF4BF61B27562A4B0081CEEF /* NCManageDatabse+Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF61827562A4B0081CEEF /* NCManageDatabse+Metadata.swift */; };
- AF4BF61C27562A4B0081CEEF /* NCManageDatabse+Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF61827562A4B0081CEEF /* NCManageDatabse+Metadata.swift */; };
+ AF4BF61927562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF61827562A4B0081CEEF /* NCManageDatabase+Metadata.swift */; };
+ AF4BF61A27562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF61827562A4B0081CEEF /* NCManageDatabase+Metadata.swift */; };
+ AF4BF61B27562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF61827562A4B0081CEEF /* NCManageDatabase+Metadata.swift */; };
+ AF4BF61C27562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF61827562A4B0081CEEF /* NCManageDatabase+Metadata.swift */; };
AF4BF61E27562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF61D27562B3F0081CEEF /* NCManageDatabase+Activity.swift */; };
AF4BF61F27562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF61D27562B3F0081CEEF /* NCManageDatabase+Activity.swift */; };
AF4BF62027562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF61D27562B3F0081CEEF /* NCManageDatabase+Activity.swift */; };
AF4BF62127562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF61D27562B3F0081CEEF /* NCManageDatabase+Activity.swift */; };
+ AF56C1DC2784856200D8BAE2 /* NCActivityCommentView.xib in Resources */ = {isa = PBXBuildFile; fileRef = AF56C1DB2784856200D8BAE2 /* NCActivityCommentView.xib */; };
AF68326A27BE65A90010BF0B /* NCMenuAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF68326927BE65A90010BF0B /* NCMenuAction.swift */; };
+ AF70C14D27F3484D00E13DF2 /* SharePermissionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF70C14C27F3484D00E13DF2 /* SharePermissionTest.swift */; };
+ AF730AF827834B1400B7520E /* NCShare+NCCellDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF730AF727834B1400B7520E /* NCShare+NCCellDelegate.swift */; };
AF730AFA27843E4C00B7520E /* NCShareExtension+NCDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF730AF927843E4C00B7520E /* NCShareExtension+NCDelegate.swift */; };
AF7E504E27A2D8FF00B5E4AF /* UIBarButton+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF7E504D27A2D8FF00B5E4AF /* UIBarButton+Extension.swift */; };
AF7E505027A2D92300B5E4AF /* NCSelectableNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF7E504F27A2D92300B5E4AF /* NCSelectableNavigationView.swift */; };
@@ -53,7 +59,20 @@
AF817EF4274BC781009ED85B /* NCUserBaseUrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF817EF0274BC781009ED85B /* NCUserBaseUrl.swift */; };
AF8ED1FC2757821000B8DBC4 /* NextcloudTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF8ED1FB2757821000B8DBC4 /* NextcloudTests.swift */; };
AF8ED2032757822700B8DBC4 /* NCGlobalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF8ED2022757822700B8DBC4 /* NCGlobalTests.swift */; };
+ AF93471227E2341B002537EE /* NCShare+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF93471127E2341B002537EE /* NCShare+Menu.swift */; };
+ AF93471927E2361E002537EE /* NCShareAdvancePermissionFooter.xib in Resources */ = {isa = PBXBuildFile; fileRef = AF93471427E2361E002537EE /* NCShareAdvancePermissionFooter.xib */; };
+ AF93471A27E2361E002537EE /* NCShareAdvancePermissionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF93471527E2361E002537EE /* NCShareAdvancePermissionHeader.swift */; };
+ AF93471B27E2361E002537EE /* NCShareAdvancePermission.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF93471627E2361E002537EE /* NCShareAdvancePermission.swift */; };
+ AF93471C27E2361E002537EE /* NCShareAdvancePermissionHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = AF93471727E2361E002537EE /* NCShareAdvancePermissionHeader.xib */; };
+ AF93471D27E2361E002537EE /* NCShareAdvancePermissionFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF93471827E2361E002537EE /* NCShareAdvancePermissionFooter.swift */; };
+ AF93474C27E34120002537EE /* NCUtility+Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF93474B27E34120002537EE /* NCUtility+Image.swift */; };
+ AF93474E27E3F212002537EE /* NCShareNewUserAddComment.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF93474D27E3F211002537EE /* NCShareNewUserAddComment.swift */; };
AF935067276B84E700BD078F /* NCMenu+FloatingPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF935066276B84E700BD078F /* NCMenu+FloatingPanel.swift */; };
+ AFA2AC8527849604008E1EA7 /* NCActivityCommentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA2AC8427849604008E1EA7 /* NCActivityCommentView.swift */; };
+ AFCE353327E4ED1900FEA6C2 /* UIToolbar+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353227E4ED1900FEA6C2 /* UIToolbar+Extension.swift */; };
+ AFCE353527E4ED5900FEA6C2 /* DateFormatter+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353427E4ED5900FEA6C2 /* DateFormatter+Extension.swift */; };
+ AFCE353727E4ED7B00FEA6C2 /* NCShareCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353627E4ED7B00FEA6C2 /* NCShareCells.swift */; };
+ AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; };
AFD33240276A02C100F5AE02 /* UIApplication+Orientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFD3323F276A02C000F5AE02 /* UIApplication+Orientation.swift */; };
D575039F27146F93008DC9DC /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extensions.swift */; };
D5B6AA7827200C7200D49C24 /* NCActivityTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */; };
@@ -142,6 +161,7 @@
F72D404923D2082500A97FD0 /* NCViewerNextcloudText.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72D404823D2082500A97FD0 /* NCViewerNextcloudText.swift */; };
F72D7EB7263B1207000B3DFC /* MarkdownKit in Frameworks */ = {isa = PBXBuildFile; productRef = F72D7EB6263B1207000B3DFC /* MarkdownKit */; };
F72DA9B425F53E4E00B87DB1 /* SwiftRichString in Frameworks */ = {isa = PBXBuildFile; productRef = F72DA9B325F53E4E00B87DB1 /* SwiftRichString */; };
+ F732D23327CF8AED000B0F1B /* NCPlayerToolBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = F732D23227CF8AED000B0F1B /* NCPlayerToolBar.xib */; };
F733598125C1C188002ABA72 /* NCAskAuthorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = F733598025C1C188002ABA72 /* NCAskAuthorization.swift */; };
F7362A1F220C853A005101B5 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7362A1E220C853A005101B5 /* LaunchScreen.storyboard */; };
F7381EE1218218C9000B1560 /* NCOffline.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7381EDA218218C9000B1560 /* NCOffline.swift */; };
@@ -188,6 +208,7 @@
F74E7720277A2EF40013B958 /* XLForm in Frameworks */ = {isa = PBXBuildFile; productRef = F74E771F277A2EF40013B958 /* XLForm */; };
F7501C322212E57500FB1415 /* NCMedia.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7501C302212E57400FB1415 /* NCMedia.storyboard */; };
F7501C332212E57500FB1415 /* NCMedia.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7501C312212E57400FB1415 /* NCMedia.swift */; };
+ F753BA93281FD8020015BFB6 /* EasyTipView in Frameworks */ = {isa = PBXBuildFile; productRef = F753BA92281FD8020015BFB6 /* EasyTipView */; };
F755BD9B20594AC7008C5FBB /* NCService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F755BD9A20594AC7008C5FBB /* NCService.swift */; };
F7581D1A25EFDA61004DC699 /* NCLoginWeb+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7581D1925EFDA60004DC699 /* NCLoginWeb+Menu.swift */; };
F7581D2425EFDDDF004DC699 /* NCMedia+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7581D2325EFDDDF004DC699 /* NCMedia+Menu.swift */; };
@@ -219,10 +240,7 @@
F76673F022C90434007ED366 /* FileProviderUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76673EF22C90433007ED366 /* FileProviderUtility.swift */; };
F7682FE023C36B0500983A04 /* NCMainTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7682FDF23C36B0500983A04 /* NCMainTabBar.swift */; };
F769453C22E9CFFF000A798A /* NCShareUserCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F769453B22E9CFFF000A798A /* NCShareUserCell.xib */; };
- F769453E22E9E97E000A798A /* NCShareUserMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F769453D22E9E97D000A798A /* NCShareUserMenuView.xib */; };
F769454022E9F077000A798A /* NCSharePaging.swift in Sources */ = {isa = PBXBuildFile; fileRef = F769453F22E9F077000A798A /* NCSharePaging.swift */; };
- F769454222E9F0EE000A798A /* NCShareLinkMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F769454122E9F0EE000A798A /* NCShareLinkMenuView.swift */; };
- F769454422E9F142000A798A /* NCShareUserMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F769454322E9F142000A798A /* NCShareUserMenuView.swift */; };
F769454622E9F1B0000A798A /* NCShareCommon.swift in Sources */ = {isa = PBXBuildFile; fileRef = F769454522E9F1B0000A798A /* NCShareCommon.swift */; };
F769454822E9F20D000A798A /* NCShareNetworking.swift in Sources */ = {isa = PBXBuildFile; fileRef = F769454722E9F20D000A798A /* NCShareNetworking.swift */; };
F76B3CCE1EAE01BD00921AC9 /* NCBrand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76B3CCD1EAE01BD00921AC9 /* NCBrand.swift */; };
@@ -239,7 +257,6 @@
F76DA963277B760E0082465B /* Queuer in Frameworks */ = {isa = PBXBuildFile; productRef = F76DA962277B760E0082465B /* Queuer */; };
F76DA966277B76F30082465B /* UICKeyChainStore in Frameworks */ = {isa = PBXBuildFile; productRef = F76DA965277B76F30082465B /* UICKeyChainStore */; };
F76DA969277B77EA0082465B /* DropDown in Frameworks */ = {isa = PBXBuildFile; productRef = F76DA968277B77EA0082465B /* DropDown */; };
- F76DA96C277B78400082465B /* FSCalendar in Frameworks */ = {isa = PBXBuildFile; productRef = F76DA96B277B78400082465B /* FSCalendar */; };
F76DA96F277B78AE0082465B /* TLPhotoPicker in Frameworks */ = {isa = PBXBuildFile; productRef = F76DA96E277B78AE0082465B /* TLPhotoPicker */; };
F7707687263A853700A1BA94 /* NCContentPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F765608E23BF813500765969 /* NCContentPresenter.swift */; };
F7707689263A896A00A1BA94 /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extensions.swift */; };
@@ -254,7 +271,7 @@
F771E3F820E239B500AFB62D /* FileProviderExtension+Thumbnail.swift in Sources */ = {isa = PBXBuildFile; fileRef = F771E3F520E239B400AFB62D /* FileProviderExtension+Thumbnail.swift */; };
F7725A60251F33BB00D125E0 /* NCFiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7725A5E251F33BB00D125E0 /* NCFiles.swift */; };
F7725A61251F33BB00D125E0 /* NCFiles.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7725A5F251F33BB00D125E0 /* NCFiles.storyboard */; };
- F774264A22EB4D0000B23912 /* NCShareUserDropDownCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F774264822EB4D0000B23912 /* NCShareUserDropDownCell.xib */; };
+ F774264A22EB4D0000B23912 /* NCSearchUserDropDownCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F774264822EB4D0000B23912 /* NCSearchUserDropDownCell.xib */; };
F77444F522281649000D5EB0 /* NCGridMediaCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77444F322281649000D5EB0 /* NCGridMediaCell.swift */; };
F77444F622281649000D5EB0 /* NCGridMediaCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F77444F422281649000D5EB0 /* NCGridMediaCell.xib */; };
F77444F8222816D5000D5EB0 /* NCPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77444F7222816D5000D5EB0 /* NCPickerViewController.swift */; };
@@ -269,7 +286,6 @@
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 */; };
- F77EFC0C26D6751F00806ED6 /* NCShareQuickStatusMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77EFC0B26D6751F00806ED6 /* NCShareQuickStatusMenu.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 */; };
@@ -299,8 +315,6 @@
F78F74342163757000C2ADAD /* NCTrash.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F78F74332163757000C2ADAD /* NCTrash.storyboard */; };
F78F74362163781100C2ADAD /* NCTrash.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78F74352163781100C2ADAD /* NCTrash.swift */; };
F790110E21415BF600D7B136 /* NCViewerRichdocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = F790110D21415BF600D7B136 /* NCViewerRichdocument.swift */; };
- F79728D422F96F2E003CACA7 /* NCShareLinkFolderMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F79728D322F96F2D003CACA7 /* NCShareLinkFolderMenuView.xib */; };
- F79728D622F9A0B1003CACA7 /* NCShareUserFolderMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F79728D522F9A0B0003CACA7 /* NCShareUserFolderMenuView.xib */; };
F798F0E225880608000DAFFD /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */; };
F798F0E725880609000DAFFD /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */; };
F798F0EC2588060A000DAFFD /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */; };
@@ -356,7 +370,6 @@
F7D57C8B26317BDE00DE301D /* NCAccountRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CA212B25F1333200826ABB /* NCAccountRequest.swift */; };
F7D96FCC246ED7E200536D73 /* NCNetworkingCheckRemoteUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D96FCB246ED7E100536D73 /* NCNetworkingCheckRemoteUser.swift */; };
F7DBC37C23325E02001A85BA /* NCAppConfigView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DBC37B23325E01001A85BA /* NCAppConfigView.swift */; };
- F7DFAA8A22E22EF100FC4527 /* NCShareLinkMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7DFAA8922E22EF100FC4527 /* NCShareLinkMenuView.xib */; };
F7DFB7F0219C5B8000680748 /* NCCreateFormUploadAssets.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DFB7EF219C5B8000680748 /* NCCreateFormUploadAssets.swift */; };
F7DFB7F4219C5CA800680748 /* NCCreateFormUploadScanDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DFB7F3219C5CA800680748 /* NCCreateFormUploadScanDocument.swift */; };
F7E0CDCF265CE8610044854E /* NCUserStatus.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7E0CDCE265CE8610044854E /* NCUserStatus.storyboard */; };
@@ -364,6 +377,10 @@
F7E572FD278F146C00F8C99E /* OpenSSL.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = F70B86802642CF5400ED5349 /* OpenSSL.xcframework */; };
F7E572FE278F146C00F8C99E /* OpenSSL.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F70B86802642CF5400ED5349 /* OpenSSL.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
F7E57302278F14FF00F8C99E /* OpenSSL.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = F70B86802642CF5400ED5349 /* OpenSSL.xcframework */; };
+ F7E98C1627E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E98C1527E0D0FC001F9F19 /* NCManageDatabase+Video.swift */; };
+ F7E98C1727E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E98C1527E0D0FC001F9F19 /* NCManageDatabase+Video.swift */; };
+ F7E98C1827E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E98C1527E0D0FC001F9F19 /* NCManageDatabase+Video.swift */; };
+ F7E98C1927E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E98C1527E0D0FC001F9F19 /* NCManageDatabase+Video.swift */; };
F7EBCDCF277B81FF00A4EF67 /* UICKeyChainStore in Frameworks */ = {isa = PBXBuildFile; productRef = F7EBCDCE277B81FF00A4EF67 /* UICKeyChainStore */; };
F7EBCDD1277B820D00A4EF67 /* UICKeyChainStore in Frameworks */ = {isa = PBXBuildFile; productRef = F7EBCDD0277B820D00A4EF67 /* UICKeyChainStore */; };
F7EBCDD3277B821700A4EF67 /* UICKeyChainStore in Frameworks */ = {isa = PBXBuildFile; productRef = F7EBCDD2277B821700A4EF67 /* UICKeyChainStore */; };
@@ -384,6 +401,18 @@
F7EFC0C6256BC77700461AAD /* NCMoreUserCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7EFC0C5256BC77700461AAD /* NCMoreUserCell.xib */; };
F7EFC0CD256BF8DD00461AAD /* NCUserStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7EFC0CC256BF8DD00461AAD /* NCUserStatus.swift */; };
F7F1E54C2492369A00E42386 /* NCMediaCommandView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7F1E54B2492369A00E42386 /* NCMediaCommandView.xib */; };
+ F7F4F0F727ECDBA4008676F9 /* NCSubtitles.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F4F0F327ECDBA4008676F9 /* NCSubtitles.swift */; };
+ F7F4F0F927ECDBA4008676F9 /* NCSubtitlePlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F4F0F527ECDBA4008676F9 /* NCSubtitlePlayer.swift */; };
+ F7F4F10527ECDBDB008676F9 /* Inconsolata-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F7F4F0FD27ECDBDB008676F9 /* Inconsolata-SemiBold.ttf */; };
+ F7F4F10627ECDBDB008676F9 /* Inconsolata-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F7F4F0FE27ECDBDB008676F9 /* Inconsolata-Medium.ttf */; };
+ F7F4F10727ECDBDB008676F9 /* Inconsolata-Black.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F7F4F0FF27ECDBDB008676F9 /* Inconsolata-Black.ttf */; };
+ F7F4F10827ECDBDB008676F9 /* Inconsolata-ExtraLight.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F7F4F10027ECDBDB008676F9 /* Inconsolata-ExtraLight.ttf */; };
+ F7F4F10927ECDBDB008676F9 /* Inconsolata-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F7F4F10127ECDBDB008676F9 /* Inconsolata-Bold.ttf */; };
+ F7F4F10A27ECDBDB008676F9 /* Inconsolata-ExtraBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F7F4F10227ECDBDB008676F9 /* Inconsolata-ExtraBold.ttf */; };
+ F7F4F10B27ECDBDB008676F9 /* Inconsolata-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F7F4F10327ECDBDB008676F9 /* Inconsolata-Light.ttf */; };
+ F7F4F10C27ECDBDB008676F9 /* Inconsolata-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F7F4F10427ECDBDB008676F9 /* Inconsolata-Regular.ttf */; };
+ F7F4F11027ECDC4A008676F9 /* UIDevice+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F4F10F27ECDC4A008676F9 /* UIDevice+Extensions.swift */; };
+ F7F4F11227ECDC52008676F9 /* UIFont+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F4F11127ECDC52008676F9 /* UIFont+Extension.swift */; };
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 */; };
@@ -465,6 +494,7 @@
371B5A3223D0BD5500FAFAE9 /* FloatingPanel.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FloatingPanel.framework; path = Carthage/Build/iOS/FloatingPanel.framework; sourceTree = "<group>"; };
3781B9AF23DB2B7E006B4B1D /* AppDelegate+Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+Menu.swift"; sourceTree = "<group>"; };
8491B1CC273BBA82001C8C5B /* UIViewController+Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Menu.swift"; sourceTree = "<group>"; };
+ AF1A9B6327D0CA1E00F17A9E /* UIAlertController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIAlertController+Extension.swift"; sourceTree = "<group>"; };
AF22B20B277C6F4D00DAB0CC /* NCShareCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareCell.swift; sourceTree = "<group>"; };
AF22B215277D196700DAB0CC /* NCShareExtension+DataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCShareExtension+DataSource.swift"; sourceTree = "<group>"; };
AF22B216277D196700DAB0CC /* NCShareExtension+Files.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCShareExtension+Files.swift"; sourceTree = "<group>"; };
@@ -472,11 +502,15 @@
AF2D7C7D2742559100ADF566 /* NCShareUserCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareUserCell.swift; sourceTree = "<group>"; };
AF36077027BFA4E8001A243D /* ParallelWorker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParallelWorker.swift; sourceTree = "<group>"; };
AF36077527BFB019001A243D /* ParallelWorkerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParallelWorkerTest.swift; sourceTree = "<group>"; };
+ AF3F909928213BEA0048A93E /* UserAgentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAgentTests.swift; sourceTree = "<group>"; };
AF3FDCC12796ECC300710F60 /* NCTrash+CollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCTrash+CollectionView.swift"; sourceTree = "<group>"; };
AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+Account.swift"; sourceTree = "<group>"; };
- AF4BF61827562A4B0081CEEF /* NCManageDatabse+Metadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabse+Metadata.swift"; sourceTree = "<group>"; };
+ AF4BF61827562A4B0081CEEF /* NCManageDatabase+Metadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+Metadata.swift"; sourceTree = "<group>"; };
AF4BF61D27562B3F0081CEEF /* NCManageDatabase+Activity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+Activity.swift"; sourceTree = "<group>"; };
+ AF56C1DB2784856200D8BAE2 /* NCActivityCommentView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCActivityCommentView.xib; sourceTree = "<group>"; };
AF68326927BE65A90010BF0B /* NCMenuAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMenuAction.swift; sourceTree = "<group>"; };
+ AF70C14C27F3484D00E13DF2 /* SharePermissionTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharePermissionTest.swift; sourceTree = "<group>"; };
+ AF730AF727834B1400B7520E /* NCShare+NCCellDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+NCCellDelegate.swift"; sourceTree = "<group>"; };
AF730AF927843E4C00B7520E /* NCShareExtension+NCDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShareExtension+NCDelegate.swift"; sourceTree = "<group>"; };
AF7E504D27A2D8FF00B5E4AF /* UIBarButton+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIBarButton+Extension.swift"; sourceTree = "<group>"; };
AF7E504F27A2D92300B5E4AF /* NCSelectableNavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSelectableNavigationView.swift; sourceTree = "<group>"; };
@@ -484,7 +518,20 @@
AF8ED1F92757821000B8DBC4 /* NextcloudTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NextcloudTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
AF8ED1FB2757821000B8DBC4 /* NextcloudTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextcloudTests.swift; sourceTree = "<group>"; };
AF8ED2022757822700B8DBC4 /* NCGlobalTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCGlobalTests.swift; sourceTree = "<group>"; };
+ AF93471127E2341B002537EE /* NCShare+Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Menu.swift"; sourceTree = "<group>"; };
+ AF93471427E2361E002537EE /* NCShareAdvancePermissionFooter.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCShareAdvancePermissionFooter.xib; sourceTree = "<group>"; };
+ AF93471527E2361E002537EE /* NCShareAdvancePermissionHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCShareAdvancePermissionHeader.swift; sourceTree = "<group>"; };
+ AF93471627E2361E002537EE /* NCShareAdvancePermission.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCShareAdvancePermission.swift; sourceTree = "<group>"; };
+ AF93471727E2361E002537EE /* NCShareAdvancePermissionHeader.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCShareAdvancePermissionHeader.xib; sourceTree = "<group>"; };
+ AF93471827E2361E002537EE /* NCShareAdvancePermissionFooter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCShareAdvancePermissionFooter.swift; sourceTree = "<group>"; };
+ AF93474B27E34120002537EE /* NCUtility+Image.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCUtility+Image.swift"; sourceTree = "<group>"; };
+ AF93474D27E3F211002537EE /* NCShareNewUserAddComment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCShareNewUserAddComment.swift; sourceTree = "<group>"; };
AF935066276B84E700BD078F /* NCMenu+FloatingPanel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCMenu+FloatingPanel.swift"; sourceTree = "<group>"; };
+ AFA2AC8427849604008E1EA7 /* NCActivityCommentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCActivityCommentView.swift; sourceTree = "<group>"; };
+ AFCE353227E4ED1900FEA6C2 /* UIToolbar+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIToolbar+Extension.swift"; sourceTree = "<group>"; };
+ AFCE353427E4ED5900FEA6C2 /* DateFormatter+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DateFormatter+Extension.swift"; sourceTree = "<group>"; };
+ AFCE353627E4ED7B00FEA6C2 /* NCShareCells.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareCells.swift; sourceTree = "<group>"; };
+ AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = "<group>"; };
AFD3323F276A02C000F5AE02 /* UIApplication+Orientation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIApplication+Orientation.swift"; sourceTree = "<group>"; };
D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCActivityTableViewCell.swift; sourceTree = "<group>"; };
F700222B1EC479840080073F /* Custom.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Custom.xcassets; sourceTree = "<group>"; };
@@ -610,6 +657,7 @@
F72E0B9C21AD60BC00898D7B /* WeScan.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WeScan.framework; path = Carthage/Build/iOS/WeScan.framework; sourceTree = "<group>"; };
F7320934201B812F008A0888 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = "<group>"; };
F732093B201B81E4008A0888 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/Localizable.strings"; sourceTree = "<group>"; };
+ F732D23227CF8AED000B0F1B /* NCPlayerToolBar.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCPlayerToolBar.xib; sourceTree = "<group>"; };
F733598025C1C188002ABA72 /* NCAskAuthorization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCAskAuthorization.swift; sourceTree = "<group>"; };
F733B65121997CC1001C1FFA /* TLPhotoPicker.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TLPhotoPicker.framework; path = Carthage/Build/iOS/TLPhotoPicker.framework; sourceTree = "<group>"; };
F7362A1E220C853A005101B5 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
@@ -682,10 +730,7 @@
F76673EF22C90433007ED366 /* FileProviderUtility.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileProviderUtility.swift; sourceTree = "<group>"; };
F7682FDF23C36B0500983A04 /* NCMainTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMainTabBar.swift; sourceTree = "<group>"; };
F769453B22E9CFFF000A798A /* NCShareUserCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCShareUserCell.xib; sourceTree = "<group>"; };
- F769453D22E9E97D000A798A /* NCShareUserMenuView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCShareUserMenuView.xib; sourceTree = "<group>"; };
F769453F22E9F077000A798A /* NCSharePaging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSharePaging.swift; sourceTree = "<group>"; };
- F769454122E9F0EE000A798A /* NCShareLinkMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareLinkMenuView.swift; sourceTree = "<group>"; };
- F769454322E9F142000A798A /* NCShareUserMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareUserMenuView.swift; sourceTree = "<group>"; };
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>"; };
@@ -706,7 +751,7 @@
F7725A5E251F33BB00D125E0 /* NCFiles.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCFiles.swift; sourceTree = "<group>"; };
F7725A5F251F33BB00D125E0 /* NCFiles.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCFiles.storyboard; sourceTree = "<group>"; };
F774264022EB3F7300B23912 /* DropDown.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DropDown.framework; path = Carthage/Build/iOS/DropDown.framework; sourceTree = "<group>"; };
- F774264822EB4D0000B23912 /* NCShareUserDropDownCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCShareUserDropDownCell.xib; sourceTree = "<group>"; };
+ F774264822EB4D0000B23912 /* NCSearchUserDropDownCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCSearchUserDropDownCell.xib; sourceTree = "<group>"; };
F77438EB1FCD694900662C46 /* ka-GE */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ka-GE"; path = "ka-GE.lproj/Localizable.strings"; sourceTree = "<group>"; };
F77438F21FCD69D300662C46 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Localizable.strings; sourceTree = "<group>"; };
F77438F91FCD6A0D00662C46 /* zh-Hant-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant-TW"; path = "zh-Hant-TW.lproj/Localizable.strings"; sourceTree = "<group>"; };
@@ -731,7 +776,6 @@
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>"; };
- F77EFC0B26D6751F00806ED6 /* NCShareQuickStatusMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCShareQuickStatusMenu.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>"; };
@@ -755,8 +799,6 @@
F78F74352163781100C2ADAD /* NCTrash.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCTrash.swift; sourceTree = "<group>"; };
F790110D21415BF600D7B136 /* NCViewerRichdocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCViewerRichdocument.swift; sourceTree = "<group>"; };
F79018A424092EF4007C9B6D /* ATGMediaBrowser.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ATGMediaBrowser.framework; path = Carthage/Build/iOS/ATGMediaBrowser.framework; sourceTree = "<group>"; };
- F79728D322F96F2D003CACA7 /* NCShareLinkFolderMenuView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCShareLinkFolderMenuView.xib; sourceTree = "<group>"; };
- F79728D522F9A0B0003CACA7 /* NCShareUserFolderMenuView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCShareUserFolderMenuView.xib; sourceTree = "<group>"; };
F79918A021997F9000C2E308 /* UICKeyChainStore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UICKeyChainStore.framework; path = Carthage/Build/iOS/UICKeyChainStore.framework; sourceTree = "<group>"; };
F79918A72199840500C2E308 /* Sheeeeeeeeet.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sheeeeeeeeet.framework; path = Carthage/Build/iOS/Sheeeeeeeeet.framework; sourceTree = "<group>"; };
F79A65C22191D90F00FF6DCC /* NCSelect.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCSelect.storyboard; sourceTree = "<group>"; };
@@ -875,13 +917,13 @@
F7DBC37B23325E01001A85BA /* NCAppConfigView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCAppConfigView.swift; sourceTree = "<group>"; };
F7DBD82B23E46A4700ECB7C6 /* MarkdownKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MarkdownKit.framework; path = Carthage/Build/iOS/MarkdownKit.framework; sourceTree = "<group>"; };
F7DE9AB01F482FA5008DFE10 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = "<group>"; };
- F7DFAA8922E22EF100FC4527 /* NCShareLinkMenuView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCShareLinkMenuView.xib; sourceTree = "<group>"; };
F7DFB7EF219C5B8000680748 /* NCCreateFormUploadAssets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateFormUploadAssets.swift; sourceTree = "<group>"; };
F7DFB7F3219C5CA800680748 /* NCCreateFormUploadScanDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateFormUploadScanDocument.swift; sourceTree = "<group>"; };
F7E0CDCE265CE8610044854E /* NCUserStatus.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCUserStatus.storyboard; sourceTree = "<group>"; };
F7E45E6D21E75BF200579249 /* ja-JP */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ja-JP"; path = "ja-JP.lproj/Localizable.strings"; sourceTree = "<group>"; };
F7E4D9C322ED929B003675FD /* NCShareCommentsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareCommentsCell.swift; sourceTree = "<group>"; };
F7E856182351D7BE009A3330 /* SwiftyXMLParser.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftyXMLParser.framework; path = Carthage/Build/iOS/SwiftyXMLParser.framework; sourceTree = "<group>"; };
+ F7E98C1527E0D0FC001F9F19 /* NCManageDatabase+Video.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+Video.swift"; sourceTree = "<group>"; };
F7EDE508262DA9D600414FE6 /* NCSelectCommandViewSelect.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCSelectCommandViewSelect.xib; sourceTree = "<group>"; };
F7EDE513262DC2CD00414FE6 /* NCSelectCommandViewSelect+CreateFolder.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "NCSelectCommandViewSelect+CreateFolder.xib"; sourceTree = "<group>"; };
F7EDE51A262DD0C400414FE6 /* NCSelectCommandViewCopyMove.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCSelectCommandViewCopyMove.xib; sourceTree = "<group>"; };
@@ -890,6 +932,18 @@
F7EFC0CC256BF8DD00461AAD /* NCUserStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCUserStatus.swift; sourceTree = "<group>"; };
F7F1E54B2492369A00E42386 /* NCMediaCommandView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCMediaCommandView.xib; sourceTree = "<group>"; };
F7F35B592578FB63003F5589 /* CollaboraOnlineWebViewKeyboardManager.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CollaboraOnlineWebViewKeyboardManager.framework; path = Carthage/Build/iOS/CollaboraOnlineWebViewKeyboardManager.framework; sourceTree = "<group>"; };
+ F7F4F0F327ECDBA4008676F9 /* NCSubtitles.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCSubtitles.swift; sourceTree = "<group>"; };
+ F7F4F0F527ECDBA4008676F9 /* NCSubtitlePlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCSubtitlePlayer.swift; sourceTree = "<group>"; };
+ F7F4F0FD27ECDBDB008676F9 /* Inconsolata-SemiBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inconsolata-SemiBold.ttf"; sourceTree = "<group>"; };
+ F7F4F0FE27ECDBDB008676F9 /* Inconsolata-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inconsolata-Medium.ttf"; sourceTree = "<group>"; };
+ F7F4F0FF27ECDBDB008676F9 /* Inconsolata-Black.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inconsolata-Black.ttf"; sourceTree = "<group>"; };
+ F7F4F10027ECDBDB008676F9 /* Inconsolata-ExtraLight.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inconsolata-ExtraLight.ttf"; sourceTree = "<group>"; };
+ F7F4F10127ECDBDB008676F9 /* Inconsolata-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inconsolata-Bold.ttf"; sourceTree = "<group>"; };
+ F7F4F10227ECDBDB008676F9 /* Inconsolata-ExtraBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inconsolata-ExtraBold.ttf"; sourceTree = "<group>"; };
+ F7F4F10327ECDBDB008676F9 /* Inconsolata-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inconsolata-Light.ttf"; sourceTree = "<group>"; };
+ F7F4F10427ECDBDB008676F9 /* Inconsolata-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inconsolata-Regular.ttf"; sourceTree = "<group>"; };
+ F7F4F10F27ECDC4A008676F9 /* UIDevice+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIDevice+Extensions.swift"; sourceTree = "<group>"; };
+ F7F4F11127ECDC52008676F9 /* UIFont+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIFont+Extension.swift"; sourceTree = "<group>"; };
F7F67BB81A24D27800EE80DA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
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>"; };
@@ -964,6 +1018,7 @@
F758A01227A7F03E0069468B /* JGProgressHUD in Frameworks */,
F76DA96F277B78AE0082465B /* TLPhotoPicker in Frameworks */,
F76DA966277B76F30082465B /* UICKeyChainStore in Frameworks */,
+ F753BA93281FD8020015BFB6 /* EasyTipView in Frameworks */,
F76DA95B277B75A90082465B /* TOPasscodeViewController.xcframework in Frameworks */,
F76DA963277B760E0082465B /* Queuer in Frameworks */,
F75E57BD25BF0EC1002B72C2 /* SVGKit in Frameworks */,
@@ -974,7 +1029,6 @@
F72DA9B425F53E4E00B87DB1 /* SwiftRichString in Frameworks */,
F74E7720277A2EF40013B958 /* XLForm in Frameworks */,
F73ADD1C265546890069EA0D /* SwiftEntryKit in Frameworks */,
- F76DA96C277B78400082465B /* FSCalendar in Frameworks */,
F76DA93F277B75870082465B /* KTVCocoaHTTPServer.xcframework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1005,6 +1059,7 @@
F7581D2325EFDDDF004DC699 /* NCMedia+Menu.swift */,
F7CBC31B24F78E79004D3812 /* NCSortMenu.swift */,
F75D19E225EFE09000D74598 /* NCTrash+Menu.swift */,
+ AF93471127E2341B002537EE /* NCShare+Menu.swift */,
F710D2012405826100A6033D /* NCViewer+Menu.swift */,
);
path = Menu;
@@ -1015,11 +1070,27 @@
children = (
AF8ED2022757822700B8DBC4 /* NCGlobalTests.swift */,
AF36077527BFB019001A243D /* ParallelWorkerTest.swift */,
+ AF70C14C27F3484D00E13DF2 /* SharePermissionTest.swift */,
+ AF3F909928213BEA0048A93E /* UserAgentTests.swift */,
AF8ED1FB2757821000B8DBC4 /* NextcloudTests.swift */,
);
path = NextcloudTests;
sourceTree = "<group>";
};
+ AF93471327E235EB002537EE /* Advanced */ = {
+ isa = PBXGroup;
+ children = (
+ AF93471627E2361E002537EE /* NCShareAdvancePermission.swift */,
+ AFCE353627E4ED7B00FEA6C2 /* NCShareCells.swift */,
+ AF93471827E2361E002537EE /* NCShareAdvancePermissionFooter.swift */,
+ AF93471427E2361E002537EE /* NCShareAdvancePermissionFooter.xib */,
+ AF93474D27E3F211002537EE /* NCShareNewUserAddComment.swift */,
+ AF93471527E2361E002537EE /* NCShareAdvancePermissionHeader.swift */,
+ AF93471727E2361E002537EE /* NCShareAdvancePermissionHeader.xib */,
+ );
+ path = Advanced;
+ sourceTree = "<group>";
+ };
F70211F31BAC56E9003FC03E /* Main */ = {
isa = PBXGroup;
children = (
@@ -1153,24 +1224,20 @@
children = (
F700510022DF63AC003A3356 /* NCShare.storyboard */,
F700510422DF6A89003A3356 /* NCShare.swift */,
+ AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */,
+ AF730AF727834B1400B7520E /* NCShare+NCCellDelegate.swift */,
+ AF93471327E235EB002537EE /* Advanced */,
F723B3DC22FC6D1C00301EFE /* NCShareCommentsCell.xib */,
F7E4D9C322ED929B003675FD /* NCShareCommentsCell.swift */,
F769454522E9F1B0000A798A /* NCShareCommon.swift */,
F73CB3B122E072A000AD728E /* NCShareHeaderView.xib */,
F787704E22E7019900F287A9 /* NCShareLinkCell.xib */,
AF2D7C7B2742556F00ADF566 /* NCShareLinkCell.swift */,
- F79728D322F96F2D003CACA7 /* NCShareLinkFolderMenuView.xib */,
- F769454122E9F0EE000A798A /* NCShareLinkMenuView.swift */,
- F7DFAA8922E22EF100FC4527 /* NCShareLinkMenuView.xib */,
F769454722E9F20D000A798A /* NCShareNetworking.swift */,
F769453F22E9F077000A798A /* NCSharePaging.swift */,
- F77EFC0B26D6751F00806ED6 /* NCShareQuickStatusMenu.swift */,
+ F774264822EB4D0000B23912 /* NCSearchUserDropDownCell.xib */,
F769453B22E9CFFF000A798A /* NCShareUserCell.xib */,
AF2D7C7D2742559100ADF566 /* NCShareUserCell.swift */,
- F774264822EB4D0000B23912 /* NCShareUserDropDownCell.xib */,
- F79728D522F9A0B0003CACA7 /* NCShareUserFolderMenuView.xib */,
- F769453D22E9E97D000A798A /* NCShareUserMenuView.xib */,
- F769454322E9F142000A798A /* NCShareUserMenuView.swift */,
);
path = Share;
sourceTree = "<group>";
@@ -1377,7 +1444,9 @@
F79EDA9E26B004980007D134 /* NCPlayer */ = {
isa = PBXGroup;
children = (
+ F7F4F0F227ECDBA4008676F9 /* NCSubtitle */,
F79EDAA126B004980007D134 /* NCPlayer.swift */,
+ F732D23227CF8AED000B0F1B /* NCPlayerToolBar.xib */,
F79EDA9F26B004980007D134 /* NCPlayerToolBar.swift */,
F716B75E26F09DF600D37EFC /* NCKTVHTTPCache.swift */,
);
@@ -1392,11 +1461,16 @@
F78071071EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.h */,
F78071081EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m */,
F7A0D1342591FBC5008F8A13 /* String+Extensions.swift */,
+ AFD3323F276A02C000F5AE02 /* UIApplication+Orientation.swift */,
+ AFCE353227E4ED1900FEA6C2 /* UIToolbar+Extension.swift */,
+ AF1A9B6327D0CA1E00F17A9E /* UIAlertController+Extension.swift */,
+ AFCE353427E4ED5900FEA6C2 /* DateFormatter+Extension.swift */,
+ AF7E504D27A2D8FF00B5E4AF /* UIBarButton+Extension.swift */,
F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */,
F79B645F26CA661600838ACA /* UIControl+Extensions.swift */,
- AF7E504D27A2D8FF00B5E4AF /* UIBarButton+Extension.swift */,
+ F7F4F10F27ECDC4A008676F9 /* UIDevice+Extensions.swift */,
+ F7F4F11127ECDC52008676F9 /* UIFont+Extension.swift */,
F713FEFE2472764000214AF6 /* UIImage+animatedGIF.h */,
- AFD3323F276A02C000F5AE02 /* UIApplication+Orientation.swift */,
F713FEFF2472764100214AF6 /* UIImage+animatedGIF.m */,
F7B7504A2397D38E004E13EC /* UIImage+Extensions.swift */,
);
@@ -1416,7 +1490,9 @@
isa = PBXGroup;
children = (
F7C9555221F0C4CA0024296E /* NCActivity.storyboard */,
+ AF56C1DB2784856200D8BAE2 /* NCActivityCommentView.xib */,
F7C9555421F0C5470024296E /* NCActivity.swift */,
+ AFA2AC8427849604008E1EA7 /* NCActivityCommentView.swift */,
D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */,
);
path = Activity;
@@ -1473,7 +1549,8 @@
F7BAADB51ED5A87C00B7EAD4 /* NCManageDatabase.swift */,
AF4BF61D27562B3F0081CEEF /* NCManageDatabase+Activity.swift */,
AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */,
- AF4BF61827562A4B0081CEEF /* NCManageDatabse+Metadata.swift */,
+ AF4BF61827562A4B0081CEEF /* NCManageDatabase+Metadata.swift */,
+ F7E98C1527E0D0FC001F9F19 /* NCManageDatabase+Video.swift */,
F73D5E46246DE09200DF6467 /* NCElementsJSON.swift */,
);
path = Data;
@@ -1503,6 +1580,7 @@
F70968A324212C4E00ED60E5 /* NCLivePhoto.swift */,
F707C26421A2DC5200F6181E /* NCStoreReview.swift */,
F70BFC7320E0FA7C00C67599 /* NCUtility.swift */,
+ AF93474B27E34120002537EE /* NCUtility+Image.swift */,
AF817EF0274BC781009ED85B /* NCUserBaseUrl.swift */,
F74AF3A3247FB6AE00AC767B /* NCUtilityFileSystem.swift */,
AF36077027BFA4E8001A243D /* ParallelWorker.swift */,
@@ -1642,6 +1720,38 @@
path = UserStatus;
sourceTree = "<group>";
};
+ F7F4F0F227ECDBA4008676F9 /* NCSubtitle */ = {
+ isa = PBXGroup;
+ children = (
+ F7F4F0F327ECDBA4008676F9 /* NCSubtitles.swift */,
+ F7F4F0F527ECDBA4008676F9 /* NCSubtitlePlayer.swift */,
+ );
+ path = NCSubtitle;
+ sourceTree = "<group>";
+ };
+ F7F4F0FB27ECDBDA008676F9 /* Font */ = {
+ isa = PBXGroup;
+ children = (
+ F7F4F0FC27ECDBDB008676F9 /* Inconsolata */,
+ );
+ path = Font;
+ sourceTree = "<group>";
+ };
+ F7F4F0FC27ECDBDB008676F9 /* Inconsolata */ = {
+ isa = PBXGroup;
+ children = (
+ F7F4F0FD27ECDBDB008676F9 /* Inconsolata-SemiBold.ttf */,
+ F7F4F0FE27ECDBDB008676F9 /* Inconsolata-Medium.ttf */,
+ F7F4F0FF27ECDBDB008676F9 /* Inconsolata-Black.ttf */,
+ F7F4F10027ECDBDB008676F9 /* Inconsolata-ExtraLight.ttf */,
+ F7F4F10127ECDBDB008676F9 /* Inconsolata-Bold.ttf */,
+ F7F4F10227ECDBDB008676F9 /* Inconsolata-ExtraBold.ttf */,
+ F7F4F10327ECDBDB008676F9 /* Inconsolata-Light.ttf */,
+ F7F4F10427ECDBDB008676F9 /* Inconsolata-Regular.ttf */,
+ );
+ path = Inconsolata;
+ sourceTree = "<group>";
+ };
F7F67B9F1A24D27800EE80DA = {
isa = PBXGroup;
children = (
@@ -1673,6 +1783,7 @@
F7BAAD951ED5A63D00B7EAD4 /* Data */,
F73FAEE224D2CA830090692E /* Diagnostics */,
F723986F253D867900257F49 /* EmptyView */,
+ F7A0D14E259229FA008F8A13 /* Extensions */,
F7A3214D1E9E2A070069AD1B /* Favorites */,
F7725A5D251F33BB00D125E0 /* Files */,
F7A80BC7252624C100C7CD01 /* FileViewInFolder */,
@@ -1696,7 +1807,6 @@
F7E9C41320F4CA870040CF18 /* Transfers */,
F78F74322163753B00C2ADAD /* Trash */,
F7EFC0CB256BF89300461AAD /* UserStatus */,
- F7A0D14E259229FA008F8A13 /* Extensions */,
F7BFFA991A24D7BB0044ED85 /* Utility */,
F79630EC215526B60015EEA5 /* Viewer */,
);
@@ -1706,6 +1816,7 @@
F7F67BAB1A24D27800EE80DA /* Supporting Files */ = {
isa = PBXGroup;
children = (
+ F7F4F0FB27ECDBDA008676F9 /* Font */,
F72B60941A24F04E004EF66F /* Localizations */,
F7D154271E2392A300202FD9 /* Nextcloud-Bridging-Header.h */,
);
@@ -1970,13 +2081,13 @@
F76DA962277B760E0082465B /* Queuer */,
F76DA965277B76F30082465B /* UICKeyChainStore */,
F76DA968277B77EA0082465B /* DropDown */,
- F76DA96B277B78400082465B /* FSCalendar */,
F76DA96E277B78AE0082465B /* TLPhotoPicker */,
F710FC79277B7D0000AA9FBF /* Realm */,
F710FC7B277B7D0000AA9FBF /* RealmSwift */,
F7233B3927835FA400F40A43 /* ChromaColorPicker */,
F7BB7E4627A18C56009B9F29 /* Parchment */,
F758A01127A7F03E0069468B /* JGProgressHUD */,
+ F753BA92281FD8020015BFB6 /* EasyTipView */,
);
productName = "Crypto Cloud";
productReference = F7CE8AFA1DC1F8D8009CAE48 /* Nextcloud.app */;
@@ -1989,7 +2100,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1310;
- LastUpgradeCheck = 1320;
+ LastUpgradeCheck = 1330;
ORGANIZATIONNAME = "Marino Faggiana";
TargetAttributes = {
2C33C47E23E2C475005F963B = {
@@ -2098,12 +2209,12 @@
F76DA961277B760E0082465B /* XCRemoteSwiftPackageReference "Queuer" */,
F76DA964277B76F10082465B /* XCRemoteSwiftPackageReference "UICKeyChainStore" */,
F76DA967277B77E90082465B /* XCRemoteSwiftPackageReference "DropDown" */,
- F76DA96A277B78400082465B /* XCRemoteSwiftPackageReference "FSCalendar" */,
F76DA96D277B78AE0082465B /* XCRemoteSwiftPackageReference "TLPhotoPicker" */,
F710FC78277B7CFF00AA9FBF /* XCRemoteSwiftPackageReference "realm-swift" */,
F7233B3827835FA300F40A43 /* XCRemoteSwiftPackageReference "ChromaColorPicker" */,
F7BB7E4527A18C56009B9F29 /* XCRemoteSwiftPackageReference "Parchment" */,
F72CD01027A7E92400E59476 /* XCRemoteSwiftPackageReference "JGProgressHUD" */,
+ F753BA91281FD8010015BFB6 /* XCRemoteSwiftPackageReference "EasyTipView" */,
);
productRefGroup = F7F67B9F1A24D27800EE80DA;
projectDirPath = "";
@@ -2167,13 +2278,15 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- F79728D422F96F2E003CACA7 /* NCShareLinkFolderMenuView.xib in Resources */,
F7362A1F220C853A005101B5 /* LaunchScreen.storyboard in Resources */,
F77444F622281649000D5EB0 /* NCGridMediaCell.xib in Resources */,
F78ACD4421903CF20088454D /* NCListCell.xib in Resources */,
+ F7F4F10727ECDBDB008676F9 /* Inconsolata-Black.ttf in Resources */,
F78ACD4621903D010088454D /* NCGridCell.xib in Resources */,
+ F7F4F10827ECDBDB008676F9 /* Inconsolata-ExtraLight.ttf in Resources */,
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 */,
@@ -2188,48 +2301,54 @@
F7226EDC1EE4089300EBECB1 /* Main.storyboard in Resources */,
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 */,
F7D0F33E264144FC0097D4A3 /* Background.xcassets in Resources */,
F7F1E54C2492369A00E42386 /* NCMediaCommandView.xib in Resources */,
F710E8111EF95C9C00DC2427 /* ImagesIntro.xcassets in Resources */,
F76032A0252F0F8E0015A421 /* NCTransferCell.xib in Resources */,
+ F7F4F10527ECDBDB008676F9 /* Inconsolata-SemiBold.ttf in Resources */,
F74C0437253F1CDC009762AB /* NCShares.storyboard in Resources */,
+ F7F4F10C27ECDBDB008676F9 /* Inconsolata-Regular.ttf in Resources */,
F7B8B83025681C3400967775 /* GoogleService-Info.plist in Resources */,
F7381EE5218218C9000B1560 /* NCOffline.storyboard in Resources */,
F7E0CDCF265CE8610044854E /* NCUserStatus.storyboard in Resources */,
F76D3CF32428B94E005DFA87 /* NCViewerPDFSearchCell.xib in Resources */,
- F769453E22E9E97E000A798A /* NCShareUserMenuView.xib in Resources */,
F7CA212E25F1333300826ABB /* NCAccountRequest.storyboard in Resources */,
F749C10E23C4A5340027D966 /* NCIntroCollectionViewCell.xib in Resources */,
F717402D24F699A5000C87D5 /* NCFavorite.storyboard in Resources */,
F723B3DD22FC6D1D00301EFE /* NCShareCommentsCell.xib in Resources */,
F78ACD4B21903F850088454D /* NCTrashListCell.xib in Resources */,
+ AF93471927E2361E002537EE /* NCShareAdvancePermissionFooter.xib in Resources */,
F7725A61251F33BB00D125E0 /* NCFiles.storyboard in Resources */,
F700510122DF63AC003A3356 /* NCShare.storyboard in Resources */,
F787704F22E7019900F287A9 /* NCShareLinkCell.xib in Resources */,
F70753F72542A9C000972D44 /* NCViewerMediaPage.storyboard in Resources */,
F70A58C024D0545100DED00D /* NCCapabilitiesViewController.storyboard in Resources */,
+ F7F4F10627ECDBDB008676F9 /* Inconsolata-Medium.ttf in Resources */,
F749C10D23C4A5340027D966 /* NCIntro.storyboard in Resources */,
F7239877253D86D300257F49 /* NCEmptyView.xib in Resources */,
F747BA1F22354D2000971601 /* NCCreateFormUploadVoiceNote.storyboard in Resources */,
F7651A8A23A2A3F2001403D2 /* NCCreateFormUploadDocuments.storyboard in Resources */,
+ F7F4F10A27ECDBDB008676F9 /* Inconsolata-ExtraBold.ttf in Resources */,
F704B5E72430C06700632F5F /* NCCreateFormUploadConflictCell.xib in Resources */,
- F79728D622F9A0B1003CACA7 /* NCShareUserFolderMenuView.xib in Resources */,
- F7DFAA8A22E22EF100FC4527 /* NCShareLinkMenuView.xib in Resources */,
F7C9555321F0C4CA0024296E /* NCActivity.storyboard in Resources */,
F7BC287E26663F6C004D46C5 /* NCViewCertificateDetails.storyboard in Resources */,
F78ACD54219047D40088454D /* NCSectionFooter.xib in Resources */,
F704B5E32430AA6F00632F5F /* NCCreateFormUploadConflict.storyboard in Resources */,
F77B0F611D118A16002130FE /* Acknowledgements.rtf in Resources */,
F7EDE509262DA9D600414FE6 /* NCSelectCommandViewSelect.xib in Resources */,
+ F732D23327CF8AED000B0F1B /* NCPlayerToolBar.xib in Resources */,
F73D11FA253C5F4800DF9BEC /* NCViewerNextcloudText.storyboard in Resources */,
F7EDE51B262DD0C400414FE6 /* NCSelectCommandViewCopyMove.xib in Resources */,
F73B422B2476764F00A30FD3 /* NCNotification.storyboard in Resources */,
F7D1612023CF19E30039EBBF /* NCViewerRichWorkspace.storyboard in Resources */,
F77B0F631D118A16002130FE /* Localizable.strings in Resources */,
F7632FC1218353AA00721B71 /* NCTrashSectionFooter.xib in Resources */,
- F774264A22EB4D0000B23912 /* NCShareUserDropDownCell.xib in Resources */,
+ F774264A22EB4D0000B23912 /* NCSearchUserDropDownCell.xib in Resources */,
F7CB689A2541676B0050EC94 /* NCMore.storyboard in Resources */,
F70B866D2642A21300ED5349 /* NCBackgroundImageColor.storyboard in Resources */,
F77B0F7D1D118A16002130FE /* Images.xcassets in Resources */,
@@ -2297,13 +2416,14 @@
F702F2D225EE5B5C008F8E80 /* NCGlobal.swift in Sources */,
F7707689263A896A00A1BA94 /* UIImage+Extensions.swift in Sources */,
2C1D5D7523E2DE3300334ABB /* NCDatabase.swift in Sources */,
+ F7E98C1927E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */,
2C1D5D7623E2DE3300334ABB /* NCManageDatabase.swift in Sources */,
2C33C48223E2C475005F963B /* NotificationService.swift in Sources */,
AF4BF617275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */,
D575039F27146F93008DC9DC /* String+Extensions.swift in Sources */,
F73D5E4A246DE09200DF6467 /* NCElementsJSON.swift in Sources */,
F79B646326CA661600838ACA /* UIControl+Extensions.swift in Sources */,
- AF4BF61C27562A4B0081CEEF /* NCManageDatabse+Metadata.swift in Sources */,
+ AF4BF61C27562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */,
AF817EF4274BC781009ED85B /* NCUserBaseUrl.swift in Sources */,
F798F0EC2588060A000DAFFD /* UIColor+Extensions.swift in Sources */,
2CB7D1CA23E2EDCB00376EF9 /* NCPushNotificationEncryption.m in Sources */,
@@ -2315,6 +2435,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ AF70C14D27F3484D00E13DF2 /* SharePermissionTest.swift in Sources */,
+ AF3F909A28213BEA0048A93E /* UserAgentTests.swift in Sources */,
AF36077627BFB019001A243D /* ParallelWorkerTest.swift in Sources */,
AF8ED1FC2757821000B8DBC4 /* NextcloudTests.swift in Sources */,
AF8ED2032757822700B8DBC4 /* NCGlobalTests.swift in Sources */,
@@ -2336,15 +2458,17 @@
F70460532499095400BB98A7 /* NotificationCenter+MainThread.swift in Sources */,
F70BFC7520E0FA7D00C67599 /* NCUtility.swift in Sources */,
AF22B20C277C6F4D00DAB0CC /* NCShareCell.swift in Sources */,
+ F7E98C1727E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */,
F79B646126CA661600838ACA /* UIControl+Extensions.swift in Sources */,
F7EDE4CC262D7B6F00414FE6 /* NCEmptyDataSet.swift in Sources */,
- AF4BF61A27562A4B0081CEEF /* NCManageDatabse+Metadata.swift in Sources */,
+ AF4BF61A27562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */,
AF4BF615275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */,
F798F0E225880608000DAFFD /* UIColor+Extensions.swift in Sources */,
AF3FDCC32796F3FB00710F60 /* NCTrashListCell.swift in Sources */,
AF817EF2274BC781009ED85B /* NCUserBaseUrl.swift in Sources */,
F78295311F962EFA00A572F5 /* NCEndToEndEncryption.m in Sources */,
F74AF3A5247FB6AE00AC767B /* NCUtilityFileSystem.swift in Sources */,
+ AF1A9B6527D0CC0500F17A9E /* UIAlertController+Extension.swift in Sources */,
AF22B206277B4E4C00DAB0CC /* NCCreateFormUploadConflict.swift in Sources */,
F7BD71E62636EAFC00643C34 /* NCNetworkingE2EE.swift in Sources */,
F7F878AF1FB9E3B900599E4F /* NCEndToEndMetadata.swift in Sources */,
@@ -2387,8 +2511,9 @@
AF4BF616275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */,
F7434B3620E23FE000417916 /* NCManageDatabase.swift in Sources */,
F798F0E725880609000DAFFD /* UIColor+Extensions.swift in Sources */,
- AF4BF61B27562A4B0081CEEF /* NCManageDatabse+Metadata.swift in Sources */,
+ AF4BF61B27562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */,
F70460542499095400BB98A7 /* NotificationCenter+MainThread.swift in Sources */,
+ F7E98C1827E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */,
F785EEA42461A4A600B3F945 /* NCUtility.swift in Sources */,
F79B646226CA661600838ACA /* UIControl+Extensions.swift in Sources */,
AF817EF3274BC781009ED85B /* NCUserBaseUrl.swift in Sources */,
@@ -2417,6 +2542,7 @@
370D26AF248A3D7A00121797 /* NCCellProtocol.swift in Sources */,
F77B0DF51D118A16002130FE /* CCUtility.m in Sources */,
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 */,
@@ -2429,7 +2555,9 @@
F73F537F1E929C8500F8678D /* NCMore.swift in Sources */,
F702F2CF25EE5B5C008F8E80 /* NCGlobal.swift in Sources */,
F72CD63A25C19EBF00F46F9A /* NCAutoUpload.swift in Sources */,
+ AF93471D27E2361E002537EE /* NCShareAdvancePermissionFooter.swift in Sources */,
F7DFB7F0219C5B8000680748 /* NCCreateFormUploadAssets.swift in Sources */,
+ AF1A9B6427D0CA1E00F17A9E /* UIAlertController+Extension.swift in Sources */,
F73B422C2476764F00A30FD3 /* NCNotification.swift in Sources */,
371B5A2E23D0B04500FAFAE9 /* NCMenu.swift in Sources */,
F79EDAA326B004980007D134 /* NCPlayerToolBar.swift in Sources */,
@@ -2441,9 +2569,11 @@
F7A80BCB252624C100C7CD01 /* NCFileViewInFolder.swift in Sources */,
F78A18B823CDE2B300F681F3 /* NCViewerRichWorkspace.swift in Sources */,
F77910AB25DD53C700CEDB9E /* NCSettingsBundleHelper.swift in Sources */,
- AF4BF61927562A4B0081CEEF /* NCManageDatabse+Metadata.swift in Sources */,
+ AF4BF61927562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */,
F78A18B623CDD07D00F681F3 /* NCViewerRichWorkspaceWebView.swift in Sources */,
+ AFA2AC8527849604008E1EA7 /* NCActivityCommentView.swift in Sources */,
F716B75F26F09DF600D37EFC /* NCKTVHTTPCache.swift in Sources */,
+ AFCE353727E4ED7B00FEA6C2 /* NCShareCells.swift in Sources */,
AF36077127BFA4E8001A243D /* ParallelWorker.swift in Sources */,
F75A9EE623796C6F0044CFCE /* NCNetworking.swift in Sources */,
F758B460212C56A400515F55 /* NCScan.swift in Sources */,
@@ -2455,9 +2585,9 @@
F72928A0253B0937009CA4FD /* NCMainNavigationController.swift in Sources */,
F704B5E92430C0B800632F5F /* NCCreateFormUploadConflictCell.swift in Sources */,
F72D404923D2082500A97FD0 /* NCViewerNextcloudText.swift in Sources */,
+ AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */,
F700510522DF6A89003A3356 /* NCShare.swift in Sources */,
F72D1007210B6882009C96B7 /* NCPushNotificationEncryption.m in Sources */,
- F769454222E9F0EE000A798A /* NCShareLinkMenuView.swift in Sources */,
F785EE9D246196DF00B3F945 /* NCNetworkingE2EE.swift in Sources */,
F76673ED22C901F6007ED366 /* FileProviderDomain.swift in Sources */,
F7A321AD1E9E6AD50069AD1B /* CCAdvanced.m in Sources */,
@@ -2472,16 +2602,22 @@
F7A0D1352591FBC5008F8A13 /* String+Extensions.swift in Sources */,
F77B0E5F1D118A16002130FE /* NCSettings.m in Sources */,
F7F9D1BB25397CE000D9BFF5 /* NCViewer.swift in Sources */,
+ AF730AF827834B1400B7520E /* NCShare+NCCellDelegate.swift in Sources */,
F70460522499061800BB98A7 /* NotificationCenter+MainThread.swift in Sources */,
F78F74362163781100C2ADAD /* NCTrash.swift in Sources */,
AF817EF1274BC781009ED85B /* NCUserBaseUrl.swift in Sources */,
AF2D7C7C2742556F00ADF566 /* NCShareLinkCell.swift in Sources */,
+ 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 */,
F702F2F725EE5CED008F8E80 /* NCLogin.swift in Sources */,
+ F7E98C1627E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */,
+ F7F4F11227ECDC52008676F9 /* UIFont+Extension.swift in Sources */,
+ AF93471A27E2361E002537EE /* NCShareAdvancePermissionHeader.swift in Sources */,
F7F878AE1FB9E3B900599E4F /* NCEndToEndMetadata.swift in Sources */,
F7DBC37C23325E02001A85BA /* NCAppConfigView.swift in Sources */,
3781B9B023DB2B7E006B4B1D /* AppDelegate+Menu.swift in Sources */,
@@ -2494,6 +2630,7 @@
F7C1EEA525053A9C00866ACC /* NCDataSource.swift in Sources */,
F713FF002472764100214AF6 /* UIImage+animatedGIF.m in Sources */,
F749C10B23C4A5340027D966 /* NCIntroCollectionViewCell.swift in Sources */,
+ AFCE353527E4ED5900FEA6C2 /* DateFormatter+Extension.swift in Sources */,
F718C24E254D507B00C5C256 /* NCViewerMediaDetailView.swift in Sources */,
F7381EE1218218C9000B1560 /* NCOffline.swift in Sources */,
F78071091EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m in Sources */,
@@ -2501,12 +2638,13 @@
F7CA212D25F1333300826ABB /* NCAccountRequest.swift in Sources */,
F765F73125237E3F00391DBE /* NCRecent.swift in Sources */,
F76B3CCE1EAE01BD00921AC9 /* NCBrand.swift in Sources */,
- F769454422E9F142000A798A /* NCShareUserMenuView.swift in Sources */,
F7581D2425EFDDDF004DC699 /* NCMedia+Menu.swift in Sources */,
F738D4902756740100CD1D38 /* NCLoginNavigationController.swift in Sources */,
F77B0E981D118A16002130FE /* CCManageAccount.m in Sources */,
- F77EFC0C26D6751F00806ED6 /* NCShareQuickStatusMenu.swift in Sources */,
+ AF93474C27E34120002537EE /* NCUtility+Image.swift in Sources */,
F702F30125EE5D2C008F8E80 /* NYMnemonic.m in Sources */,
+ AF93474E27E3F212002537EE /* NCShareNewUserAddComment.swift in Sources */,
+ AF93471227E2341B002537EE /* NCShare+Menu.swift in Sources */,
F7EFA47825ADBA500083159A /* NCViewerProviderContextMenu.swift in Sources */,
F755BD9B20594AC7008C5FBB /* NCService.swift in Sources */,
AFD33240276A02C100F5AE02 /* UIApplication+Orientation.swift in Sources */,
@@ -2522,6 +2660,7 @@
F79A65C62191D95E00FF6DCC /* NCSelect.swift in Sources */,
F75D19E325EFE09000D74598 /* NCTrash+Menu.swift in Sources */,
F70CAE3A1F8CF31A008125FD /* NCEndToEndEncryption.m in Sources */,
+ AF93471B27E2361E002537EE /* NCShareAdvancePermission.swift in Sources */,
F70753EB2542A99800972D44 /* NCViewerMediaPage.swift in Sources */,
F74C0436253F1CDC009762AB /* NCShares.swift in Sources */,
F7AE00F5230D5F9E007ACF8A /* NCLoginWeb.swift in Sources */,
@@ -2543,6 +2682,7 @@
F7C7B489245EBA4100D93E60 /* NCViewerQuickLook.swift in Sources */,
F758B45E212C569D00515F55 /* NCScanCell.swift in Sources */,
F7581D1A25EFDA61004DC699 /* NCLoginWeb+Menu.swift in Sources */,
+ F7F4F11027ECDC4A008676F9 /* UIDevice+Extensions.swift in Sources */,
F77B0ED11D118A16002130FE /* Acknowledgements.m in Sources */,
F70D8D8124A4A9BF000A5756 /* NCNetworkingProcessUpload.swift in Sources */,
F7D96FCC246ED7E200536D73 /* NCNetworkingCheckRemoteUser.swift in Sources */,
@@ -2843,6 +2983,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
@@ -2865,9 +3006,9 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 0;
+ CURRENT_PROJECT_VERSION = 18;
DEVELOPMENT_TEAM = 6JLRKY9ZV7;
- ENABLE_BITCODE = NO;
+ ENABLE_BITCODE = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_NO_COMMON_BLOCKS = YES;
@@ -2888,11 +3029,12 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = 4.3.1;
+ MARKETING_VERSION = 4.4.0;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "";
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) NC";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
@@ -2902,6 +3044,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
@@ -2924,9 +3067,9 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 0;
+ CURRENT_PROJECT_VERSION = 18;
DEVELOPMENT_TEAM = 6JLRKY9ZV7;
- ENABLE_BITCODE = NO;
+ ENABLE_BITCODE = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
@@ -2945,11 +3088,12 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = 4.3.1;
+ MARKETING_VERSION = 4.4.0;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "";
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG NC";
+ SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@@ -3072,12 +3216,20 @@
minimumVersion = 4.0.0;
};
};
+ F753BA91281FD8010015BFB6 /* XCRemoteSwiftPackageReference "EasyTipView" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/marinofaggiana/EasyTipView";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 2.0.0;
+ };
+ };
F75E57A725BF0D61002B72C2 /* XCRemoteSwiftPackageReference "SVGKit" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/SVGKit/SVGKit.git";
requirement = {
- branch = 3.x;
- kind = branch;
+ kind = upToNextMinorVersion;
+ minimumVersion = 3.0.0;
};
};
F75EAED626D2552E00F4320E /* XCRemoteSwiftPackageReference "MarqueeLabel" */ = {
@@ -3112,14 +3264,6 @@
kind = branch;
};
};
- F76DA96A277B78400082465B /* XCRemoteSwiftPackageReference "FSCalendar" */ = {
- isa = XCRemoteSwiftPackageReference;
- repositoryURL = "https://github.com/WenchaoD/FSCalendar";
- requirement = {
- kind = upToNextMajorVersion;
- minimumVersion = 2.0.0;
- };
- };
F76DA96D277B78AE0082465B /* XCRemoteSwiftPackageReference "TLPhotoPicker" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/tilltue/TLPhotoPicker";
@@ -3141,7 +3285,7 @@
repositoryURL = "https://github.com/nextcloud/ios-communication-library/";
requirement = {
kind = exactVersion;
- version = 0.99.5;
+ version = 0.99.6;
};
};
F788ECC5263AAAF900ADC67F /* XCRemoteSwiftPackageReference "MarkdownKit" */ = {
@@ -3256,6 +3400,11 @@
package = F74E771E277A2EF40013B958 /* XCRemoteSwiftPackageReference "XLForm" */;
productName = XLForm;
};
+ F753BA92281FD8020015BFB6 /* EasyTipView */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = F753BA91281FD8010015BFB6 /* XCRemoteSwiftPackageReference "EasyTipView" */;
+ productName = EasyTipView;
+ };
F758A01127A7F03E0069468B /* JGProgressHUD */ = {
isa = XCSwiftPackageProductDependency;
package = F72CD01027A7E92400E59476 /* XCRemoteSwiftPackageReference "JGProgressHUD" */;
@@ -3301,11 +3450,6 @@
package = F76DA967277B77E90082465B /* XCRemoteSwiftPackageReference "DropDown" */;
productName = DropDown;
};
- F76DA96B277B78400082465B /* FSCalendar */ = {
- isa = XCSwiftPackageProductDependency;
- package = F76DA96A277B78400082465B /* XCRemoteSwiftPackageReference "FSCalendar" */;
- productName = FSCalendar;
- };
F76DA96E277B78AE0082465B /* TLPhotoPicker */ = {
isa = XCSwiftPackageProductDependency;
package = F76DA96D277B78AE0082465B /* XCRemoteSwiftPackageReference "TLPhotoPicker" */;
diff --git a/Nextcloud.xcodeproj/xcshareddata/xcschemes/File Provider Extension.xcscheme b/Nextcloud.xcodeproj/xcshareddata/xcschemes/File Provider Extension.xcscheme
index 9f6feaf4e..32b1efb9e 100755
--- a/Nextcloud.xcodeproj/xcshareddata/xcschemes/File Provider Extension.xcscheme
+++ b/Nextcloud.xcodeproj/xcshareddata/xcschemes/File Provider Extension.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "1320"
+ LastUpgradeVersion = "1330"
wasCreatedForAppExtension = "YES"
version = "2.0">
<BuildAction
diff --git a/Nextcloud.xcodeproj/xcshareddata/xcschemes/Nextcloud.xcscheme b/Nextcloud.xcodeproj/xcshareddata/xcschemes/Nextcloud.xcscheme
index 3646e7016..5e0b54e5b 100755
--- a/Nextcloud.xcodeproj/xcshareddata/xcschemes/Nextcloud.xcscheme
+++ b/Nextcloud.xcodeproj/xcshareddata/xcschemes/Nextcloud.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "1320"
+ LastUpgradeVersion = "1330"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
diff --git a/Nextcloud.xcodeproj/xcshareddata/xcschemes/Share.xcscheme b/Nextcloud.xcodeproj/xcshareddata/xcschemes/Share.xcscheme
index 80e2013e6..13c5e2fe1 100755
--- a/Nextcloud.xcodeproj/xcshareddata/xcschemes/Share.xcscheme
+++ b/Nextcloud.xcodeproj/xcshareddata/xcschemes/Share.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "1320"
+ LastUpgradeVersion = "1330"
wasCreatedForAppExtension = "YES"
version = "2.0">
<BuildAction
diff --git a/NextcloudTests/SharePermissionTest.swift b/NextcloudTests/SharePermissionTest.swift
new file mode 100644
index 000000000..919941eb4
--- /dev/null
+++ b/NextcloudTests/SharePermissionTest.swift
@@ -0,0 +1,136 @@
+//
+// SharePermissionTest.swift
+// Nextcloud
+//
+// Created by Henrik Storch on 29.03.22.
+// Copyright © 2021 Henrik Storch. All rights reserved.
+//
+// Author Henrik Storch <henrik.storch@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/>.
+//
+
+@testable import Nextcloud
+import XCTest
+import NCCommunication
+
+class SharePermissionTest: XCTestCase {
+ override func setUp() {
+ let json =
+ """
+ {"ocs":{"data":{"capabilities":{"files_sharing":{"default_permissions":31}}}}}
+ """.data(using: .utf8)!
+ NCManageDatabase.shared.addCapabilitiesJSon(json, account: "")
+ }
+
+ func testShareCellPermissionCell() throws {
+ let share = NCTableShareOptions(sharee: NCCommunicationSharee(), metadata: tableMetadata(), password: nil)
+ let shareConfig = NCShareConfig(parentMetadata: tableMetadata(), share: share)
+
+ for row in 0..<shareConfig.permissions.count {
+ guard let cell = shareConfig.config(for: IndexPath(row: row, section: 0)) as? NCToggleCellConfig else {
+ XCTFail("Invalid share permission cell")
+ continue
+ }
+ XCTAssertFalse(cell.isOn(for: share))
+ }
+
+ let meta = tableMetadata()
+ meta.sharePermissionsCollaborationServices = 31
+ let fullShare = NCTableShareOptions(sharee: NCCommunicationSharee(), metadata: meta, password: nil)
+ let shareFullConfig = NCShareConfig(parentMetadata: meta, share: fullShare)
+
+ for row in 0..<shareFullConfig.permissions.count {
+ guard let cell = shareConfig.config(for: IndexPath(row: row, section: 0)) as? NCToggleCellConfig else {
+ XCTFail("Invalid share permission cell")
+ continue
+ }
+ XCTAssertTrue(cell.isOn(for: fullShare))
+ }
+ }
+
+ func testSharePermission() throws {
+ XCTAssertTrue(NCLinkPermission.allowEdit.hasResharePermission(for: 15))
+ XCTAssertTrue(NCLinkPermission.allowEdit.hasResharePermission(for: 11))
+ XCTAssertTrue(NCLinkPermission.allowEdit.hasResharePermission(for: 7))
+ XCTAssertFalse(NCLinkPermission.allowEdit.hasResharePermission(for: 13))
+ XCTAssertFalse(NCLinkPermission.allowEdit.hasResharePermission(for: 1))
+
+ XCTAssertTrue(NCLinkPermission.viewOnly.hasResharePermission(for: 25))
+ XCTAssertTrue(NCLinkPermission.viewOnly.hasResharePermission(for: 17))
+ XCTAssertFalse(NCLinkPermission.viewOnly.hasResharePermission(for: 12))
+ XCTAssertFalse(NCLinkPermission.viewOnly.hasResharePermission(for: 2))
+
+ XCTAssertTrue(NCLinkPermission.fileDrop.hasResharePermission(for: 4))
+ XCTAssertFalse(NCLinkPermission.fileDrop.hasResharePermission(for: 27))
+
+ XCTAssertTrue(NCUserPermission.create.hasResharePermission(for: 4))
+ XCTAssertFalse(NCUserPermission.create.hasResharePermission(for: 27))
+
+ XCTAssertTrue(NCUserPermission.edit.hasResharePermission(for: 2))
+ XCTAssertFalse(NCUserPermission.edit.hasResharePermission(for: 29))
+
+ XCTAssertTrue(NCUserPermission.reshare.hasResharePermission(for: 16))
+ XCTAssertFalse(NCUserPermission.reshare.hasResharePermission(for: 15))
+ }
+
+ func testFileShare() throws {
+ let meta = tableMetadata()
+ meta.directory = false
+ let share = NCTableShareOptions.shareLink(metadata: meta, password: nil)
+ let fileConfig = NCShareConfig(parentMetadata: meta, share: share)
+ XCTAssertEqual(fileConfig.advanced, NCShareDetails.forLink)
+ XCTAssertEqual(fileConfig.permissions as? [NCLinkPermission], NCLinkPermission.forFile)
+
+ meta.directory = true
+ let folderConfig = NCShareConfig(parentMetadata: meta, share: share)
+ XCTAssertEqual(folderConfig.advanced, NCShareDetails.forLink)
+ XCTAssertEqual(folderConfig.permissions as? [NCLinkPermission], NCLinkPermission.forDirectory)
+ }
+
+ func testUserShare() throws {
+ let meta = tableMetadata()
+ meta.directory = false
+ let sharee = NCCommunicationSharee()
+ let share = NCTableShareOptions(sharee: sharee, metadata: meta, password: nil)
+ let fileConfig = NCShareConfig(parentMetadata: meta, share: share)
+ XCTAssertEqual(fileConfig.advanced, NCShareDetails.forUser)
+ XCTAssertEqual(fileConfig.permissions as? [NCUserPermission], NCUserPermission.forFile)
+
+ meta.directory = true
+ let folderConfig = NCShareConfig(parentMetadata: meta, share: share)
+ XCTAssertEqual(folderConfig.advanced, NCShareDetails.forUser)
+ XCTAssertEqual(folderConfig.permissions as? [NCUserPermission], NCUserPermission.forDirectory)
+ }
+
+ func testResharePermission() throws {
+ let meta = tableMetadata()
+ let permissionReadShare = NCGlobal.shared.permissionShareShare + NCGlobal.shared.permissionReadShare
+ meta.sharePermissionsCollaborationServices = permissionReadShare
+ meta.directory = false
+ let share = NCTableShareOptions.shareLink(metadata: meta, password: nil)
+ let fileConfig = NCShareConfig(parentMetadata: meta, share: share)
+ XCTAssertEqual(fileConfig.resharePermission, meta.sharePermissionsCollaborationServices)
+ XCTAssertEqual(fileConfig.advanced, NCShareDetails.forLink)
+ XCTAssertEqual(fileConfig.permissions as? [NCLinkPermission], NCLinkPermission.forFile)
+
+ meta.directory = true
+ let sharee = NCCommunicationSharee()
+ let folderShare = NCTableShareOptions(sharee: sharee, metadata: meta, password: nil)
+ let folderConfig = NCShareConfig(parentMetadata: meta, share: folderShare)
+ XCTAssertEqual(folderConfig.resharePermission, meta.sharePermissionsCollaborationServices)
+ XCTAssertEqual(folderConfig.advanced, NCShareDetails.forUser)
+ XCTAssertEqual(folderConfig.permissions as? [NCUserPermission], NCUserPermission.forDirectory)
+ }
+}
diff --git a/NextcloudTests/UserAgentTests.swift b/NextcloudTests/UserAgentTests.swift
new file mode 100644
index 000000000..f66975c21
--- /dev/null
+++ b/NextcloudTests/UserAgentTests.swift
@@ -0,0 +1,64 @@
+//
+// UserAgentTests.swift
+// Nextcloud
+//
+// Created by Henrik Storch on 03.05.22.
+// Copyright © 2022 Henrik Storch. All rights reserved.
+//
+// Author Henrik Storch <henrik.storch@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/>.
+//
+
+@testable import Nextcloud
+import XCTest
+
+class UserAgentTests: XCTestCase {
+ // https://github.com/nextcloud/server/blob/fc826e98115b510313ddacbf6fef4ce8d041e373/lib/public/IRequest.php#L83
+ let ncServerUARegex = "^Mozilla\\/5\\.0 \\(iOS\\) (ownCloud|Nextcloud)\\-iOS.*$"
+
+ // https://github.com/ProseMirror/prosemirror-view/blob/427d278aaaacde422ed1f2b8c84bb53337162775/src/browser.js#L18-L22
+ let proseMirrorWebKitUARegex = "\\bAppleWebKit\\/(\\d+)"
+ let proseMirroriOSUARegex = "Mobile\\/\\w+"
+
+ func testDefaultUserAgent() throws {
+ let userAgent: String = CCUtility.getUserAgent()
+ let match = try matches(for: ncServerUARegex, in: userAgent).first
+ XCTAssertNotNil(match)
+ }
+
+ func testTextUserAgent() throws {
+ let userAgent: String = NCUtility.shared.getCustomUserAgentNCText()
+ let match = try matches(for: ncServerUARegex, in: userAgent).first
+ XCTAssertNotNil(match)
+
+ let iOSMatch = try matches(for: proseMirroriOSUARegex, in: userAgent).first
+ XCTAssertNotNil(iOSMatch)
+
+ // https://github.com/ProseMirror/prosemirror-view/blob/8f246f320801f8e3cac92c97f71ac91e3e327f2f/src/input.js#L521-L522
+ let webKitMatch = try matches(for: proseMirrorWebKitUARegex, in: userAgent).first
+ XCTAssertNotNil(webKitMatch)
+ XCTAssertEqual(webKitMatch!.numberOfRanges, 2)
+ let versionRange = webKitMatch!.range(at: 1)
+ let versionString = userAgent[Range(versionRange, in: userAgent)!]
+ let webkitVersion = Int(versionString) ?? 0
+ XCTAssertGreaterThanOrEqual(webkitVersion, 604)
+ }
+
+ func matches(for regex: String, in text: String) throws -> [NSTextCheckingResult] {
+ let range = NSRange(location: 0, length: text.utf16.count)
+ let regex = try NSRegularExpression(pattern: regex)
+ return regex.matches(in: text, range: range)
+ }
+}
diff --git a/Share/NCShareExtension+Files.swift b/Share/NCShareExtension+Files.swift
index 13f05e8dc..8a1ccf6bf 100644
--- a/Share/NCShareExtension+Files.swift
+++ b/Share/NCShareExtension+Files.swift
@@ -47,22 +47,15 @@ extension NCShareExtension {
collectionView.reloadData()
}
- func createFolder(with fileName: String) {
-
- NCNetworking.shared.createFolder(fileName: fileName, serverUrl: serverUrl, account: activeAccount.account, urlBase: activeAccount.urlBase) { errorCode, errorDescription in
-
- DispatchQueue.main.async {
- if errorCode == 0 {
-
- self.serverUrl += "/" + fileName
- self.reloadDatasource(withLoadFolder: true)
- self.setNavigationBar(navigationTitle: fileName)
-
- } else {
- self.showAlert(title: "_error_createsubfolders_upload_", description: errorDescription)
- }
- }
- }
+ @objc func didCreateFolder(_ notification: NSNotification) {
+ guard let userInfo = notification.userInfo as NSDictionary?,
+ let ocId = userInfo["ocId"] as? String,
+ let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId)
+ else { return }
+
+ self.serverUrl += "/" + metadata.fileName
+ self.reloadDatasource(withLoadFolder: true)
+ self.setNavigationBar(navigationTitle: metadata.fileName)
}
func loadFolder() {
diff --git a/Share/NCShareExtension.swift b/Share/NCShareExtension.swift
index f45c2d342..831dc455c 100644
--- a/Share/NCShareExtension.swift
+++ b/Share/NCShareExtension.swift
@@ -132,6 +132,7 @@ class NCShareExtension: UIViewController {
}
NotificationCenter.default.addObserver(self, selector: #selector(triggerProgressTask(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterProgressTask), object: nil)
+ NotificationCenter.default.addObserver(self, selector: #selector(didCreateFolder(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterCreateFolder), object: nil)
}
override func viewWillAppear(_ animated: Bool) {
@@ -216,10 +217,7 @@ class NCShareExtension: UIViewController {
}
}
- let image = NCUtility.shared.loadUserImage(
- for: activeAccount.user,
- displayName: activeAccount.displayName,
- userBaseUrl: activeAccount)
+ let image = NCUtility.shared.loadUserImage(for: activeAccount.user, displayName: activeAccount.displayName, userBaseUrl: activeAccount)
let profileButton = UIButton(type: .custom)
profileButton.setImage(image, for: .normal)
@@ -277,25 +275,11 @@ class NCShareExtension: UIViewController {
}
@objc func actionCreateFolder() {
-
- let alertController = UIAlertController(title: NSLocalizedString("_create_folder_", comment: ""), message: "", preferredStyle: .alert)
-
- alertController.addTextField { textField in
- textField.autocapitalizationType = UITextAutocapitalizationType.words
- }
-
- let actionSave = UIAlertAction(title: NSLocalizedString("_save_", comment: ""), style: .default) { _ in
- if let fileName = alertController.textFields?.first?.text {
- self.createFolder(with: fileName)
- }
+ let alertController = UIAlertController.createFolder(serverUrl: serverUrl, urlBase: activeAccount) { errorCode, errorDescription in
+ guard errorCode != 0 else { return }
+ self.showAlert(title: "_error_createsubfolders_upload_", description: errorDescription)
}
-
- let actionCancel = UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel)
-
- alertController.addAction(actionSave)
- alertController.addAction(actionCancel)
-
- self.present(alertController, animated: true, completion: nil)
+ self.present(alertController, animated: true)
}
}
@@ -359,16 +343,16 @@ extension NCShareExtension {
hud.show(in: self.view)
NCNetworking.shared.upload(metadata: metadata) { } completion: { errorCode, _ in
- if errorCode == 0 {
- self.counterUploaded += 1
- self.upload()
- } else {
+ if errorCode != 0 {
let path = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId)!
NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
NCManageDatabase.shared.deleteChunks(account: metadata.account, ocId: metadata.ocId)
NCUtilityFileSystem.shared.deleteFile(filePath: path)
self.uploadErrors.append(metadata)
}
+
+ self.counterUploaded += 1
+ self.upload()
}
}
diff --git a/iOSClient/Activity/NCActivity.storyboard b/iOSClient/Activity/NCActivity.storyboard
index 39c8ecb24..6e9486484 100644
--- a/iOSClient/Activity/NCActivity.storyboard
+++ b/iOSClient/Activity/NCActivity.storyboard
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19455" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="nhT-TJ-YvX">
+<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="nhT-TJ-YvX">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19454"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@@ -17,7 +17,7 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="20" sectionFooterHeight="1" translatesAutoresizingMaskIntoConstraints="NO" id="X49-xg-JXO">
- <rect key="frame" x="0.0" y="100" width="414" height="762"/>
+ <rect key="frame" x="0.0" y="44" width="414" height="818"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="tableCell" rowHeight="120" id="ggj-aE-fnh" customClass="NCActivityTableViewCell" customModule="Nextcloud" customModuleProvider="target">
@@ -113,66 +113,18 @@
<outlet property="prefetchDataSource" destination="nhT-TJ-YvX" id="317-AD-uQe"/>
</connections>
</tableView>
- <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sG1-7f-3rF">
- <rect key="frame" x="0.0" y="0.0" width="414" height="100"/>
- <subviews>
- <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="hVn-Fn-7td">
- <rect key="frame" x="10" y="10" width="40" height="40"/>
- <constraints>
- <constraint firstAttribute="height" constant="40" id="eRU-q6-wZT"/>
- <constraint firstAttribute="width" constant="40" id="nee-e2-atl"/>
- </constraints>
- </imageView>
- <textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="249" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" clearButtonMode="always" translatesAutoresizingMaskIntoConstraints="NO" id="Wz7-gw-foA">
- <rect key="frame" x="60" y="60" width="344" height="30"/>
- <constraints>
- <constraint firstAttribute="height" constant="30" id="4ni-Qx-ber"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="14"/>
- <textInputTraits key="textInputTraits"/>
- <connections>
- <action selector="newCommentFieldDidEndOnExitWithTextField:" destination="nhT-TJ-YvX" eventType="editingDidEndOnExit" id="vPB-Eu-qkb"/>
- </connections>
- </textField>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="user" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YRy-AS-CMk">
- <rect key="frame" x="60" y="21.5" width="344" height="17"/>
- <fontDescription key="fontDescription" type="system" pointSize="14"/>
- <color key="textColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- <nil key="highlightedColor"/>
- </label>
- </subviews>
- <constraints>
- <constraint firstItem="YRy-AS-CMk" firstAttribute="centerY" secondItem="hVn-Fn-7td" secondAttribute="centerY" id="CBB-vi-6Z1"/>
- <constraint firstAttribute="trailing" secondItem="Wz7-gw-foA" secondAttribute="trailing" constant="10" id="CuV-5o-sFz"/>
- <constraint firstItem="hVn-Fn-7td" firstAttribute="leading" secondItem="sG1-7f-3rF" secondAttribute="leading" constant="10" id="NWH-NK-FjI"/>
- <constraint firstAttribute="height" constant="100" id="SfP-Sr-vbR"/>
- <constraint firstItem="Wz7-gw-foA" firstAttribute="leading" secondItem="hVn-Fn-7td" secondAttribute="trailing" constant="10" id="baP-t5-Kut"/>
- <constraint firstItem="Wz7-gw-foA" firstAttribute="top" secondItem="hVn-Fn-7td" secondAttribute="bottom" constant="10" id="bsh-yh-NR2"/>
- <constraint firstItem="YRy-AS-CMk" firstAttribute="leading" secondItem="hVn-Fn-7td" secondAttribute="trailing" constant="10" id="chn-JO-eYr"/>
- <constraint firstAttribute="bottom" secondItem="Wz7-gw-foA" secondAttribute="bottom" constant="10" id="e8b-hy-WHK"/>
- <constraint firstAttribute="trailing" secondItem="YRy-AS-CMk" secondAttribute="trailing" constant="10" id="uaN-5Y-k6V"/>
- <constraint firstItem="hVn-Fn-7td" firstAttribute="top" secondItem="sG1-7f-3rF" secondAttribute="top" constant="10" id="yLz-68-e22"/>
- </constraints>
- </view>
</subviews>
<viewLayoutGuide key="safeArea" id="USa-eR-a1s"/>
<constraints>
- <constraint firstItem="sG1-7f-3rF" firstAttribute="top" secondItem="vOO-VC-ekK" secondAttribute="top" id="0Wu-9f-jFf"/>
<constraint firstItem="X49-xg-JXO" firstAttribute="trailing" secondItem="USa-eR-a1s" secondAttribute="trailing" id="5we-Fh-GVu"/>
+ <constraint firstItem="X49-xg-JXO" firstAttribute="top" secondItem="USa-eR-a1s" secondAttribute="top" id="E1U-4Q-6uu"/>
<constraint firstItem="USa-eR-a1s" firstAttribute="bottom" secondItem="X49-xg-JXO" secondAttribute="bottom" id="aHq-g4-dUG"/>
- <constraint firstItem="X49-xg-JXO" firstAttribute="top" secondItem="sG1-7f-3rF" secondAttribute="bottom" id="eeu-9y-t1U"/>
- <constraint firstItem="sG1-7f-3rF" firstAttribute="trailing" secondItem="vOO-VC-ekK" secondAttribute="trailing" id="htz-S1-01v"/>
- <constraint firstItem="sG1-7f-3rF" firstAttribute="leading" secondItem="vOO-VC-ekK" secondAttribute="leading" id="lLm-NY-aXQ"/>
<constraint firstItem="X49-xg-JXO" firstAttribute="leading" secondItem="USa-eR-a1s" secondAttribute="leading" id="pfF-ag-f7x"/>
</constraints>
</view>
<connections>
- <outlet property="commentView" destination="sG1-7f-3rF" id="Nip-au-Ilu"/>
- <outlet property="imageItem" destination="hVn-Fn-7td" id="tqx-nV-WfA"/>
- <outlet property="labelUser" destination="YRy-AS-CMk" id="ijz-je-fBV"/>
- <outlet property="newCommentField" destination="Wz7-gw-foA" id="PDr-8b-iQY"/>
<outlet property="tableView" destination="X49-xg-JXO" id="GUb-8b-mIS"/>
- <outlet property="viewContainerConstraint" destination="0Wu-9f-jFf" id="TGF-fh-T7Y"/>
+ <outlet property="viewContainerConstraint" destination="E1U-4Q-6uu" id="NpJ-Iz-DtL"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="UOE-pW-DRy" userLabel="First Responder" sceneMemberID="firstResponder"/>
diff --git a/iOSClient/Activity/NCActivity.swift b/iOSClient/Activity/NCActivity.swift
index ab6354cfd..39edd3544 100644
--- a/iOSClient/Activity/NCActivity.swift
+++ b/iOSClient/Activity/NCActivity.swift
@@ -26,14 +26,12 @@ import UIKit
import SwiftRichString
import NCCommunication
-class NCActivity: UIViewController {
+class NCActivity: UIViewController, NCSharePagingContent {
@IBOutlet weak var tableView: UITableView!
- @IBOutlet weak var commentView: UIView!
- @IBOutlet weak var imageItem: UIImageView!
- @IBOutlet weak var labelUser: UILabel!
- @IBOutlet weak var newCommentField: UITextField!
+ var commentView: NCActivityCommentView?
+ var textField: UITextField? { commentView?.newCommentField }
@IBOutlet weak var viewContainerConstraint: NSLayoutConstraint!
var height: CGFloat = 0
@@ -76,46 +74,34 @@ class NCActivity: UIViewController {
if showComments {
setupComments()
- } else {
- commentView.isHidden = true
}
}
func setupComments() {
- tableView.register(UINib(nibName: "NCShareCommentsCell", bundle: nil), forCellReuseIdentifier: "cell")
-
- newCommentField.placeholder = NSLocalizedString("_new_comment_", comment: "")
- viewContainerConstraint.constant = height
-
// Display Name & Quota
guard let activeAccount = NCManageDatabase.shared.getActiveAccount(), height > 0 else {
- commentView.isHidden = true
return
}
- let fileName = appDelegate.userBaseUrl + "-" + appDelegate.user + ".png"
- let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName
- if let image = UIImage(contentsOfFile: fileNameLocalPath) {
- imageItem.image = image
- } else {
- imageItem.image = UIImage(named: "avatar")
- }
-
- if activeAccount.displayName.isEmpty {
- labelUser.text = activeAccount.user
- } else {
- labelUser.text = activeAccount.displayName
+ tableView.register(UINib(nibName: "NCShareCommentsCell", bundle: nil), forCellReuseIdentifier: "cell")
+ commentView = Bundle.main.loadNibNamed("NCActivityCommentView", owner: self, options: nil)?.first as? NCActivityCommentView
+ commentView?.setup(urlBase: appDelegate, account: activeAccount) { newComment in
+ guard let newComment = newComment, !newComment.isEmpty, let metadata = self.metadata else { return }
+ NCCommunication.shared.putComments(fileId: metadata.fileId, message: newComment) { _, errorCode, errorDescription in
+ if errorCode == 0 {
+ self.commentView?.newCommentField.text?.removeAll()
+ self.loadComments()
+ } else {
+ NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+ }
+ }
}
- labelUser.textColor = NCBrandColor.shared.label
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
-
appDelegate.activeViewController = self
-
NotificationCenter.default.addObserver(self, selector: #selector(initialize), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterInitialize), object: nil)
-
initialize()
}
@@ -127,6 +113,10 @@ class NCActivity: UIViewController {
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
tableView.tableFooterView = makeTableFooterView()
+ tableView.tableHeaderView = commentView
+ commentView?.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
+ commentView?.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
+ viewContainerConstraint.constant = height
}
// MARK: - NotificationCenter
@@ -140,23 +130,6 @@ class NCActivity: UIViewController {
tableView.reloadData()
}
- @IBAction func newCommentFieldDidEndOnExit(textField: UITextField) {
- guard
- let message = textField.text,
- !message.isEmpty,
- let metadata = self.metadata
- else { return }
-
- NCCommunication.shared.putComments(fileId: metadata.fileId, message: message) { _, errorCode, errorDescription in
- if errorCode == 0 {
- self.newCommentField.text = ""
- self.loadComments()
- } else {
- NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
- }
- }
- }
-
func makeTableFooterView() -> UIView {
let view = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 100))
view.backgroundColor = .clear
@@ -525,7 +498,7 @@ extension NCActivity: NCShareCommentsCellDelegate {
actions.append(
NCMenuAction(
title: NSLocalizedString("_edit_comment_", comment: ""),
- icon: UIImage(named: "edit")!.image(color: NCBrandColor.shared.gray, size: 50),
+ icon: UIImage(named: "pencil")!.image(color: NCBrandColor.shared.gray, size: 50),
action: { _ in
guard let metadata = self.metadata, let tableComments = tableComments else { return }
diff --git a/iOSClient/Activity/NCActivityCommentView.swift b/iOSClient/Activity/NCActivityCommentView.swift
new file mode 100644
index 000000000..b3b0d9c4f
--- /dev/null
+++ b/iOSClient/Activity/NCActivityCommentView.swift
@@ -0,0 +1,59 @@
+//
+// NCActivityCommentView.swift
+// Nextcloud
+//
+// Created by Henrik Storch on 04.01.22.
+// Copyright © 2021 Henrik Storch. All rights reserved.
+//
+// Author Henrik Storch <henrik.storch@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 NCActivityCommentView: UIView, UITextFieldDelegate {
+ @IBOutlet weak var imageItem: UIImageView!
+ @IBOutlet weak var labelUser: UILabel!
+ @IBOutlet weak var newCommentField: UITextField!
+
+ var completionHandler: ((String?) -> Void)?
+
+ func setup(urlBase: NCUserBaseUrl, account: tableAccount, completionHandler: @escaping (String?) -> Void) {
+ self.completionHandler = completionHandler
+ newCommentField.placeholder = NSLocalizedString("_new_comment_", comment: "")
+ newCommentField.delegate = self
+
+ let fileName = urlBase.userBaseUrl + "-" + urlBase.user + ".png"
+ let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName
+ if let image = UIImage(contentsOfFile: fileNameLocalPath) {
+ imageItem.image = image
+ } else {
+ imageItem.image = UIImage(named: "avatar")
+ }
+
+ if account.displayName.isEmpty {
+ labelUser.text = account.user
+ } else {
+ labelUser.text = account.displayName
+ }
+ labelUser.textColor = NCBrandColor.shared.label
+ }
+
+ func textFieldShouldReturn(_ textField: UITextField) -> Bool {
+ textField.resignFirstResponder()
+ completionHandler?(textField.text)
+ return true
+ }
+}
diff --git a/iOSClient/Activity/NCActivityCommentView.xib b/iOSClient/Activity/NCActivityCommentView.xib
new file mode 100644
index 000000000..0eba994ad
--- /dev/null
+++ b/iOSClient/Activity/NCActivityCommentView.xib
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+ <device id="retina6_1" orientation="portrait" appearance="light"/>
+ <dependencies>
+ <deployment identifier="iOS"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
+ <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"/>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="GuF-Pi-nHv" customClass="NCActivityCommentView" customModule="Nextcloud" customModuleProvider="target">
+ <rect key="frame" x="0.0" y="0.0" width="269" height="100"/>
+ <subviews>
+ <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="YXy-gE-g7y">
+ <rect key="frame" x="10" y="10" width="40" height="40"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="40" id="kUz-t2-bFL"/>
+ <constraint firstAttribute="height" constant="40" id="yRS-7c-bMw"/>
+ </constraints>
+ </imageView>
+ <textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="249" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" clearButtonMode="always" translatesAutoresizingMaskIntoConstraints="NO" id="5pv-VB-vbL">
+ <rect key="frame" x="60" y="60" width="199" height="30"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="30" id="OLX-lD-EIH"/>
+ </constraints>
+ <fontDescription key="fontDescription" type="system" pointSize="14"/>
+ <textInputTraits key="textInputTraits"/>
+ </textField>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="user" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0Ja-ik-S0n">
+ <rect key="frame" x="60" y="21.5" width="199" height="17"/>
+ <fontDescription key="fontDescription" type="system" pointSize="14"/>
+ <color key="textColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ <viewLayoutGuide key="safeArea" id="Y5x-Vi-PYA"/>
+ <constraints>
+ <constraint firstItem="YXy-gE-g7y" firstAttribute="top" secondItem="GuF-Pi-nHv" secondAttribute="top" constant="10" id="26g-rF-Ags"/>
+ <constraint firstAttribute="trailing" secondItem="0Ja-ik-S0n" secondAttribute="trailing" constant="10" id="7ue-4o-ZT2"/>
+ <constraint firstAttribute="height" constant="100" id="IsL-V9-dXU"/>
+ <constraint firstItem="0Ja-ik-S0n" firstAttribute="centerY" secondItem="YXy-gE-g7y" secondAttribute="centerY" id="NxM-vu-j06"/>
+ <constraint firstItem="5pv-VB-vbL" firstAttribute="leading" secondItem="YXy-gE-g7y" secondAttribute="trailing" constant="10" id="Oza-Za-mDZ"/>
+ <constraint firstItem="5pv-VB-vbL" firstAttribute="top" secondItem="YXy-gE-g7y" secondAttribute="bottom" constant="10" id="iie-Nv-YUr"/>
+ <constraint firstItem="0Ja-ik-S0n" firstAttribute="leading" secondItem="YXy-gE-g7y" secondAttribute="trailing" constant="10" id="j0L-NP-Z4H"/>
+ <constraint firstAttribute="trailing" secondItem="5pv-VB-vbL" secondAttribute="trailing" constant="10" id="oXJ-ov-XCK"/>
+ <constraint firstItem="YXy-gE-g7y" firstAttribute="leading" secondItem="GuF-Pi-nHv" secondAttribute="leading" constant="10" id="t5p-fd-swt"/>
+ <constraint firstAttribute="bottom" secondItem="5pv-VB-vbL" secondAttribute="bottom" constant="10" id="yEr-QL-mtD"/>
+ </constraints>
+ <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+ <connections>
+ <outlet property="imageItem" destination="YXy-gE-g7y" id="yWc-3P-gIU"/>
+ <outlet property="labelUser" destination="0Ja-ik-S0n" id="GkS-TV-2ic"/>
+ <outlet property="newCommentField" destination="5pv-VB-vbL" id="8vL-Mt-0rZ"/>
+ </connections>
+ <point key="canvasLocation" x="-231.15942028985509" y="-99.776785714285708"/>
+ </view>
+ </objects>
+</document>
diff --git a/iOSClient/AppDelegate.swift b/iOSClient/AppDelegate.swift
index 7172cc047..ccaeb5659 100644
--- a/iOSClient/AppDelegate.swift
+++ b/iOSClient/AppDelegate.swift
@@ -188,12 +188,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
// L' applicazione entrerà in primo piano (attivo sempre)
func applicationDidBecomeActive(_ application: UIApplication) {
-
- // Privacy
- hidePrivacyProtectionWindow()
-
- NCSettingsBundleHelper.setVersionAndBuildNumber()
-
+
+ if !NCAskAuthorization.shared.isRequesting {
+ // Privacy
+ hidePrivacyProtectionWindow()
+ }
+
NCSettingsBundleHelper.setVersionAndBuildNumber()
if account == "" { return }
@@ -245,9 +245,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
if account == "" { return }
- // Privacy
- showPrivacyProtectionWindow()
-
+ if CCUtility.getPrivacyScreenEnabled() {
+ // Privacy
+ showPrivacyProtectionWindow()
+ }
+
// Clear operation queue
NCOperationQueue.shared.cancelAllQueue()
// Clear download
@@ -266,20 +268,20 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
func applicationDidEnterBackground(_ application: UIApplication) {
if account == "" { return }
-
+
// STOP TIMER UPLOAD PROCESS
if NCUtility.shared.isSimulator() {
networkingProcessUpload?.stopTimer()
}
-
+
if #available(iOS 13.0, *) {
scheduleAppRefresh()
scheduleBackgroundProcessing()
}
-
+
// Passcode
presentPasscode { }
-
+
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterApplicationDidEnterBackground)
}
@@ -297,7 +299,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
if account == "" { return }
NCCommunicationCommon.shared.writeLog("initialize Main")
-
+
// Registeration push notification
NCPushNotification.shared().pushNotification()
@@ -362,7 +364,7 @@ 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 %lu uploads [Auto upload]")
+ NCCommunicationCommon.shared.writeLog("Completition handler refresh task with [Auto upload]")
task.setTaskCompleted(success: true)
}
}
@@ -606,6 +608,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
if serverVersionMajor > 0 {
NCCommunicationCommon.shared.setup(nextcloudVersion: serverVersionMajor)
}
+ NCKTVHTTPCache.shared.restartProxy(user: user, password: password)
}
@objc func deleteAccount(_ account: String, wipe: Bool) {
@@ -654,17 +657,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
// MARK: - Account Request
func accountRequestChangeAccount(account: String) {
-
changeAccount(account)
}
func requestAccount() {
-
+
if isPasscodePresented() { return }
if !CCUtility.getAccountRequest() { return }
-
+
let accounts = NCManageDatabase.shared.getAllAccount()
-
+
if accounts.count > 1 {
if let vcAccountRequest = UIStoryboard(name: "NCAccountRequest", bundle: nil).instantiateInitialViewController() as? NCAccountRequest {
@@ -691,30 +693,21 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
}
// MARK: - Passcode
-
- func presentPasscode(completion: @escaping ()->()) {
+
+ func presentPasscode(completion: @escaping () -> ()) {
let laContext = LAContext()
var error: NSError?
- defer {
- self.requestAccount()
- }
-
- guard !account.isEmpty, CCUtility.isPasscodeAtStartEnabled() else { return }
-
- // If activated hide the privacy protection
- hidePrivacyProtectionWindow()
+ defer { self.requestAccount() }
- // Dismiss present window?.rootViewController? [ONLY PASSCODE]
let presentedViewController = window?.rootViewController?.presentedViewController
- if presentedViewController is NCLoginNavigationController {
- return
- } else {
- presentedViewController?.dismiss(animated: false)
- }
+ guard !account.isEmpty, CCUtility.isPasscodeAtStartEnabled(), !(presentedViewController is NCLoginNavigationController) else { return }
- let passcodeViewController = TOPasscodeViewController.init(passcodeType: .sixDigits, allowCancel: false)
+ // Make sure we have a privacy window (in case it's not enabled)
+ showPrivacyProtectionWindow()
+
+ let passcodeViewController = TOPasscodeViewController(passcodeType: .sixDigits, allowCancel: false)
passcodeViewController.delegate = self
passcodeViewController.keypadButtonShowLettering = false
if CCUtility.getEnableTouchFaceID() && laContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
@@ -728,38 +721,40 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
passcodeViewController.automaticallyPromptForBiometricValidation = false
}
}
-
- window?.rootViewController?.present(passcodeViewController, animated: true, completion: {
+
+ // show passcode on top of privacy window
+ privacyProtectionWindow?.rootViewController?.present(passcodeViewController, animated: true, completion: {
completion()
})
}
-
+
func isPasscodePresented() -> Bool {
- return window?.rootViewController?.presentedViewController is TOPasscodeViewController
+ return privacyProtectionWindow?.rootViewController?.presentedViewController is TOPasscodeViewController
}
-
- func enableTouchFaceID() {
+ func enableTouchFaceID() {
guard !account.isEmpty,
CCUtility.getEnableTouchFaceID(),
CCUtility.isPasscodeAtStartEnabled(),
- let passcodeViewController = window?.rootViewController?.presentedViewController as? TOPasscodeViewController
+ let passcodeViewController = privacyProtectionWindow?.rootViewController?.presentedViewController as? TOPasscodeViewController
else { return }
LAContext().evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: NCBrandOptions.shared.brand) { (success, error) in
if success {
DispatchQueue.main.async {
passcodeViewController.dismiss(animated: true) {
+ self.hidePrivacyProtectionWindow()
self.requestAccount()
}
}
}
}
}
-
+
func didInputCorrectPasscode(in passcodeViewController: TOPasscodeViewController) {
DispatchQueue.main.async {
passcodeViewController.dismiss(animated: true) {
+ self.hidePrivacyProtectionWindow()
self.requestAccount()
}
}
@@ -769,27 +764,37 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
return code == CCUtility.getPasscode()
}
+ func didPerformBiometricValidationRequest(in passcodeViewController: TOPasscodeViewController) {
+ enableTouchFaceID()
+ }
+
// MARK: - Privacy Protection
-
+
private func showPrivacyProtectionWindow() {
-
- guard CCUtility.getPrivacyScreenEnabled() else { return }
-
+ guard privacyProtectionWindow == nil else {
+ privacyProtectionWindow?.isHidden = false
+ return
+ }
+
privacyProtectionWindow = UIWindow(frame: UIScreen.main.bounds)
-
+
let storyboard = UIStoryboard(name: "LaunchScreen", bundle: nil)
let initialViewController = storyboard.instantiateInitialViewController()
self.privacyProtectionWindow?.rootViewController = initialViewController
-
+
privacyProtectionWindow?.windowLevel = .alert + 1
privacyProtectionWindow?.makeKeyAndVisible()
}
- private func hidePrivacyProtectionWindow() {
-
- privacyProtectionWindow?.isHidden = true
- privacyProtectionWindow = nil
+ func hidePrivacyProtectionWindow() {
+ guard !(privacyProtectionWindow?.rootViewController?.presentedViewController is TOPasscodeViewController) else { return }
+ UIWindow.animate(withDuration: 0.25) {
+ self.privacyProtectionWindow?.alpha = 0
+ } completion: { _ in
+ self.privacyProtectionWindow?.isHidden = true
+ self.privacyProtectionWindow = nil
+ }
}
// MARK: - Open URL
@@ -873,13 +878,13 @@ extension AppDelegate: NCAudioRecorderViewControllerDelegate {
func didFinishRecording(_ viewController: NCAudioRecorderViewController, fileName: String) {
- guard let navigationController = UIStoryboard(name: "NCCreateFormUploadVoiceNote", bundle: nil).instantiateInitialViewController() else { return }
- navigationController.modalPresentationStyle = UIModalPresentationStyle.formSheet
- let appDelegate = UIApplication.shared.delegate as! AppDelegate
-
- let viewController = (navigationController as! UINavigationController).topViewController as! NCCreateFormUploadVoiceNote
- viewController.setup(serverUrl: appDelegate.activeServerUrl, fileNamePath: NSTemporaryDirectory() + fileName, fileName: fileName)
- appDelegate.window?.rootViewController?.present(navigationController, animated: true, completion: nil)
+ guard
+ let navigationController = UIStoryboard(name: "NCCreateFormUploadVoiceNote", bundle: nil).instantiateInitialViewController() as? UINavigationController,
+ let viewController = navigationController.topViewController as? NCCreateFormUploadVoiceNote
+ else { return }
+ navigationController.modalPresentationStyle = .formSheet
+ viewController.setup(serverUrl: activeServerUrl, fileNamePath: NSTemporaryDirectory() + fileName, fileName: fileName)
+ window?.rootViewController?.present(navigationController, animated: true)
}
func didFinishWithoutRecording(_ viewController: NCAudioRecorderViewController, fileName: String) {
diff --git a/iOSClient/Brand/Intro/NCIntroCollectionViewCell.xib b/iOSClient/Brand/Intro/NCIntroCollectionViewCell.xib
index 5c2357315..7eed66d3b 100644
--- a/iOSClient/Brand/Intro/NCIntroCollectionViewCell.xib
+++ b/iOSClient/Brand/Intro/NCIntroCollectionViewCell.xib
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="15702" 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="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
+ <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>
@@ -18,32 +18,30 @@
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bZc-Ai-h3y">
- <rect key="frame" x="8" y="426" width="321" height="28"/>
- <constraints>
- <constraint firstAttribute="height" relation="greaterThanOrEqual" constant="28" id="bXT-nO-EeQ"/>
- </constraints>
+ <rect key="frame" x="8" y="426.5" width="321" height="27.5"/>
<fontDescription key="fontDescription" type="system" pointSize="23"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" image="intro1" translatesAutoresizingMaskIntoConstraints="NO" id="f3T-nC-cwA">
- <rect key="frame" x="93.5" y="8" width="150" height="410"/>
+ <rect key="frame" x="93.5" y="156" width="150" height="150"/>
<constraints>
<constraint firstAttribute="width" relation="lessThanOrEqual" constant="150" id="jne-Xj-IAh"/>
+ <constraint firstAttribute="width" secondItem="f3T-nC-cwA" secondAttribute="height" multiplier="1:1" id="mhZ-Cn-42Q"/>
</constraints>
</imageView>
</subviews>
</view>
+ <viewLayoutGuide key="safeArea" id="ZTg-uK-7eu"/>
<color key="backgroundColor" red="1" green="0.57637232540000005" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="f3T-nC-cwA" firstAttribute="centerX" secondItem="gTV-IL-0wX" secondAttribute="centerX" id="4le-ih-K34"/>
- <constraint firstItem="bZc-Ai-h3y" firstAttribute="top" secondItem="f3T-nC-cwA" secondAttribute="bottom" constant="8" id="AWt-Zg-Blt"/>
- <constraint firstItem="f3T-nC-cwA" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" constant="8" id="Eh0-Bq-FKp"/>
<constraint firstAttribute="bottom" secondItem="bZc-Ai-h3y" secondAttribute="bottom" constant="8" id="YBJ-eg-EmZ"/>
+ <constraint firstItem="bZc-Ai-h3y" firstAttribute="top" relation="greaterThanOrEqual" secondItem="f3T-nC-cwA" secondAttribute="bottom" constant="16" id="av5-zS-GLQ"/>
<constraint firstItem="bZc-Ai-h3y" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" constant="8" id="eNj-fx-een"/>
+ <constraint firstItem="f3T-nC-cwA" firstAttribute="centerY" secondItem="gTV-IL-0wX" secondAttribute="centerY" priority="250" id="haX-eS-EOe"/>
<constraint firstAttribute="trailing" secondItem="bZc-Ai-h3y" secondAttribute="trailing" constant="8" id="uif-cW-sAI"/>
</constraints>
- <viewLayoutGuide key="safeArea" id="ZTg-uK-7eu"/>
<size key="customSize" width="337" height="428"/>
<connections>
<outlet property="imageView" destination="f3T-nC-cwA" id="aRR-4x-Dwk"/>
@@ -53,6 +51,6 @@
</collectionViewCell>
</objects>
<resources>
- <image name="intro1" width="200" height="200"/>
+ <image name="intro1" width="256" height="128"/>
</resources>
</document>
diff --git a/iOSClient/Brand/Intro/NCIntroViewController.swift b/iOSClient/Brand/Intro/NCIntroViewController.swift
index f9e725dc8..1002b888c 100644
--- a/iOSClient/Brand/Intro/NCIntroViewController.swift
+++ b/iOSClient/Brand/Intro/NCIntroViewController.swift
@@ -89,6 +89,8 @@ class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICol
buttonSignUp.layer.borderWidth = 1.0
buttonSignUp.setTitleColor(textColor, for: .normal)
buttonSignUp.backgroundColor = NCBrandColor.shared.customer
+ buttonSignUp.titleLabel?.adjustsFontSizeToFitWidth = true
+ buttonSignUp.titleEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)
buttonSignUp.setTitle(NSLocalizedString("_sign_up_", comment: ""), for: .normal)
buttonHost.layer.cornerRadius = 20
diff --git a/iOSClient/Brand/LaunchScreen.storyboard b/iOSClient/Brand/LaunchScreen.storyboard
index 0a2323f9f..26840f619 100755
--- a/iOSClient/Brand/LaunchScreen.storyboard
+++ b/iOSClient/Brand/LaunchScreen.storyboard
@@ -1,11 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
- <device id="retina4_7" orientation="portrait">
- <adaptation id="fullscreen"/>
- </device>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+ <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="19519"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@@ -18,16 +16,18 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
- <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="logo" translatesAutoresizingMaskIntoConstraints="NO" id="7UE-Dr-Fma">
- <rect key="frame" x="134" y="306" width="107" height="75"/>
+ <imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="logo" translatesAutoresizingMaskIntoConstraints="NO" id="7UE-Dr-Fma">
+ <rect key="frame" x="59.5" y="269.5" width="256" height="128"/>
</imageView>
</subviews>
+ <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
<color key="backgroundColor" red="0.0" green="0.50980392156862742" blue="0.78823529411764703" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
+ <constraint firstItem="7UE-Dr-Fma" firstAttribute="width" relation="lessThanOrEqual" secondItem="6Tk-OE-BBY" secondAttribute="width" id="8ik-eB-po8"/>
+ <constraint firstItem="7UE-Dr-Fma" firstAttribute="height" relation="lessThanOrEqual" secondItem="6Tk-OE-BBY" secondAttribute="height" id="G3L-l7-lxv"/>
<constraint firstItem="7UE-Dr-Fma" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="XdS-tM-D9I"/>
<constraint firstItem="7UE-Dr-Fma" firstAttribute="centerY" secondItem="6Tk-OE-BBY" secondAttribute="centerY" id="ZR5-ct-Gg8"/>
</constraints>
- <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
@@ -36,6 +36,6 @@
</scene>
</scenes>
<resources>
- <image name="logo" width="107" height="75.599998474121094"/>
+ <image name="logo" width="256" height="128"/>
</resources>
</document>
diff --git a/iOSClient/Brand/NCBrand.swift b/iOSClient/Brand/NCBrand.swift
index f393126b4..b8148e5af 100755
--- a/iOSClient/Brand/NCBrand.swift
+++ b/iOSClient/Brand/NCBrand.swift
@@ -47,7 +47,7 @@ import UIKit
@objc public var brand: String = "Nextcloud"
// @objc public var mailMe: String = "ios@nextcloud.com" // Deprecated
- @objc public var textCopyrightNextcloudiOS: String = "Nextcloud Liquid for iOS %@ © 2021"
+ @objc public var textCopyrightNextcloudiOS: String = "Nextcloud Liquid for iOS %@ © 2022"
@objc public var textCopyrightNextcloudServer: String = "Nextcloud Server %@"
@objc public var loginBaseUrl: String = "https://cloud.nextcloud.com"
@objc public var pushNotificationServerProxy: String = "https://push-notifications.nextcloud.com"
@@ -137,6 +137,7 @@ class NCBrandColor: NSObject {
static var buttonMore = UIImage()
static var buttonStop = UIImage()
+ static var buttonMoreLock = UIImage()
static var buttonRestore = UIImage()
}
@@ -215,6 +216,16 @@ class NCBrandColor: NSObject {
}
}
+ @objc public var secondaryLabel: UIColor {
+ get {
+ if #available(iOS 13, *) {
+ return .secondaryLabel
+ } else {
+ return UIColor(red: 0.24, green: 0.24, blue: 0.26, alpha: 0.6)
+ }
+ }
+ }
+
@objc public var separator: UIColor {
get {
if #available(iOS 13, *) {
@@ -345,6 +356,7 @@ class NCBrandColor: NSObject {
cacheImages.buttonMore = UIImage(named: "more")!.image(color: gray, size: 50)
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)
}
diff --git a/iOSClient/Brand/iOSClient.entitlements b/iOSClient/Brand/iOSClient.entitlements
index 1f984963f..a879c6400 100755
--- a/iOSClient/Brand/iOSClient.entitlements
+++ b/iOSClient/Brand/iOSClient.entitlements
@@ -4,18 +4,6 @@
<dict>
<key>aps-environment</key>
<string>development</string>
- <key>com.apple.developer.icloud-container-identifiers</key>
- <array>
- <string>iCloud.$(CFBundleIdentifier)</string>
- </array>
- <key>com.apple.developer.icloud-services</key>
- <array>
- <string>CloudDocuments</string>
- </array>
- <key>com.apple.developer.ubiquity-container-identifiers</key>
- <array>
- <string>iCloud.$(CFBundleIdentifier)</string>
- </array>
<key>com.apple.security.application-groups</key>
<array>
<string>group.it.twsweb.Crypto-Cloud</string>
diff --git a/iOSClient/Brand/iOSClient.plist b/iOSClient/Brand/iOSClient.plist
index 9af7f687d..9f096d6cb 100755
--- a/iOSClient/Brand/iOSClient.plist
+++ b/iOSClient/Brand/iOSClient.plist
@@ -64,17 +64,29 @@
<key>NSFaceIDUsageDescription</key>
<string>Face ID is required to authenticate using face recognition.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
- <string>GPS is used to detect new photos from camera roll, continued use of GPS running in the background can dramatically decrease battery life.</string>
+ <string>GPS is used to detect new photos from camera roll. Continued use of GPS running in the background can dramatically decrease battery life.</string>
<key>NSLocationAlwaysUsageDescription</key>
- <string>GPS is used to detect new photos from camera roll, continued use of GPS running in the background can dramatically decrease battery life.</string>
+ <string>GPS is used to detect new photos from camera roll. Continued use of GPS running in the background can dramatically decrease battery life.</string>
<key>NSLocationWhenInUseUsageDescription</key>
- <string>GPS is used to detect new photos from camera roll on background, the use of GPS only when the App is in use is useless.</string>
+ <string>GPS is used to detect new photos from camera roll on background. It is useless to use GPS only while using the app.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Microphone access is required to create voice notes.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<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>UIAppFonts</key>
+ <array>
+ <string>Inconsolata-Light.ttf</string>
+ <string>Inconsolata-Regular.ttf</string>
+ <string>Inconsolata-ExtraLight.ttf</string>
+ <string>Inconsolata-Medium.ttf</string>
+ <string>Inconsolata-Bold.ttf</string>
+ <string>Inconsolata-ExtraBold.ttf</string>
+ <string>Inconsolata-Black.ttf</string>
+ </array>
+ <key>PHPhotoLibraryPreventAutomaticLimitedAccessAlert</key>
+ <true/>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
@@ -105,8 +117,6 @@
<string>UIInterfaceOrientationLandscapeRight</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
- <key>UISupportsDocumentBrowser</key>
- <true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>
<key>UTExportedTypeDeclarations</key>
@@ -132,6 +142,27 @@
</array>
</dict>
</dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.text</string>
+ </array>
+ <key>UTTypeDescription</key>
+ <string>SRT Subtitle Format</string>
+ <key>UTTypeIconFiles</key>
+ <array/>
+ <key>UTTypeIdentifier</key>
+ <string>com.company.srt</string>
+ <key>UTTypeReferenceURL</key>
+ <string></string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>srt</string>
+ </array>
+ </dict>
+ </dict>
</array>
</dict>
</plist>
diff --git a/iOSClient/Data/NCDatabase.swift b/iOSClient/Data/NCDatabase.swift
index 479e8ca92..0bd307150 100644
--- a/iOSClient/Data/NCDatabase.swift
+++ b/iOSClient/Data/NCDatabase.swift
@@ -37,9 +37,7 @@ class tableAccount: Object, NCUserBaseUrl {
@objc dynamic var address = ""
@objc dynamic var alias = ""
@objc dynamic var autoUpload: Bool = false
- @objc dynamic var autoUploadBackground: Bool = false
@objc dynamic var autoUploadCreateSubfolder: Bool = false
- @objc dynamic var autoUploadDeleteAssetLocalIdentifier: Bool = false
@objc dynamic var autoUploadDirectory = ""
@objc dynamic var autoUploadFileName = ""
@objc dynamic var autoUploadFull: Bool = false
@@ -384,6 +382,13 @@ class tableMetadata: Object, NCUserBaseUrl {
@objc dynamic var ocId = ""
@objc dynamic var ownerId = ""
@objc dynamic var ownerDisplayName = ""
+ @objc public var lock = false
+ @objc public var lockOwner = ""
+ @objc public var lockOwnerEditor = ""
+ @objc public var lockOwnerType = 0
+ @objc public var lockOwnerDisplayName = ""
+ @objc public var lockTime: Date?
+ @objc public var lockTimeOut: Date?
@objc dynamic var path = ""
@objc dynamic var permissions = ""
@objc dynamic var quotaUsedBytes: Int64 = 0
@@ -420,6 +425,11 @@ extension tableMetadata {
var isPrintable: Bool {
classFile == NCCommunicationCommon.typeClassFile.image.rawValue || ["application/pdf", "com.adobe.pdf"].contains(contentType) || contentType.hasPrefix("text/")
}
+
+ /// Returns false if the user is lokced out of the file. I.e. The file is locked but by somone else
+ func canUnlock(as user: String) -> Bool {
+ return !lock || (lockOwner == user && lockOwnerType == 0)
+ }
}
class tablePhotoLibrary: Object {
@@ -493,6 +503,11 @@ class tableTag: Object {
}
}
+class tableTip: Object {
+
+ @Persisted(primaryKey: true) var tipName = ""
+}
+
class tableTrash: Object {
@objc dynamic var account = ""
@@ -539,7 +554,6 @@ class tableVideo: Object {
@objc dynamic var codecNameAudio: String?
@objc dynamic var codecAudioChannelLayout: String?
@objc dynamic var codecAudioLanguage: String?
- @objc dynamic var codecSubtitleLanguage: String?
@objc dynamic var codecMaxCompatibility: Bool = false
@objc dynamic var codecQuality: String?
diff --git a/iOSClient/Data/NCElementsJSON.swift b/iOSClient/Data/NCElementsJSON.swift
index 030464637..962a142c3 100644
--- a/iOSClient/Data/NCElementsJSON.swift
+++ b/iOSClient/Data/NCElementsJSON.swift
@@ -58,7 +58,8 @@ import UIKit
@objc public let capabilitiesNotification: Array = ["ocs", "data", "capabilities", "notifications", "ocs-endpoints"]
@objc public let capabilitiesFilesUndelete: Array = ["ocs", "data", "capabilities", "files", "undelete"]
- @objc public let capabilitiesFilesComments: Array = ["ocs", "data", "capabilities", "files", "comments"] // NC 20
+ @objc public let capabilitiesFilesLockVersion: Array = ["ocs", "data", "capabilities", "files", "locking"] // NC 24
+ @objc public let capabilitiesFilesComments: Array = ["ocs", "data", "capabilities", "files", "comments"] // NC 20
@objc public let capabilitiesHWCEnabled: Array = ["ocs", "data", "capabilities", "handwerkcloud", "enabled"]
diff --git a/iOSClient/Data/NCManageDatabase+Account.swift b/iOSClient/Data/NCManageDatabase+Account.swift
index 305e37f33..7b5574ea2 100644
--- a/iOSClient/Data/NCManageDatabase+Account.swift
+++ b/iOSClient/Data/NCManageDatabase+Account.swift
@@ -5,6 +5,21 @@
// Created by Henrik Storch on 30.11.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 Foundation
import RealmSwift
diff --git a/iOSClient/Data/NCManageDatabase+Activity.swift b/iOSClient/Data/NCManageDatabase+Activity.swift
index f3d7f3a1f..3e84bf4df 100644
--- a/iOSClient/Data/NCManageDatabase+Activity.swift
+++ b/iOSClient/Data/NCManageDatabase+Activity.swift
@@ -5,6 +5,21 @@
// Created by Henrik Storch on 30.11.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 Foundation
import RealmSwift
@@ -13,9 +28,6 @@ import SwiftyJSON
extension NCManageDatabase {
- // MARK: -
- // MARK: Table Activity
-
@objc func addActivity(_ activities: [NCCommunicationActivity], account: String) {
let realm = try! Realm()
diff --git a/iOSClient/Data/NCManageDatabse+Metadata.swift b/iOSClient/Data/NCManageDatabase+Metadata.swift
index 684a37a1e..2c115ce6d 100644
--- a/iOSClient/Data/NCManageDatabse+Metadata.swift
+++ b/iOSClient/Data/NCManageDatabase+Metadata.swift
@@ -1,10 +1,25 @@
//
-// NCManageDatabse+Metadata.swift
+// NCManageDatabase+Metadata.swift
// Nextcloud
//
// Created by Henrik Storch on 30.11.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 Foundation
import RealmSwift
@@ -49,6 +64,13 @@ extension NCManageDatabase {
metadata.ocId = file.ocId
metadata.ownerId = file.ownerId
metadata.ownerDisplayName = file.ownerDisplayName
+ metadata.lock = file.lock
+ metadata.lockOwner = file.lockOwner
+ metadata.lockOwnerEditor = file.lockOwnerEditor
+ metadata.lockOwnerType = file.lockOwnerType
+ metadata.lockOwnerDisplayName = file.lockOwnerDisplayName
+ metadata.lockTime = file.lockTime
+ metadata.lockTimeOut = file.lockTimeOut
metadata.path = file.path
metadata.permissions = file.permissions
metadata.quotaUsedBytes = file.quotaUsedBytes
@@ -65,6 +87,10 @@ 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 {
+ metadata.classFile = NCCommunicationCommon.typeClassFile.document.rawValue
+ }
if let date = file.uploadDate {
metadata.uploadDate = date
} else {
@@ -166,6 +192,10 @@ extension NCManageDatabase {
metadata.urlBase = urlBase
metadata.user = user
metadata.userId = userId
+
+ if !metadata.urlBase.isEmpty, metadata.serverUrl.hasPrefix(metadata.urlBase) {
+ metadata.path = String(metadata.serverUrl.dropFirst(metadata.urlBase.count)) + "/"
+ }
return metadata
}
@@ -300,7 +330,9 @@ extension NCManageDatabase {
if let result = metadatasResult.first(where: { $0.ocId == metadata.ocId }) {
// update
- 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) {
+ // 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) {
ocIdsUdate.append(metadata.ocId)
realm.add(tableMetadata.init(value: metadata), update: .all)
} else if result.status == NCGlobal.shared.metadataStatusNormal && addCompareLivePhoto && result.livePhoto != metadata.livePhoto {
@@ -676,14 +708,14 @@ extension NCManageDatabase {
}
}
- @objc func getAssetLocalIdentifiersUploaded(account: String, sessionSelector: String) -> [String] {
+ @objc func getAssetLocalIdentifiersUploaded(account: String) -> [String] {
let realm = try! Realm()
realm.refresh()
var assetLocalIdentifiers: [String] = []
- let results = realm.objects(tableMetadata.self).filter("account == %@ AND assetLocalIdentifier != '' AND deleteAssetLocalIdentifier == true AND sessionSelector == %@", account, sessionSelector)
+ let results = realm.objects(tableMetadata.self).filter("account == %@ AND assetLocalIdentifier != '' AND deleteAssetLocalIdentifier == true", account)
for result in results {
assetLocalIdentifiers.append(result.assetLocalIdentifier)
}
@@ -788,4 +820,19 @@ extension NCManageDatabase {
}
return getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileNameView == %@", account, serverUrl, fileNameConflict))
}
+
+ func getSubtitles(account: String, serverUrl: String, fileName: String) -> (all:[tableMetadata], existing:[tableMetadata]) {
+
+ let realm = try! Realm()
+ let nameOnly = (fileName as NSString).deletingPathExtension + "."
+ var metadatas: [tableMetadata] = []
+
+ let results = realm.objects(tableMetadata.self).filter("account == %@ AND serverUrl == %@ AND fileName BEGINSWITH[c] %@ AND fileName ENDSWITH[c] '.srt'", account, serverUrl, nameOnly)
+ for result in results {
+ if CCUtility.fileProviderStorageExists(result) {
+ metadatas.append(result)
+ }
+ }
+ return(Array(results.map { tableMetadata.init(value: $0) }), Array(metadatas.map { tableMetadata.init(value: $0) }))
+ }
}
diff --git a/iOSClient/Data/NCManageDatabase+Video.swift b/iOSClient/Data/NCManageDatabase+Video.swift
new file mode 100644
index 000000000..34723d9ec
--- /dev/null
+++ b/iOSClient/Data/NCManageDatabase+Video.swift
@@ -0,0 +1,152 @@
+//
+// NCManageDatabase+Video.swift
+// Nextcloud
+//
+// Created by Marino Faggiana on 15/03/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 RealmSwift
+import NCCommunication
+
+extension NCManageDatabase {
+
+ func addVideoTime(metadata: tableMetadata, time: CMTime?, durationTime: CMTime?) {
+
+ if metadata.livePhoto { return }
+ let realm = try! Realm()
+
+ do {
+ try realm.safeWrite {
+ if let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId).first {
+
+ if let durationTime = durationTime {
+ result.duration = durationTime.convertScale(1000, method: .default).value
+ }
+ if let time = time {
+ result.time = time.convertScale(1000, method: .default).value
+ }
+ realm.add(result, update: .all)
+
+ } else {
+
+ let addObject = tableVideo()
+
+ addObject.account = metadata.account
+ if let durationTime = durationTime {
+ addObject.duration = durationTime.convertScale(1000, method: .default).value
+ }
+ addObject.ocId = metadata.ocId
+ if let time = time {
+ addObject.time = time.convertScale(1000, method: .default).value
+ }
+ realm.add(addObject, update: .all)
+ }
+ }
+ } catch let error {
+ NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+ }
+ }
+
+ func addVideoCodec(metadata: tableMetadata, codecNameVideo: String?, codecNameAudio: String?, codecAudioChannelLayout: String?, codecAudioLanguage: String?, codecMaxCompatibility: Bool, codecQuality: String?) {
+
+ let realm = try! Realm()
+
+ do {
+ try realm.safeWrite {
+ if let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId).first {
+ if let codecNameVideo = codecNameVideo { result.codecNameVideo = codecNameVideo }
+ if let codecNameAudio = codecNameAudio { result.codecNameAudio = codecNameAudio }
+ if let codecAudioChannelLayout = codecAudioChannelLayout { result.codecAudioChannelLayout = codecAudioChannelLayout }
+ if let codecAudioLanguage = codecAudioLanguage { result.codecAudioLanguage = codecAudioLanguage }
+ result.codecMaxCompatibility = codecMaxCompatibility
+ if let codecQuality = codecQuality { result.codecQuality = codecQuality }
+ realm.add(result, update: .all)
+ } else {
+ let addObject = tableVideo()
+ addObject.account = metadata.account
+ addObject.ocId = metadata.ocId
+ addObject.codecNameVideo = codecNameVideo
+ addObject.codecNameAudio = codecNameAudio
+ addObject.codecAudioChannelLayout = codecAudioChannelLayout
+ addObject.codecAudioLanguage = codecAudioLanguage
+ addObject.codecMaxCompatibility = codecMaxCompatibility
+ addObject.codecQuality = codecQuality
+ realm.add(addObject, update: .all)
+ }
+ }
+ } catch let error {
+ NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+ }
+ }
+
+ func getVideo(metadata: tableMetadata?) -> tableVideo? {
+ guard let metadata = metadata else { return nil }
+
+ let realm = try! Realm()
+ guard let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId).first else {
+ return nil
+ }
+
+ return tableVideo.init(value: result)
+ }
+
+ func getVideoDurationTime(metadata: tableMetadata?) -> CMTime? {
+ guard let metadata = metadata else { return nil }
+
+ if metadata.livePhoto { return nil }
+ let realm = try! Realm()
+
+ guard let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId).first else {
+ return nil
+ }
+
+ if result.duration == 0 { return nil }
+ let duration = CMTimeMake(value: result.duration, timescale: 1000)
+ return duration
+ }
+
+ func getVideoTime(metadata: tableMetadata) -> CMTime? {
+
+ if metadata.livePhoto { return nil }
+ let realm = try! Realm()
+
+ guard let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId).first else {
+ return nil
+ }
+
+ if result.time == 0 { return nil }
+ let time = CMTimeMake(value: result.time, timescale: 1000)
+ return time
+ }
+
+ func deleteVideo(metadata: tableMetadata) {
+
+ let realm = try! Realm()
+
+ do {
+ try realm.safeWrite {
+ let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId)
+ realm.delete(result)
+ }
+ } catch let error {
+ NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+ }
+ }
+}
diff --git a/iOSClient/Data/NCManageDatabase.swift b/iOSClient/Data/NCManageDatabase.swift
index d2df51389..37f9aa4c7 100644
--- a/iOSClient/Data/NCManageDatabase.swift
+++ b/iOSClient/Data/NCManageDatabase.swift
@@ -149,6 +149,11 @@ class NCManageDatabase: NSObject {
}
}
+ if oldSchemaVersion < 222 && NCUtility.shared.SYSTEM_VERSION_LESS_THAN(version: "13") {
+ migration.deleteData(forType: tableMetadata.className())
+ migration.deleteData(forType: tableDirectory.className())
+ }
+
}, shouldCompactOnLaunch: { totalBytes, usedBytes in
// totalBytes refers to the size of the file on disk in bytes (data + free space)
@@ -245,6 +250,7 @@ class NCManageDatabase: NSObject {
self.clearTable(tablePhotoLibrary.self, account: account)
self.clearTable(tableShare.self, account: account)
self.clearTable(tableTag.self, account: account)
+ self.clearTable(tableTip.self)
self.clearTable(tableTrash.self, account: account)
self.clearTable(tableUserStatus.self, account: account)
self.clearTable(tableVideo.self, account: account)
@@ -1547,6 +1553,37 @@ class NCManageDatabase: NSObject {
}
// MARK: -
+ // MARK: Table Tip
+
+ @objc func tipExists(_ tipName: String) -> Bool {
+
+ let realm = try! Realm()
+
+ guard (realm.objects(tableTip.self).where {
+ $0.tipName == tipName
+ }.first) == nil else {
+ return true
+ }
+
+ return false
+ }
+
+ @objc func addTip(_ tipName: String) {
+
+ let realm = try! Realm()
+
+ do {
+ try realm.safeWrite {
+ let addObject = tableTip()
+ addObject.tipName = tipName
+ realm.add(addObject, update: .all)
+ }
+ } catch let error {
+ NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
+ }
+ }
+
+ // MARK: -
// MARK: Table Trash
@objc func addTrash(account: String, items: [NCCommunicationTrash]) {
@@ -1682,133 +1719,6 @@ class NCManageDatabase: NSObject {
NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
}
}
- // MARK: -
- // MARK: Table Video
-
- func addVideoTime(metadata: tableMetadata, time: CMTime?, durationTime: CMTime?) {
-
- if metadata.livePhoto { return }
- let realm = try! Realm()
-
- do {
- try realm.safeWrite {
- if let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId).first {
-
- if let durationTime = durationTime {
- result.duration = durationTime.convertScale(1000, method: .default).value
- }
- if let time = time {
- result.time = time.convertScale(1000, method: .default).value
- }
- realm.add(result, update: .all)
-
- } else {
-
- let addObject = tableVideo()
-
- addObject.account = metadata.account
- if let durationTime = durationTime {
- addObject.duration = durationTime.convertScale(1000, method: .default).value
- }
- addObject.ocId = metadata.ocId
- if let time = time {
- addObject.time = time.convertScale(1000, method: .default).value
- }
- realm.add(addObject, update: .all)
- }
- }
- } catch let error {
- NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
- }
- }
-
- func addVideoCodec(metadata: tableMetadata, codecNameVideo: String?, codecNameAudio: String?, codecAudioChannelLayout: String?, codecAudioLanguage: String?, codecSubtitleLanguage: String?, codecMaxCompatibility: Bool, codecQuality: String?) {
-
- let realm = try! Realm()
-
- do {
- try realm.safeWrite {
- if let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId).first {
- if let codecNameVideo = codecNameVideo { result.codecNameVideo = codecNameVideo }
- if let codecNameAudio = codecNameAudio { result.codecNameAudio = codecNameAudio }
- if let codecAudioChannelLayout = codecAudioChannelLayout { result.codecAudioChannelLayout = codecAudioChannelLayout }
- if let codecAudioLanguage = codecAudioLanguage { result.codecAudioLanguage = codecAudioLanguage }
- if let codecSubtitleLanguage = codecSubtitleLanguage { result.codecSubtitleLanguage = codecSubtitleLanguage }
- result.codecMaxCompatibility = codecMaxCompatibility
- if let codecQuality = codecQuality { result.codecQuality = codecQuality }
- realm.add(result, update: .all)
- } else {
- let addObject = tableVideo()
- addObject.account = metadata.account
- addObject.ocId = metadata.ocId
- addObject.codecNameVideo = codecNameVideo
- addObject.codecNameAudio = codecNameAudio
- addObject.codecAudioChannelLayout = codecAudioChannelLayout
- addObject.codecAudioLanguage = codecAudioLanguage
- addObject.codecSubtitleLanguage = codecSubtitleLanguage
- addObject.codecMaxCompatibility = codecMaxCompatibility
- addObject.codecQuality = codecQuality
- realm.add(addObject, update: .all)
- }
- }
- } catch let error {
- NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
- }
- }
-
- func getVideo(metadata: tableMetadata?) -> tableVideo? {
- guard let metadata = metadata else { return nil }
-
- let realm = try! Realm()
- guard let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId).first else {
- return nil
- }
-
- return tableVideo.init(value: result)
- }
-
- func getVideoDurationTime(metadata: tableMetadata?) -> CMTime? {
- guard let metadata = metadata else { return nil }
-
- if metadata.livePhoto { return nil }
- let realm = try! Realm()
-
- guard let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId).first else {
- return nil
- }
-
- if result.duration == 0 { return nil }
- let duration = CMTimeMake(value: result.duration, timescale: 1000)
- return duration
- }
-
- func getVideoTime(metadata: tableMetadata) -> CMTime? {
-
- if metadata.livePhoto { return nil }
- let realm = try! Realm()
-
- guard let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId).first else {
- return nil
- }
-
- if result.time == 0 { return nil }
- let time = CMTimeMake(value: result.time, timescale: 1000)
- return time
- }
-
- func deleteVideo(metadata: tableMetadata) {
-
- let realm = try! Realm()
-
- do {
- try realm.safeWrite {
- let result = realm.objects(tableVideo.self).filter("account == %@ AND ocId == %@", metadata.account, metadata.ocId)
- realm.delete(result)
- }
- } catch let error {
- NCCommunicationCommon.shared.writeLog("Could not write to database: \(error)")
- }
- }
}
// MARK: -
diff --git a/iOSClient/Diagnostics/NCCapabilitiesViewController.storyboard b/iOSClient/Diagnostics/NCCapabilitiesViewController.storyboard
index e5846cd02..05f89c257 100644
--- a/iOSClient/Diagnostics/NCCapabilitiesViewController.storyboard
+++ b/iOSClient/Diagnostics/NCCapabilitiesViewController.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="vTK-Er-kbZ">
+<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="vTK-Er-kbZ">
<device id="retina6_1" 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"/>
@@ -21,7 +21,7 @@
<rect key="frame" x="0.0" y="88" width="414" height="774"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Sms-Ez-fLO" userLabel="View Capabilities">
- <rect key="frame" x="5" y="5" width="404" height="550"/>
+ <rect key="frame" x="5" y="5" width="404" height="600"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jdW-oZ-cH8" userLabel="FileSharing">
<rect key="frame" x="0.0" y="0.0" width="404" height="50"/>
@@ -455,26 +455,68 @@
<constraint firstAttribute="trailing" secondItem="lVT-MG-7kN" secondAttribute="trailing" constant="5" id="zCZ-du-XT5"/>
</constraints>
</view>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="npG-0C-m3A" userLabel="Lock">
+ <rect key="frame" x="0.0" y="550" width="404" height="50"/>
+ <subviews>
+ <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="lock" translatesAutoresizingMaskIntoConstraints="NO" id="eAC-Li-gKO">
+ <rect key="frame" x="0.0" y="10" width="30" height="30"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="30" id="JsP-Q6-6yG"/>
+ <constraint firstAttribute="width" constant="30" id="WUk-lh-3Vb"/>
+ </constraints>
+ </imageView>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Lock file" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SCj-6t-sXN">
+ <rect key="frame" x="40" y="16" width="57.5" height="18"/>
+ <fontDescription key="fontDescription" type="system" pointSize="15"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Available" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="db5-st-O6M">
+ <rect key="frame" x="279" y="12.5" width="120" height="25"/>
+ <color key="backgroundColor" systemColor="systemGray4Color"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="120" id="Vfm-Rm-l7N"/>
+ <constraint firstAttribute="height" constant="25" id="oam-XV-KqH"/>
+ </constraints>
+ <fontDescription key="fontDescription" type="system" pointSize="12"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+ <constraints>
+ <constraint firstItem="db5-st-O6M" firstAttribute="centerY" secondItem="npG-0C-m3A" secondAttribute="centerY" id="0X7-Jw-OjP"/>
+ <constraint firstItem="eAC-Li-gKO" firstAttribute="leading" secondItem="npG-0C-m3A" secondAttribute="leading" id="1yz-QU-lXY"/>
+ <constraint firstAttribute="height" constant="50" id="6GQ-cE-Nz3"/>
+ <constraint firstItem="SCj-6t-sXN" firstAttribute="centerY" secondItem="npG-0C-m3A" secondAttribute="centerY" id="Ocs-LT-OYb"/>
+ <constraint firstItem="eAC-Li-gKO" firstAttribute="centerY" secondItem="npG-0C-m3A" secondAttribute="centerY" id="SlK-BL-Nba"/>
+ <constraint firstAttribute="trailing" secondItem="db5-st-O6M" secondAttribute="trailing" constant="5" id="Upi-tI-m1R"/>
+ <constraint firstItem="SCj-6t-sXN" firstAttribute="leading" secondItem="eAC-Li-gKO" secondAttribute="trailing" constant="10" id="dgu-xW-E8T"/>
+ </constraints>
+ </view>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="lGp-bh-Ysz" firstAttribute="leading" secondItem="Sms-Ez-fLO" secondAttribute="leading" id="0qE-PV-O2f"/>
<constraint firstAttribute="trailing" secondItem="8nf-zJ-Qas" secondAttribute="trailing" id="0vv-HQ-Qqx"/>
- <constraint firstAttribute="height" constant="550" id="6nU-Cb-MzH"/>
+ <constraint firstAttribute="height" constant="600" id="6nU-Cb-MzH"/>
<constraint firstItem="mSC-JU-xuk" firstAttribute="leading" secondItem="Sms-Ez-fLO" secondAttribute="leading" id="9Nq-du-3ah"/>
<constraint firstItem="S24-Wc-fps" firstAttribute="leading" secondItem="Sms-Ez-fLO" secondAttribute="leading" id="Aad-cm-E1T"/>
<constraint firstAttribute="trailing" secondItem="S24-Wc-fps" secondAttribute="trailing" id="Ajf-er-GBr"/>
<constraint firstItem="ZNB-jF-9zg" firstAttribute="leading" secondItem="Sms-Ez-fLO" secondAttribute="leading" id="GdE-lt-vZC"/>
<constraint firstAttribute="trailing" secondItem="nVq-4i-FNy" secondAttribute="trailing" id="HSG-Ia-fYc"/>
+ <constraint firstItem="npG-0C-m3A" firstAttribute="top" secondItem="S24-Wc-fps" secondAttribute="bottom" constant="2" id="IQe-Xv-U7D"/>
<constraint firstItem="S24-Wc-fps" firstAttribute="top" secondItem="2Pp-Kb-YMc" secondAttribute="bottom" constant="-2" id="ML8-GT-9hb"/>
<constraint firstAttribute="trailing" secondItem="2Pp-Kb-YMc" secondAttribute="trailing" id="NG8-Nu-ic6"/>
<constraint firstItem="LTt-2C-rPb" firstAttribute="top" secondItem="dhs-06-3RT" secondAttribute="bottom" id="Nm6-NH-AC9"/>
+ <constraint firstItem="npG-0C-m3A" firstAttribute="leading" secondItem="Sms-Ez-fLO" secondAttribute="leading" id="QH1-s3-UQ7"/>
<constraint firstItem="UPC-L1-VKj" firstAttribute="leading" secondItem="Sms-Ez-fLO" secondAttribute="leading" id="QcN-sd-pHM"/>
<constraint firstItem="LTt-2C-rPb" firstAttribute="leading" secondItem="Sms-Ez-fLO" secondAttribute="leading" id="SUy-Mo-oAO"/>
<constraint firstItem="jdW-oZ-cH8" firstAttribute="top" secondItem="Sms-Ez-fLO" secondAttribute="top" id="UBW-Mx-NTs"/>
<constraint firstItem="8nf-zJ-Qas" firstAttribute="top" secondItem="UPC-L1-VKj" secondAttribute="bottom" id="UqS-Lx-6mL"/>
<constraint firstItem="dhs-06-3RT" firstAttribute="leading" secondItem="Sms-Ez-fLO" secondAttribute="leading" id="UwG-6b-pEk"/>
<constraint firstItem="nVq-4i-FNy" firstAttribute="top" secondItem="mSC-JU-xuk" secondAttribute="bottom" id="VfU-sj-S9y"/>
+ <constraint firstAttribute="trailing" secondItem="npG-0C-m3A" secondAttribute="trailing" id="bLv-wr-d5v"/>
<constraint firstAttribute="trailing" secondItem="lGp-bh-Ysz" secondAttribute="trailing" id="bUd-8w-D8k"/>
<constraint firstItem="UPC-L1-VKj" firstAttribute="top" secondItem="lGp-bh-Ysz" secondAttribute="bottom" id="br5-nz-w7h"/>
<constraint firstItem="8nf-zJ-Qas" firstAttribute="leading" secondItem="Sms-Ez-fLO" secondAttribute="leading" id="dsm-XA-dZD"/>
@@ -495,7 +537,7 @@
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ogC-ph-Xdr" userLabel="View Link">
- <rect key="frame" x="5" y="550" width="404" height="40"/>
+ <rect key="frame" x="5" y="620" width="404" height="40"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Home server" textAlignment="natural" lineBreakMode="characterWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="PD5-8h-ZLm">
<rect key="frame" x="40" y="0.0" width="359" height="40"/>
@@ -525,7 +567,7 @@
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="OO4-N7-9vp" userLabel="View JSON">
- <rect key="frame" x="0.0" y="600" width="414" height="40.5"/>
+ <rect key="frame" x="0.0" y="670" width="414" height="40.5"/>
<subviews>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" editable="NO" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="RIO-6X-GG1">
<rect key="frame" x="5" y="5" width="404" height="30.5"/>
@@ -545,8 +587,8 @@
</view>
</subviews>
<constraints>
- <constraint firstItem="ogC-ph-Xdr" firstAttribute="top" secondItem="hTE-ys-qsF" secondAttribute="top" constant="550" id="9yP-Qs-EjJ"/>
- <constraint firstItem="OO4-N7-9vp" firstAttribute="top" secondItem="hTE-ys-qsF" secondAttribute="top" constant="600" id="A9O-TK-Vz6" userLabel="View JSON.top = top + 550"/>
+ <constraint firstItem="ogC-ph-Xdr" firstAttribute="top" secondItem="hTE-ys-qsF" secondAttribute="top" constant="620" id="9yP-Qs-EjJ"/>
+ <constraint firstItem="OO4-N7-9vp" firstAttribute="top" secondItem="hTE-ys-qsF" secondAttribute="top" constant="670" id="A9O-TK-Vz6" userLabel="View JSON.top = top + 550"/>
<constraint firstAttribute="trailing" secondItem="ogC-ph-Xdr" secondAttribute="trailing" constant="5" id="JLe-vC-Oyq"/>
<constraint firstAttribute="bottom" secondItem="OO4-N7-9vp" secondAttribute="bottom" id="MpX-OZ-MDh"/>
<constraint firstItem="OO4-N7-9vp" firstAttribute="width" secondItem="hTE-ys-qsF" secondAttribute="width" id="PWW-C3-Qcw"/>
@@ -579,6 +621,7 @@
<outlet property="imageEndToEndEncryption" destination="S7m-5Z-ktw" id="0Pv-Yt-YJB"/>
<outlet property="imageExternalSite" destination="JWO-C0-32L" id="JKi-n1-5IQ"/>
<outlet property="imageFileSharing" destination="G9c-Nd-Ikl" id="Wha-2g-8o0"/>
+ <outlet property="imageLockFile" destination="eAC-Li-gKO" id="hHH-Pl-uOW"/>
<outlet property="imageNotification" destination="cgb-3g-trc" id="fa5-99-76C"/>
<outlet property="imageOnlyOffice" destination="xvv-h0-9bM" id="tw2-is-KHy"/>
<outlet property="imageText" destination="iCB-2A-phO" id="uit-Ku-oOF"/>
@@ -590,6 +633,7 @@
<outlet property="statusEndToEndEncryption" destination="M82-8U-M4Q" id="S9e-h3-GpF"/>
<outlet property="statusExternalSite" destination="ivv-te-kaP" id="qzS-eo-Dq3"/>
<outlet property="statusFileSharing" destination="SbT-rU-lJ8" id="zqA-0V-TLr"/>
+ <outlet property="statusLockFile" destination="db5-st-O6M" id="dRt-zm-Qd7"/>
<outlet property="statusNotification" destination="WAg-Hw-sQS" id="T5C-Ch-11o"/>
<outlet property="statusOnlyOffice" destination="ucV-YG-5ht" id="11e-La-p9K"/>
<outlet property="statusText" destination="uiz-H8-p3D" id="wLb-D2-MNS"/>
@@ -626,7 +670,7 @@
<image name="comments" width="425" height="425"/>
<image name="delete" width="425" height="425"/>
<image name="externalsites" width="425" height="425"/>
- <image name="home" width="425" height="425"/>
+ <image name="home" width="120" height="120"/>
<image name="lock" width="24" height="24"/>
<image name="notification" width="512" height="512"/>
<image name="onlyoffice" width="425" height="425"/>
diff --git a/iOSClient/Diagnostics/NCCapabilitiesViewController.swift b/iOSClient/Diagnostics/NCCapabilitiesViewController.swift
index c8d4ada34..6078ffa28 100644
--- a/iOSClient/Diagnostics/NCCapabilitiesViewController.swift
+++ b/iOSClient/Diagnostics/NCCapabilitiesViewController.swift
@@ -64,6 +64,9 @@ class NCCapabilitiesViewController: UIViewController, UIDocumentInteractionContr
@IBOutlet weak var homeImage: UIImageView!
@IBOutlet weak var homeServer: UILabel!
+ @IBOutlet weak var imageLockFile: UIImageView!
+ @IBOutlet weak var statusLockFile: UILabel!
+
private let appDelegate = UIApplication.shared.delegate as! AppDelegate
private var documentController: UIDocumentInteractionController?
private var account: String = ""
@@ -139,6 +142,11 @@ class NCCapabilitiesViewController: UIViewController, UIDocumentInteractionContr
statusComments.layer.borderColor = UIColor.gray.cgColor
statusComments.layer.masksToBounds = true
+ statusLockFile.layer.cornerRadius = 12.5
+ statusLockFile.layer.borderWidth = 0.5
+ statusLockFile.layer.borderColor = UIColor.gray.cgColor
+ statusLockFile.layer.masksToBounds = true
+
imageFileSharing.image = UIImage(named: "share")!.image(color: NCBrandColor.shared.gray, size: 50)
imageExternalSite.image = NCUtility.shared.loadImage(named: "network", color: NCBrandColor.shared.gray)
imageEndToEndEncryption.image = NCUtility.shared.loadImage(named: "lock", color: NCBrandColor.shared.gray)
@@ -150,6 +158,7 @@ class NCCapabilitiesViewController: UIViewController, UIDocumentInteractionContr
imageOnlyOffice.image = UIImage(named: "onlyoffice")!.image(color: NCBrandColor.shared.gray, size: 50)
imageUserStatus.image = UIImage(named: "userStatusAway")!.image(color: NCBrandColor.shared.gray, size: 50)
imageComments.image = UIImage(named: "comments")!.image(color: NCBrandColor.shared.gray, size: 50)
+ imageLockFile.image = UIImage(named: "lock")!.image(color: NCBrandColor.shared.gray, size: 50)
guard let activeAccount = NCManageDatabase.shared.getActiveAccount() else { return }
self.account = activeAccount.account
@@ -315,6 +324,13 @@ class NCCapabilitiesViewController: UIViewController, UIDocumentInteractionContr
statusComments.text = NSLocalizedString("_not_available_", comment: "")
}
+ let hasLockCapability = NCManageDatabase.shared.getCapabilitiesServerInt(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesFilesLockVersion) >= 1
+ if hasLockCapability {
+ statusLockFile.text = "✓ " + NSLocalizedString("_available_", comment: "")
+ } else {
+ statusLockFile.text = NSLocalizedString("_not_available_", comment: "")
+ }
+
print("end.")
}
}
diff --git a/iOSClient/Extensions/DateFormatter+Extension.swift b/iOSClient/Extensions/DateFormatter+Extension.swift
new file mode 100644
index 000000000..aa126ce78
--- /dev/null
+++ b/iOSClient/Extensions/DateFormatter+Extension.swift
@@ -0,0 +1,33 @@
+//
+// DateFormatter+Extension.swift
+// Nextcloud
+//
+// Created by Henrik Storch on 18.03.22.
+// Copyright © 2022 Henrik Storch. All rights reserved.
+//
+// Author Henrik Storch <henrik.storch@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 DateFormatter {
+ static let shareExpDate: DateFormatter = {
+ let dateFormatter = DateFormatter()
+ dateFormatter.formatterBehavior = .behavior10_4
+ dateFormatter.dateStyle = .medium
+ return dateFormatter
+ }()
+}
diff --git a/iOSClient/Extensions/String+Extensions.swift b/iOSClient/Extensions/String+Extensions.swift
index 40bd244af..f30751ed7 100644
--- a/iOSClient/Extensions/String+Extensions.swift
+++ b/iOSClient/Extensions/String+Extensions.swift
@@ -26,6 +26,11 @@ import UIKit
import CommonCrypto
extension String {
+
+ var alphanumeric: String {
+ return self.components(separatedBy: CharacterSet.alphanumerics.inverted).joined().lowercased()
+ }
+
public var uppercaseInitials: String? {
let initials = self.components(separatedBy: .whitespaces)
.reduce("", {
@@ -49,7 +54,7 @@ extension String {
//https://stackoverflow.com/a/32166735/9506784
let length = Int(CC_MD5_DIGEST_LENGTH)
- let messageData = self.data(using: .utf8)!
+ let messageData = self.data(using: .utf8) ?? Data()
var digestData = Data(count: length)
_ = digestData.withUnsafeMutableBytes { digestBytes -> UInt8 in
diff --git a/iOSClient/Extensions/UIAlertController+Extension.swift b/iOSClient/Extensions/UIAlertController+Extension.swift
new file mode 100644
index 000000000..90a55c09d
--- /dev/null
+++ b/iOSClient/Extensions/UIAlertController+Extension.swift
@@ -0,0 +1,91 @@
+//
+// UIAlertController+Extension.swift
+// Nextcloud
+//
+// Created by Henrik Storch on 27.01.22.
+// Copyright © 2022 Henrik Storch. All rights reserved.
+//
+// Author Henrik Storch <henrik.storch@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
+
+extension UIAlertController {
+ /// Creates a alert controller with a textfield, asking to create a new folder
+ /// - Parameters:
+ /// - serverUrl: Server url of the location where the folder should be created
+ /// - urlBase: UrlBase object
+ /// - completion: If not` nil` it overrides the default behavior which shows an error using `NCContentPresenter`
+ /// - Returns: The presentable alert controller
+ static func createFolder(serverUrl: String, urlBase: NCUserBaseUrl, completion: ((_ errorCode: Int, _ errorDescription: String) -> Void)? = nil) -> UIAlertController {
+ let alertController = UIAlertController(title: NSLocalizedString("_create_folder_", comment: ""), message: nil, preferredStyle: .alert)
+
+ let okAction = UIAlertAction(title: NSLocalizedString("_save_", comment: ""), style: .default, handler: { _ in
+ guard let fileNameFolder = alertController.textFields?.first?.text else { return }
+ NCNetworking.shared.createFolder(fileName: fileNameFolder, serverUrl: serverUrl, account: urlBase.account, urlBase: urlBase.urlBase, overwrite: false) { errorCode, errorDescription in
+ if let completion = completion {
+ completion(errorCode, errorDescription)
+ } else if errorCode != 0 {
+ NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+ } // else: successful, no action
+ }
+ })
+
+ // text field is initially empty, no action
+ okAction.isEnabled = false
+ let cancelAction = UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel)
+
+ alertController.addTextField { textField in
+ textField.autocapitalizationType = .words
+ }
+
+ // only allow saving if folder name exists
+ NotificationCenter.default.addObserver(
+ forName: UITextField.textDidChangeNotification,
+ object: alertController.textFields?.first,
+ queue: .main) { _ in
+ guard let text = alertController.textFields?.first?.text,
+ let folderName = CCUtility.removeForbiddenCharactersServer(text)?.trimmingCharacters(in: .whitespaces) else { return }
+ okAction.isEnabled = !folderName.isEmpty && folderName != "." && folderName != ".."
+ }
+
+ alertController.addAction(cancelAction)
+ alertController.addAction(okAction)
+ return alertController
+ }
+
+ static func withTextField(titleKey: String, textFieldConfiguration: ((UITextField) -> Void)?, completion: @escaping (String?) -> Void) -> UIAlertController {
+ let alertController = UIAlertController(title: NSLocalizedString(titleKey, comment: ""), message: "", preferredStyle: .alert)
+ alertController.addTextField { textField in
+ textFieldConfiguration?(textField)
+ }
+ alertController.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .default) { _ in })
+ let okAction = UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default) { _ in
+ completion(alertController.textFields?.first?.text)
+ }
+
+ alertController.addAction(okAction)
+ return alertController
+ }
+
+ static func password(titleKey: String, completion: @escaping (String?) -> Void) -> UIAlertController {
+ return .withTextField(titleKey: titleKey, textFieldConfiguration: { textField in
+ textField.isSecureTextEntry = true
+ textField.placeholder = NSLocalizedString("_password_", comment: "")
+ }, completion: completion)
+
+ }
+}
diff --git a/iOSClient/Extensions/UIApplication+Orientation.swift b/iOSClient/Extensions/UIApplication+Orientation.swift
index d49c72e88..aa3f1528b 100644
--- a/iOSClient/Extensions/UIApplication+Orientation.swift
+++ b/iOSClient/Extensions/UIApplication+Orientation.swift
@@ -20,7 +20,7 @@
// 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
extension UIApplication {
// indicates if current device is in landscape orientation
diff --git a/iOSClient/Extensions/UIDevice+Extensions.swift b/iOSClient/Extensions/UIDevice+Extensions.swift
new file mode 100644
index 000000000..07305585e
--- /dev/null
+++ b/iOSClient/Extensions/UIDevice+Extensions.swift
@@ -0,0 +1,37 @@
+//
+// UIDevice+Extensions.swift
+// Nextcloud
+//
+// Created by Federico Malagoni on 23/02/22.
+// Copyright © 2022 Federico Malagoni. All rights reserved.
+//
+// Author Federico Malagoni <federico.malagoni@astrairidium.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 UIDevice {
+
+ var hasNotch: Bool {
+ if #available(iOS 11.0, *) {
+ if UIApplication.shared.windows.isEmpty { return false }
+ let top = UIApplication.shared.windows[0].safeAreaInsets.top
+ return top > 20
+ } else {
+ // Fallback on earlier versions
+ return false
+ }
+ }
+}
diff --git a/iOSClient/Extensions/UIFont+Extension.swift b/iOSClient/Extensions/UIFont+Extension.swift
new file mode 100644
index 000000000..42e5b9529
--- /dev/null
+++ b/iOSClient/Extensions/UIFont+Extension.swift
@@ -0,0 +1,31 @@
+//
+// UIFont+Extensions.swift
+// Nextcloud
+//
+// Created by Federico Malagoni on 23/02/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 UIKit
+
+extension UIFont {
+
+ static func incosolataMedium(size: CGFloat) -> UIFont {
+ return UIFont(name: "Inconsolata-Medium", size: size)!
+ }
+}
diff --git a/iOSClient/Extensions/UIToolbar+Extension.swift b/iOSClient/Extensions/UIToolbar+Extension.swift
new file mode 100644
index 000000000..983c4d7b3
--- /dev/null
+++ b/iOSClient/Extensions/UIToolbar+Extension.swift
@@ -0,0 +1,77 @@
+//
+// UIToolbar+Extension.swift
+// Nextcloud
+//
+// Created by Henrik Storch on 18.03.22.
+// Copyright © 2022 Henrik Storch. All rights reserved.
+//
+// Author Henrik Storch <henrik.storch@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
+
+extension UIToolbar {
+ static func toolbar(onClear: (() -> Void)?, completion: @escaping () -> Void) -> UIToolbar {
+ let toolbar = UIToolbar()
+ toolbar.sizeToFit()
+ var buttons: [UIBarButtonItem] = []
+
+ if let onClear = onClear {
+ let clearButton = UIBarButtonItem(title: NSLocalizedString("_clear_", comment: ""), style: .plain) {
+ onClear()
+ }
+ buttons.append(clearButton)
+ }
+ buttons.append(UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil))
+ let doneButton = UIBarButtonItem(title: NSLocalizedString("_done_", comment: ""), style: .done) {
+ completion()
+ }
+ buttons.append(doneButton)
+ toolbar.setItems(buttons, animated: false)
+ return toolbar
+ }
+
+ // by default inputAccessoryView does not respect safeArea
+ var wrappedSafeAreaContainer: UIView {
+ let view = InputBarWrapper()
+ view.addSubview(self)
+ self.translatesAutoresizingMaskIntoConstraints = false
+ NSLayoutConstraint.activate([
+ self.topAnchor.constraint(equalTo: view.topAnchor),
+ self.leftAnchor.constraint(equalTo: view.leftAnchor),
+ self.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
+ self.rightAnchor.constraint(equalTo: view.rightAnchor)
+ ])
+ return view
+ }
+}
+
+// https://stackoverflow.com/a/67985180/9506784
+class InputBarWrapper: UIView {
+
+ var desiredHeight: CGFloat = 0 {
+ didSet { invalidateIntrinsicContentSize() }
+ }
+
+ override var intrinsicContentSize: CGSize { CGSize(width: 0, height: desiredHeight) }
+
+ required init?(coder aDecoder: NSCoder) { fatalError() }
+
+ override init(frame: CGRect) {
+ super.init(frame: frame)
+ autoresizingMask = .flexibleHeight
+ }
+}
diff --git a/iOSClient/Font/Inconsolata/Inconsolata-Black.ttf b/iOSClient/Font/Inconsolata/Inconsolata-Black.ttf
new file mode 100644
index 000000000..45f991721
--- /dev/null
+++ b/iOSClient/Font/Inconsolata/Inconsolata-Black.ttf
Binary files differ
diff --git a/iOSClient/Font/Inconsolata/Inconsolata-Bold.ttf b/iOSClient/Font/Inconsolata/Inconsolata-Bold.ttf
new file mode 100644
index 000000000..9f9272588
--- /dev/null
+++ b/iOSClient/Font/Inconsolata/Inconsolata-Bold.ttf
Binary files differ
diff --git a/iOSClient/Font/Inconsolata/Inconsolata-ExtraBold.ttf b/iOSClient/Font/Inconsolata/Inconsolata-ExtraBold.ttf
new file mode 100644
index 000000000..ceefce0ee
--- /dev/null
+++ b/iOSClient/Font/Inconsolata/Inconsolata-ExtraBold.ttf
Binary files differ
diff --git a/iOSClient/Font/Inconsolata/Inconsolata-ExtraLight.ttf b/iOSClient/Font/Inconsolata/Inconsolata-ExtraLight.ttf
new file mode 100644
index 000000000..8a4abb844
--- /dev/null
+++ b/iOSClient/Font/Inconsolata/Inconsolata-ExtraLight.ttf
Binary files differ
diff --git a/iOSClient/Font/Inconsolata/Inconsolata-Light.ttf b/iOSClient/Font/Inconsolata/Inconsolata-Light.ttf
new file mode 100644
index 000000000..2ce184299
--- /dev/null
+++ b/iOSClient/Font/Inconsolata/Inconsolata-Light.ttf
Binary files differ
diff --git a/iOSClient/Font/Inconsolata/Inconsolata-Medium.ttf b/iOSClient/Font/Inconsolata/Inconsolata-Medium.ttf
new file mode 100644
index 000000000..364328355
--- /dev/null
+++ b/iOSClient/Font/Inconsolata/Inconsolata-Medium.ttf
Binary files differ
diff --git a/iOSClient/Font/Inconsolata/Inconsolata-Regular.ttf b/iOSClient/Font/Inconsolata/Inconsolata-Regular.ttf
new file mode 100644
index 000000000..457d262cf
--- /dev/null
+++ b/iOSClient/Font/Inconsolata/Inconsolata-Regular.ttf
Binary files differ
diff --git a/iOSClient/Font/Inconsolata/Inconsolata-SemiBold.ttf b/iOSClient/Font/Inconsolata/Inconsolata-SemiBold.ttf
new file mode 100644
index 000000000..f6a0d18fa
--- /dev/null
+++ b/iOSClient/Font/Inconsolata/Inconsolata-SemiBold.ttf
Binary files differ
diff --git a/iOSClient/Images.xcassets/pdf-vertical.imageset/Contents.json b/iOSClient/Images.xcassets/captions.bubble.imageset/Contents.json
index 580932404..f17a1e2e0 100644
--- a/iOSClient/Images.xcassets/pdf-vertical.imageset/Contents.json
+++ b/iOSClient/Images.xcassets/captions.bubble.imageset/Contents.json
@@ -1,7 +1,7 @@
{
"images" : [
{
- "filename" : "swap-vertical-variant.svg",
+ "filename" : "subtitles-outline.svg",
"idiom" : "universal"
}
],
diff --git a/iOSClient/Images.xcassets/pdf-horizontal.imageset/swap-horizontal-variant.svg b/iOSClient/Images.xcassets/captions.bubble.imageset/subtitles-outline.svg
index b77ae3826..69a07d483 100644
--- a/iOSClient/Images.xcassets/pdf-horizontal.imageset/swap-horizontal-variant.svg
+++ b/iOSClient/Images.xcassets/captions.bubble.imageset/subtitles-outline.svg
@@ -1 +1 @@
-<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M4,6L8,10V7H16A2,2 0 0,1 18,9A2,2 0 0,1 16,11H8A4,4 0 0,0 4,15A4,4 0 0,0 8,19H16V22L20,18L16,14V17H8A2,2 0 0,1 6,15A2,2 0 0,1 8,13H16A4,4 0 0,0 20,9A4,4 0 0,0 16,5H8V2L4,6Z" /></svg> \ No newline at end of file
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M20,4A2,2 0 0,1 22,6V18A2,2 0 0,1 20,20H4A2,2 0 0,1 2,18V6A2,2 0 0,1 4,4H20M20,18V6H4V18H20M6,10H8V12H6V10M6,14H14V16H6V14M16,14H18V16H16V14M10,10H18V12H10V10Z" /></svg> \ No newline at end of file
diff --git a/iOSClient/Images.xcassets/circle.fill.imageset/Contents.json b/iOSClient/Images.xcassets/circle_fill.imageset/Contents.json
index b73baca81..b73baca81 100644
--- a/iOSClient/Images.xcassets/circle.fill.imageset/Contents.json
+++ b/iOSClient/Images.xcassets/circle_fill.imageset/Contents.json
diff --git a/iOSClient/Images.xcassets/circle.fill.imageset/circle.pdf b/iOSClient/Images.xcassets/circle_fill.imageset/circle.pdf
index 4be68b831..4be68b831 100644
--- a/iOSClient/Images.xcassets/circle.fill.imageset/circle.pdf
+++ b/iOSClient/Images.xcassets/circle_fill.imageset/circle.pdf
Binary files differ
diff --git a/iOSClient/Images.xcassets/closeVideo.imageset/Contents.json b/iOSClient/Images.xcassets/closeVideo.imageset/Contents.json
deleted file mode 100644
index 27c37246d..000000000
--- a/iOSClient/Images.xcassets/closeVideo.imageset/Contents.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "images" : [
- {
- "filename" : "closeVideo.pdf",
- "idiom" : "universal"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- },
- "properties" : {
- "preserves-vector-representation" : true
- }
-}
diff --git a/iOSClient/Images.xcassets/closeVideo.imageset/closeVideo.pdf b/iOSClient/Images.xcassets/closeVideo.imageset/closeVideo.pdf
deleted file mode 100644
index dd2befdd9..000000000
--- a/iOSClient/Images.xcassets/closeVideo.imageset/closeVideo.pdf
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/edit.imageset/Contents.json b/iOSClient/Images.xcassets/edit.imageset/Contents.json
deleted file mode 100644
index 8c2130e77..000000000
--- a/iOSClient/Images.xcassets/edit.imageset/Contents.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "filename" : "edit.pdf"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- },
- "properties" : {
- "preserves-vector-representation" : true
- }
-} \ No newline at end of file
diff --git a/iOSClient/Images.xcassets/edit.imageset/edit.pdf b/iOSClient/Images.xcassets/edit.imageset/edit.pdf
deleted file mode 100644
index fd83883ab..000000000
--- a/iOSClient/Images.xcassets/edit.imageset/edit.pdf
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/userStatusOnline.imageset/Contents.json b/iOSClient/Images.xcassets/eye.imageset/Contents.json
index 9f25229ad..704cf79b5 100644
--- a/iOSClient/Images.xcassets/userStatusOnline.imageset/Contents.json
+++ b/iOSClient/Images.xcassets/eye.imageset/Contents.json
@@ -1,7 +1,7 @@
{
"images" : [
{
- "filename" : "online.pdf",
+ "filename" : "eye.svg",
"idiom" : "universal"
}
],
diff --git a/iOSClient/Images.xcassets/eye.imageset/eye.svg b/iOSClient/Images.xcassets/eye.imageset/eye.svg
new file mode 100644
index 000000000..b1459db41
--- /dev/null
+++ b/iOSClient/Images.xcassets/eye.imageset/eye.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 15.06"><path d="M12.004 15.06q1.774 0 3.351-.426 1.576-.425 2.911-1.124 1.334-.698 2.393-1.541 1.058-.843 1.804-1.69.747-.848 1.142-1.572Q24 7.982 24 7.535q0-.448-.395-1.173-.395-.724-1.142-1.572-.746-.847-1.804-1.69-1.059-.843-2.398-1.541Q16.922.861 15.346.435 13.769.009 12.004.009q-1.747 0-3.315.426-1.567.426-2.906 1.124-1.34.698-2.406 1.541-1.067.843-1.823 1.69Q.799 5.638.4 6.362 0 7.087 0 7.535q0 .447.4 1.172.399.724 1.154 1.572.756.847 1.818 1.69 1.063.843 2.402 1.541 1.339.699 2.907 1.124 1.567.426 3.323.426Zm0-1.387q-1.449 0-2.783-.36-1.335-.36-2.503-.953-1.168-.593-2.116-1.295-.949-.703-1.638-1.392-.69-.689-1.058-1.26-.369-.571-.369-.878 0-.264.369-.808.368-.545 1.058-1.243.689-.698 1.638-1.409.948-.712 2.116-1.322 1.168-.61 2.503-.984 1.334-.373 2.783-.373 1.441 0 2.771.373 1.33.374 2.498.984 1.168.61 2.121 1.322.953.711 1.638 1.409.685.698 1.058 1.243.373.544.373.808 0 .307-.373.878t-1.058 1.26q-.685.689-1.638 1.392-.953.702-2.121 1.295-1.168.593-2.498.953-1.33.36-2.771.36Zm0-1.221q1.019 0 1.915-.386.895-.387 1.572-1.067.676-.681 1.058-1.572t.382-1.892q0-1.028-.382-1.924-.382-.895-1.058-1.567-.677-.672-1.572-1.049-.896-.378-1.915-.378-1.036 0-1.932.378-.895.377-1.571 1.049-.677.672-1.059 1.567-.382.896-.382 1.924.009 1.001.391 1.892t1.058 1.572q.676.68 1.568 1.067.891.386 1.927.386Zm0-3.284q-.685 0-1.168-.483-.483-.483-.483-1.15 0-.677.483-1.155.483-.479 1.168-.479.677 0 1.16.479.483.478.483 1.155 0 .667-.483 1.15-.483.483-1.16.483Z"/></svg> \ No newline at end of file
diff --git a/iOSClient/Images.xcassets/lock.open.imageset/Contents.json b/iOSClient/Images.xcassets/lock_open.imageset/Contents.json
index d6fb0c7a0..d6fb0c7a0 100644
--- a/iOSClient/Images.xcassets/lock.open.imageset/Contents.json
+++ b/iOSClient/Images.xcassets/lock_open.imageset/Contents.json
diff --git a/iOSClient/Images.xcassets/lock.open.imageset/lock-open-variant-outline.svg b/iOSClient/Images.xcassets/lock_open.imageset/lock-open-variant-outline.svg
index d1e4c56ff..d1e4c56ff 100644
--- a/iOSClient/Images.xcassets/lock.open.imageset/lock-open-variant-outline.svg
+++ b/iOSClient/Images.xcassets/lock_open.imageset/lock-open-variant-outline.svg
diff --git a/iOSClient/Images.xcassets/pdf-horizontal.imageset/Contents.json b/iOSClient/Images.xcassets/moreLock.imageset/Contents.json
index 9a580cc28..194258945 100644
--- a/iOSClient/Images.xcassets/pdf-horizontal.imageset/Contents.json
+++ b/iOSClient/Images.xcassets/moreLock.imageset/Contents.json
@@ -1,7 +1,7 @@
{
"images" : [
{
- "filename" : "swap-horizontal-variant.svg",
+ "filename" : "menu-locked-filled.svg",
"idiom" : "universal"
}
],
diff --git a/iOSClient/Images.xcassets/moreLock.imageset/menu-locked-filled.svg b/iOSClient/Images.xcassets/moreLock.imageset/menu-locked-filled.svg
new file mode 100644
index 000000000..19be22ed7
--- /dev/null
+++ b/iOSClient/Images.xcassets/moreLock.imageset/menu-locked-filled.svg
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ version="1.1"
+ width="24"
+ height="24"
+ viewBox="0 0 24 24"
+ id="svg4"
+ sodipodi:docname="locked-filled.svg"
+ inkscape:version="1.1.2 (1:1.1+202202050950+0a00cf5339)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs8">
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath839">
+ <path
+ d="M 0,0 H 1770.8333 V 1770.8333 H 0 Z"
+ clip-rule="evenodd"
+ id="path837" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath839-3">
+ <path
+ d="M 0,0 H 1770.8333 V 1770.8333 H 0 Z"
+ clip-rule="evenodd"
+ id="path837-6" />
+ </clipPath>
+ </defs>
+ <sodipodi:namedview
+ id="namedview6"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ showgrid="false"
+ inkscape:zoom="17"
+ inkscape:cx="9.7941176"
+ inkscape:cy="9.4117647"
+ inkscape:window-width="1920"
+ inkscape:window-height="1046"
+ inkscape:window-x="0"
+ inkscape:window-y="34"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg4" />
+ <path
+ d="m 15.75,6.375 c 0.690625,0 1.25,0.559375 1.25,1.25 v 6.25 c 0,0.690625 -0.559375,1.25 -1.25,1.25 H 8.25 C 7.55625,15.125 7,14.5625 7,13.875 V 7.625 C 7,6.93125 7.55625,6.375 8.25,6.375 H 8.875 V 5.125 C 8.875,3.399375 10.274375,2 12,2 c 1.725625,0 3.125,1.399375 3.125,3.125 v 1.25 H 15.75 M 12,3.25 c -1.035625,0 -1.875,0.839375 -1.875,1.875 v 1.25 h 3.75 V 5.125 C 13.875,4.089375 13.035625,3.25 12,3.25 Z"
+ id="path2"
+ style="stroke-width:0.625"
+ sodipodi:nodetypes="cssssssscsssccssccss" />
+ <g
+ id="g833"
+ transform="matrix(0.01355297,0,0,0.01355297,-8.4406855e-6,6.9999789)">
+ <g
+ id="g835"
+ clip-path="url(#clipPath839-3)">
+ <g
+ id="g841"
+ transform="scale(73.784721)">
+ <path
+ d="m 16,12 c 0,-0.0655 0.0032,-0.130847 0.0096,-0.196034 0.0064,-0.06519 0.01602,-0.129902 0.0288,-0.194147 0.01278,-0.06424 0.02868,-0.127705 0.04769,-0.190387 0.01901,-0.06268 0.04106,-0.124281 0.06612,-0.184798 0.02507,-0.06052 0.05304,-0.119658 0.08392,-0.177426 0.03088,-0.05777 0.06451,-0.113885 0.100903,-0.168348 0.03639,-0.05446 0.07536,-0.107011 0.116917,-0.157645 0.04155,-0.05063 0.08549,-0.09911 0.131809,-0.145428 0.04632,-0.04632 0.09479,-0.09025 0.145426,-0.131807 0.05063,-0.04155 0.103183,-0.08053 0.157646,-0.116919 0.05446,-0.03639 0.11058,-0.07003 0.168348,-0.100903 0.05777,-0.03088 0.116909,-0.05885 0.177425,-0.08392 0.06052,-0.02507 0.122118,-0.04711 0.1848,-0.06612 0.06268,-0.01902 0.126144,-0.03491 0.190387,-0.04769 0.06425,-0.01278 0.12896,-0.02238 0.194148,-0.0288 C 17.869154,10.003211 17.9345,10.000001 18,10 c 0.0655,10e-7 0.130848,0.0032 0.196033,0.0096 0.06519,0.0064 0.129904,0.01602 0.194148,0.0288 0.06425,0.01278 0.127708,0.02868 0.190389,0.04769 0.06268,0.01901 0.124281,0.04105 0.184796,0.06612 0.06052,0.02507 0.119659,0.05304 0.177427,0.08392 0.05777,0.03088 0.113882,0.06451 0.168346,0.100903 0.05446,0.03639 0.107016,0.07536 0.15765,0.116919 0.05063,0.04155 0.09911,0.08549 0.145424,0.131807 0.04632,0.04632 0.09025,0.09479 0.131806,0.145428 0.04155,0.05063 0.08053,0.103181 0.116916,0.157644 0.03639,0.05446 0.07003,0.110579 0.100905,0.168348 0.03088,0.05777 0.05885,0.11691 0.08392,0.177425 0.02507,0.06052 0.04711,0.122116 0.06612,0.184798 0.01901,0.06268 0.03491,0.126145 0.04769,0.190389 0.01278,0.06424 0.02238,0.12896 0.0288,0.194148 0.0064,0.06519 0.0096,0.130532 0.0096,0.196034 2e-6,0.0655 -0.0032,0.130848 -0.0096,0.196034 -0.0064,0.06519 -0.01602,0.129903 -0.0288,0.194146 -0.01278,0.06424 -0.02867,0.127707 -0.04769,0.190389 -0.01901,0.06268 -0.04105,0.12428 -0.06612,0.184796 -0.02506,0.06052 -0.05304,0.119658 -0.08392,0.177427 -0.03088,0.05777 -0.06451,0.113884 -0.100903,0.168346 -0.03639,0.05446 -0.07536,0.107013 -0.116918,0.157647 -0.04155,0.05063 -0.08549,0.09911 -0.131806,0.145427 -0.04632,0.04632 -0.09479,0.09025 -0.145426,0.131808 -0.05063,0.04155 -0.103183,0.08053 -0.157648,0.116918 -0.05446,0.03639 -0.110578,0.07003 -0.168346,0.100905 -0.05777,0.03088 -0.116909,0.05885 -0.177427,0.08391 -0.06051,0.02507 -0.122115,0.04711 -0.184796,0.06612 -0.06268,0.01902 -0.126144,0.03491 -0.190389,0.04769 -0.06424,0.01278 -0.12896,0.02238 -0.194148,0.0288 -0.06518,0.0064 -0.130529,0.0096 -0.196033,0.0096 -0.0655,0 -0.130846,-0.0032 -0.196033,-0.0096 -0.06519,-0.0064 -0.129904,-0.01602 -0.194149,-0.0288 -0.06424,-0.01278 -0.127707,-0.02867 -0.19039,-0.04769 -0.06268,-0.01901 -0.124281,-0.04105 -0.184797,-0.06612 -0.06052,-0.02507 -0.119658,-0.05304 -0.177426,-0.08392 -0.05777,-0.03088 -0.113886,-0.06451 -0.168348,-0.100905 -0.05446,-0.03639 -0.107012,-0.07536 -0.157646,-0.116917 -0.05063,-0.04155 -0.09911,-0.08549 -0.145424,-0.131808 -0.04632,-0.04632 -0.09025,-0.09479 -0.131809,-0.145427 -0.04155,-0.05063 -0.08053,-0.103183 -0.116919,-0.157647 -0.03639,-0.05446 -0.07003,-0.110578 -0.100903,-0.168346 -0.03088,-0.05777 -0.05885,-0.11691 -0.08392,-0.177427 -0.02507,-0.06052 -0.04711,-0.122115 -0.06612,-0.184797 -0.01901,-0.06268 -0.03491,-0.126145 -0.04769,-0.190389 -0.01278,-0.06424 -0.02238,-0.128958 -0.0288,-0.194146 C 16.00321,12.130848 16,12.065503 16,12 m -6,0 c 10e-7,-0.0655 0.0032,-0.130847 0.0096,-0.196034 0.0064,-0.06519 0.01602,-0.129902 0.0288,-0.194147 0.01278,-0.06424 0.02868,-0.127705 0.04769,-0.190387 0.01901,-0.06268 0.04105,-0.124281 0.06612,-0.184798 0.02507,-0.06052 0.05304,-0.119658 0.08392,-0.177426 0.03088,-0.05777 0.06451,-0.113885 0.100904,-0.168348 0.03639,-0.05446 0.07536,-0.107011 0.116919,-0.157645 0.04156,-0.05063 0.08549,-0.09911 0.131807,-0.145428 0.04632,-0.04632 0.09479,-0.09025 0.145427,-0.131807 0.05063,-0.04155 0.103182,-0.08053 0.157646,-0.116919 0.05446,-0.03639 0.110579,-0.07003 0.168348,-0.100903 0.05777,-0.03088 0.11691,-0.05885 0.177426,-0.08392 0.06052,-0.02507 0.122116,-0.04711 0.184798,-0.06612 0.06268,-0.01902 0.126144,-0.03491 0.190387,-0.04769 0.06424,-0.01278 0.12896,-0.02238 0.194147,-0.0288 0.06519,-0.0064 0.130532,-0.0096 0.196034,-0.0096 0.0655,10e-7 0.130848,0.0032 0.196034,0.0096 0.06519,0.0064 0.129903,0.01602 0.194146,0.0288 0.06424,0.01278 0.127707,0.02868 0.190389,0.04769 0.06268,0.01901 0.12428,0.04105 0.184796,0.06612 0.06052,0.02507 0.119658,0.05304 0.177427,0.08392 0.05777,0.03088 0.113884,0.06451 0.168346,0.100903 0.05446,0.03639 0.107013,0.07536 0.157647,0.116919 0.05063,0.04155 0.09911,0.08549 0.145427,0.131807 0.04632,0.04632 0.09025,0.09479 0.131808,0.145428 0.04155,0.05063 0.08053,0.103181 0.116918,0.157644 0.03639,0.05446 0.07003,0.110579 0.100905,0.168348 0.03088,0.05777 0.05885,0.11691 0.08391,0.177425 0.02507,0.06052 0.04711,0.122116 0.06612,0.184798 0.01902,0.06268 0.03491,0.126145 0.04769,0.190389 0.01278,0.06424 0.02238,0.12896 0.0288,0.194148 0.0064,0.06519 0.0096,0.130532 0.0096,0.196034 -10e-7,0.0655 -0.0032,0.130848 -0.0096,0.196034 -0.0064,0.06519 -0.01602,0.129903 -0.0288,0.194146 -0.01278,0.06424 -0.02867,0.127707 -0.04769,0.190389 -0.01901,0.06268 -0.04105,0.12428 -0.06612,0.184796 -0.02507,0.06052 -0.05304,0.119658 -0.08391,0.177427 -0.03088,0.05777 -0.06451,0.113884 -0.100905,0.168346 -0.03639,0.05446 -0.07536,0.107013 -0.116917,0.157647 -0.04156,0.05063 -0.08549,0.09911 -0.131808,0.145427 -0.04632,0.04632 -0.09479,0.09025 -0.145427,0.131808 -0.05063,0.04155 -0.103183,0.08053 -0.157647,0.116918 -0.05446,0.03639 -0.110577,0.07003 -0.168346,0.100905 -0.05777,0.03088 -0.116911,0.05885 -0.177427,0.08391 -0.06052,0.02507 -0.122115,0.04711 -0.184797,0.06612 -0.06268,0.01902 -0.126144,0.03491 -0.190388,0.04769 -0.06424,0.01278 -0.128958,0.02238 -0.194146,0.0288 -0.06519,0.0064 -0.130531,0.0096 -0.196034,0.0096 -0.0655,0 -0.130847,-0.0032 -0.196034,-0.0096 -0.06519,-0.0064 -0.129903,-0.01602 -0.194148,-0.0288 -0.06424,-0.01278 -0.127707,-0.02867 -0.190389,-0.04769 -0.06268,-0.01901 -0.124281,-0.04105 -0.184798,-0.06612 -0.06052,-0.02507 -0.119658,-0.05304 -0.177425,-0.08392 -0.05777,-0.03088 -0.113885,-0.06451 -0.168348,-0.100905 -0.05446,-0.03639 -0.107011,-0.07536 -0.157644,-0.116917 -0.05063,-0.04155 -0.09911,-0.08549 -0.145428,-0.131808 -0.04632,-0.04632 -0.09025,-0.09479 -0.131807,-0.145427 -0.04156,-0.05063 -0.08053,-0.103183 -0.11692,-0.157647 -0.03639,-0.05446 -0.07002,-0.110578 -0.100902,-0.168346 -0.03088,-0.05777 -0.05885,-0.11691 -0.08392,-0.177427 -0.02507,-0.06052 -0.04711,-0.122115 -0.06612,-0.184797 -0.01901,-0.06268 -0.03491,-0.126145 -0.04769,-0.190389 -0.01278,-0.06424 -0.02238,-0.128958 -0.0288,-0.194146 C 10.003211,12.130848 10.000001,12.065503 10,12 m -6,0 c 0,-0.0655 0.00321,-0.130847 0.00963,-0.196034 0.00642,-0.06519 0.01602,-0.129902 0.028799,-0.194147 0.012779,-0.06424 0.028676,-0.127705 0.04769,-0.190387 0.019014,-0.06268 0.041055,-0.124281 0.066121,-0.184798 0.025067,-0.06052 0.053039,-0.119658 0.083917,-0.177426 0.030878,-0.05777 0.064512,-0.113885 0.1009026,-0.168348 0.036392,-0.05446 0.075365,-0.107011 0.116919,-0.157645 0.041554,-0.05063 0.08549,-0.09911 0.1318068,-0.145428 0.046318,-0.04632 0.094793,-0.09025 0.1454268,-0.131807 0.050634,-0.04155 0.1031833,-0.08053 0.1576462,-0.116919 0.054463,-0.03639 0.110579,-0.07003 0.1683473,-0.100903 0.057768,-0.03088 0.1169105,-0.05885 0.1774268,-0.08392 0.060516,-0.02507 0.1221157,-0.04711 0.1847973,-0.06612 0.062682,-0.01902 0.1261444,-0.03491 0.1903882,-0.04769 0.064244,-0.01278 0.1289597,-0.02238 0.1941467,-0.0288 C 5.869153,10.003211 5.9344978,10.000001 6,10 c 0.065503,10e-7 0.1308475,0.0032 0.1960344,0.0096 0.065186,0.0064 0.1299014,0.01602 0.1941452,0.0288 0.064244,0.01278 0.127707,0.02868 0.1903887,0.04769 0.062682,0.01901 0.1242809,0.04105 0.1847973,0.06612 0.060517,0.02507 0.1196589,0.05304 0.1774268,0.08392 0.057768,0.03088 0.1138845,0.06451 0.1683474,0.100903 0.054464,0.03639 0.1070127,0.07536 0.1576466,0.116919 0.050634,0.04155 0.09911,0.08549 0.1454268,0.131807 0.046317,0.04632 0.090253,0.09479 0.1318073,0.145428 0.041555,0.05063 0.080527,0.103181 0.1169181,0.157644 0.036391,0.05446 0.070026,0.110579 0.100904,0.168348 0.030878,0.05777 0.058849,0.11691 0.083916,0.177425 0.025067,0.06052 0.047108,0.122116 0.066122,0.184798 0.019014,0.06268 0.034911,0.126145 0.04769,0.190389 0.012779,0.06424 0.022379,0.12896 0.028799,0.194148 C 7.9967899,11.869153 8,11.934498 8,12 c 0,0.0655 -0.00321,0.130848 -0.00963,0.196034 -0.00642,0.06519 -0.016021,0.129903 -0.0288,0.194146 -0.012779,0.06424 -0.028675,0.127707 -0.04769,0.190389 -0.019014,0.06268 -0.041055,0.12428 -0.066122,0.184796 -0.025066,0.06052 -0.053039,0.119658 -0.083917,0.177427 -0.030878,0.05777 -0.064512,0.113884 -0.1009035,0.168346 -0.036391,0.05446 -0.075364,0.107013 -0.1169181,0.157647 -0.041554,0.05063 -0.08549,0.09911 -0.1318068,0.145427 -0.046317,0.04632 -0.094792,0.09025 -0.1454272,0.131808 -0.050634,0.04155 -0.1031828,0.08053 -0.1576467,0.116918 -0.054463,0.03639 -0.1105785,0.07003 -0.1683464,0.100905 -0.057768,0.03088 -0.11691,0.05885 -0.1774268,0.08391 -0.060516,0.02507 -0.1221152,0.04711 -0.1847973,0.06612 -0.062682,0.01902 -0.1261449,0.03491 -0.1903887,0.04769 -0.064244,0.01278 -0.1289592,0.02238 -0.1941457,0.0288 C 6.1308475,13.996789 6.0655026,13.999999 6,14 5.934498,14 5.869153,13.9968 5.803966,13.9904 5.738779,13.984 5.6740627,13.97438 5.6098189,13.9616 5.5455749,13.94882 5.4821124,13.93293 5.4194303,13.91391 5.3567483,13.8949 5.2951498,13.87286 5.234633,13.84779 5.174117,13.82272 5.1149745,13.79475 5.0572062,13.76387 4.9994382,13.73299 4.9433227,13.69936 4.8888593,13.662965 4.8343963,13.626575 4.7818475,13.587605 4.7312136,13.546048 4.6805796,13.504498 4.6321036,13.460558 4.5857863,13.41424 4.5394693,13.36792 4.4955333,13.31945 4.4539795,13.268813 4.4124245,13.218183 4.3734525,13.16563 4.3370605,13.111166 4.3006695,13.056706 4.2670355,13.000588 4.2361574,12.94282 4.2052794,12.88505 4.1773074,12.82591 4.1522404,12.765393 4.1271734,12.704873 4.1051334,12.643278 4.0861194,12.580596 4.0671044,12.517916 4.0512074,12.454451 4.0384294,12.390207 4.02565,12.325937 4.0160508,12.261222 4.0096302,12.196034 4.0032101,12.130848 4,12.065503 4,12 Z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path843" />
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/iOSClient/Images.xcassets/pdf-vertical.imageset/swap-vertical-variant.svg b/iOSClient/Images.xcassets/pdf-vertical.imageset/swap-vertical-variant.svg
deleted file mode 100644
index 72050e85d..000000000
--- a/iOSClient/Images.xcassets/pdf-vertical.imageset/swap-vertical-variant.svg
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M18,4L14,8H17V16A2,2 0 0,1 15,18A2,2 0 0,1 13,16V8A4,4 0 0,0 9,4A4,4 0 0,0 5,8V16H2L6,20L10,16H7V8A2,2 0 0,1 9,6A2,2 0 0,1 11,8V16A4,4 0 0,0 15,20A4,4 0 0,0 19,16V8H22L18,4Z" /></svg> \ No newline at end of file
diff --git a/iOSClient/Images.xcassets/photoEditorCancel.imageset/Contents.json b/iOSClient/Images.xcassets/photoEditorCancel.imageset/Contents.json
deleted file mode 100644
index d979ab59b..000000000
--- a/iOSClient/Images.xcassets/photoEditorCancel.imageset/Contents.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "filename" : "photoEditorCancel.png",
- "scale" : "1x"
- },
- {
- "idiom" : "universal",
- "filename" : "photoEditorCancel@2x.png",
- "scale" : "2x"
- },
- {
- "idiom" : "universal",
- "filename" : "photoEditorCancel@3x.png",
- "scale" : "3x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-} \ No newline at end of file
diff --git a/iOSClient/Images.xcassets/photoEditorCancel.imageset/photoEditorCancel.png b/iOSClient/Images.xcassets/photoEditorCancel.imageset/photoEditorCancel.png
deleted file mode 100644
index 67b045d96..000000000
--- a/iOSClient/Images.xcassets/photoEditorCancel.imageset/photoEditorCancel.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/photoEditorCancel.imageset/photoEditorCancel@2x.png b/iOSClient/Images.xcassets/photoEditorCancel.imageset/photoEditorCancel@2x.png
deleted file mode 100644
index 9e586f136..000000000
--- a/iOSClient/Images.xcassets/photoEditorCancel.imageset/photoEditorCancel@2x.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/photoEditorCancel.imageset/photoEditorCancel@3x.png b/iOSClient/Images.xcassets/photoEditorCancel.imageset/photoEditorCancel@3x.png
deleted file mode 100644
index 51e41a5ac..000000000
--- a/iOSClient/Images.xcassets/photoEditorCancel.imageset/photoEditorCancel@3x.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/photoEditorClear.imageset/Contents.json b/iOSClient/Images.xcassets/photoEditorClear.imageset/Contents.json
deleted file mode 100644
index a25af1e47..000000000
--- a/iOSClient/Images.xcassets/photoEditorClear.imageset/Contents.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "filename" : "photoEditorClear.png",
- "scale" : "1x"
- },
- {
- "idiom" : "universal",
- "filename" : "photoEditorClear@2x.png",
- "scale" : "2x"
- },
- {
- "idiom" : "universal",
- "filename" : "photoEditorClear@3x.png",
- "scale" : "3x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-} \ No newline at end of file
diff --git a/iOSClient/Images.xcassets/photoEditorClear.imageset/photoEditorClear.png b/iOSClient/Images.xcassets/photoEditorClear.imageset/photoEditorClear.png
deleted file mode 100644
index cf1bdeec6..000000000
--- a/iOSClient/Images.xcassets/photoEditorClear.imageset/photoEditorClear.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/photoEditorClear.imageset/photoEditorClear@2x.png b/iOSClient/Images.xcassets/photoEditorClear.imageset/photoEditorClear@2x.png
deleted file mode 100644
index d79aa9abd..000000000
--- a/iOSClient/Images.xcassets/photoEditorClear.imageset/photoEditorClear@2x.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/photoEditorClear.imageset/photoEditorClear@3x.png b/iOSClient/Images.xcassets/photoEditorClear.imageset/photoEditorClear@3x.png
deleted file mode 100644
index ac81fb574..000000000
--- a/iOSClient/Images.xcassets/photoEditorClear.imageset/photoEditorClear@3x.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/photoEditorCrop.imageset/Contents.json b/iOSClient/Images.xcassets/photoEditorCrop.imageset/Contents.json
deleted file mode 100644
index debea08a8..000000000
--- a/iOSClient/Images.xcassets/photoEditorCrop.imageset/Contents.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "filename" : "photoEditorCrop.png",
- "scale" : "1x"
- },
- {
- "idiom" : "universal",
- "filename" : "photoEditorCrop@2x.png",
- "scale" : "2x"
- },
- {
- "idiom" : "universal",
- "filename" : "photoEditorCrop@3x.png",
- "scale" : "3x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-} \ No newline at end of file
diff --git a/iOSClient/Images.xcassets/photoEditorCrop.imageset/photoEditorCrop.png b/iOSClient/Images.xcassets/photoEditorCrop.imageset/photoEditorCrop.png
deleted file mode 100644
index 7e4f85742..000000000
--- a/iOSClient/Images.xcassets/photoEditorCrop.imageset/photoEditorCrop.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/photoEditorCrop.imageset/photoEditorCrop@2x.png b/iOSClient/Images.xcassets/photoEditorCrop.imageset/photoEditorCrop@2x.png
deleted file mode 100644
index ad9b4d0d2..000000000
--- a/iOSClient/Images.xcassets/photoEditorCrop.imageset/photoEditorCrop@2x.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/photoEditorCrop.imageset/photoEditorCrop@3x.png b/iOSClient/Images.xcassets/photoEditorCrop.imageset/photoEditorCrop@3x.png
deleted file mode 100644
index a94ad5720..000000000
--- a/iOSClient/Images.xcassets/photoEditorCrop.imageset/photoEditorCrop@3x.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/photoEditorDone.imageset/Contents.json b/iOSClient/Images.xcassets/photoEditorDone.imageset/Contents.json
deleted file mode 100644
index 39d8a0da1..000000000
--- a/iOSClient/Images.xcassets/photoEditorDone.imageset/Contents.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "filename" : "photoEditorDone.png",
- "scale" : "1x"
- },
- {
- "idiom" : "universal",
- "filename" : "photoEditorDone@2x.png",
- "scale" : "2x"
- },
- {
- "idiom" : "universal",
- "filename" : "photoEditorDone@3x.png",
- "scale" : "3x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-} \ No newline at end of file
diff --git a/iOSClient/Images.xcassets/photoEditorDone.imageset/photoEditorDone.png b/iOSClient/Images.xcassets/photoEditorDone.imageset/photoEditorDone.png
deleted file mode 100644
index 4763dc297..000000000
--- a/iOSClient/Images.xcassets/photoEditorDone.imageset/photoEditorDone.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/photoEditorDone.imageset/photoEditorDone@2x.png b/iOSClient/Images.xcassets/photoEditorDone.imageset/photoEditorDone@2x.png
deleted file mode 100644
index 1ddc90b92..000000000
--- a/iOSClient/Images.xcassets/photoEditorDone.imageset/photoEditorDone@2x.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/photoEditorDone.imageset/photoEditorDone@3x.png b/iOSClient/Images.xcassets/photoEditorDone.imageset/photoEditorDone@3x.png
deleted file mode 100644
index 2eaf2ba59..000000000
--- a/iOSClient/Images.xcassets/photoEditorDone.imageset/photoEditorDone@3x.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/photoEditorDraw.imageset/Contents.json b/iOSClient/Images.xcassets/photoEditorDraw.imageset/Contents.json
deleted file mode 100644
index f409ad8e8..000000000
--- a/iOSClient/Images.xcassets/photoEditorDraw.imageset/Contents.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "filename" : "photoEditorDraw.png",
- "scale" : "1x"
- },
- {
- "idiom" : "universal",
- "filename" : "photoEditorDraw@2x.png",
- "scale" : "2x"
- },
- {
- "idiom" : "universal",
- "filename" : "photoEditorDraw@3x.png",
- "scale" : "3x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-} \ No newline at end of file
diff --git a/iOSClient/Images.xcassets/photoEditorDraw.imageset/photoEditorDraw.png b/iOSClient/Images.xcassets/photoEditorDraw.imageset/photoEditorDraw.png
deleted file mode 100644
index 96fd9e393..000000000
--- a/iOSClient/Images.xcassets/photoEditorDraw.imageset/photoEditorDraw.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/photoEditorDraw.imageset/photoEditorDraw@2x.png b/iOSClient/Images.xcassets/photoEditorDraw.imageset/photoEditorDraw@2x.png
deleted file mode 100644
index cd8d000ec..000000000
--- a/iOSClient/Images.xcassets/photoEditorDraw.imageset/photoEditorDraw@2x.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/photoEditorDraw.imageset/photoEditorDraw@3x.png b/iOSClient/Images.xcassets/photoEditorDraw.imageset/photoEditorDraw@3x.png
deleted file mode 100644
index aa8365791..000000000
--- a/iOSClient/Images.xcassets/photoEditorDraw.imageset/photoEditorDraw@3x.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/photoEditorText.imageset/Contents.json b/iOSClient/Images.xcassets/photoEditorText.imageset/Contents.json
deleted file mode 100644
index 91c57f675..000000000
--- a/iOSClient/Images.xcassets/photoEditorText.imageset/Contents.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "filename" : "photoEditorText.png",
- "scale" : "1x"
- },
- {
- "idiom" : "universal",
- "filename" : "photoEditorText@2x.png",
- "scale" : "2x"
- },
- {
- "idiom" : "universal",
- "filename" : "photoEditorText@3x.png",
- "scale" : "3x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-} \ No newline at end of file
diff --git a/iOSClient/Images.xcassets/photoEditorText.imageset/photoEditorText.png b/iOSClient/Images.xcassets/photoEditorText.imageset/photoEditorText.png
deleted file mode 100644
index ba7bc7cea..000000000
--- a/iOSClient/Images.xcassets/photoEditorText.imageset/photoEditorText.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/photoEditorText.imageset/photoEditorText@2x.png b/iOSClient/Images.xcassets/photoEditorText.imageset/photoEditorText@2x.png
deleted file mode 100644
index 5c9271396..000000000
--- a/iOSClient/Images.xcassets/photoEditorText.imageset/photoEditorText@2x.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/photoEditorText.imageset/photoEditorText@3x.png b/iOSClient/Images.xcassets/photoEditorText.imageset/photoEditorText@3x.png
deleted file mode 100644
index 40725d067..000000000
--- a/iOSClient/Images.xcassets/photoEditorText.imageset/photoEditorText@3x.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/tabBarFavorites.imageset/Contents.json b/iOSClient/Images.xcassets/tabBarFavorites.imageset/Contents.json
deleted file mode 100644
index cfafcd9de..000000000
--- a/iOSClient/Images.xcassets/tabBarFavorites.imageset/Contents.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "images" : [
- {
- "filename" : "tabBarFavorites.pdf",
- "idiom" : "universal"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- },
- "properties" : {
- "preserves-vector-representation" : true
- }
-}
diff --git a/iOSClient/Images.xcassets/tabBarFavorites.imageset/tabBarFavorites.pdf b/iOSClient/Images.xcassets/tabBarFavorites.imageset/tabBarFavorites.pdf
deleted file mode 100644
index 25f0cd639..000000000
--- a/iOSClient/Images.xcassets/tabBarFavorites.imageset/tabBarFavorites.pdf
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/tabBarMedia.imageset/Contents.json b/iOSClient/Images.xcassets/tabBarMedia.imageset/Contents.json
deleted file mode 100644
index c42193f0f..000000000
--- a/iOSClient/Images.xcassets/tabBarMedia.imageset/Contents.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "images" : [
- {
- "filename" : "tabBarMedia.pdf",
- "idiom" : "universal"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- },
- "properties" : {
- "preserves-vector-representation" : true
- }
-}
diff --git a/iOSClient/Images.xcassets/tabBarMedia.imageset/tabBarMedia.pdf b/iOSClient/Images.xcassets/tabBarMedia.imageset/tabBarMedia.pdf
deleted file mode 100644
index 515ca27a1..000000000
--- a/iOSClient/Images.xcassets/tabBarMedia.imageset/tabBarMedia.pdf
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/userStatusOnline.imageset/online.pdf b/iOSClient/Images.xcassets/userStatusOnline.imageset/online.pdf
deleted file mode 100644
index 672db3e6e..000000000
--- a/iOSClient/Images.xcassets/userStatusOnline.imageset/online.pdf
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/visiblePassword.imageset/Contents.json b/iOSClient/Images.xcassets/visiblePassword.imageset/Contents.json
deleted file mode 100644
index fb45aa9ac..000000000
--- a/iOSClient/Images.xcassets/visiblePassword.imageset/Contents.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "scale" : "1x",
- "filename" : "visiblePassword.png"
- },
- {
- "idiom" : "universal",
- "filename" : "visiblePassword@2x.png",
- "scale" : "2x"
- },
- {
- "idiom" : "universal",
- "scale" : "3x",
- "filename" : "visiblePassword@3x.png"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-} \ No newline at end of file
diff --git a/iOSClient/Images.xcassets/visiblePassword.imageset/visiblePassword.png b/iOSClient/Images.xcassets/visiblePassword.imageset/visiblePassword.png
deleted file mode 100644
index 2e56118f3..000000000
--- a/iOSClient/Images.xcassets/visiblePassword.imageset/visiblePassword.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/visiblePassword.imageset/visiblePassword@2x.png b/iOSClient/Images.xcassets/visiblePassword.imageset/visiblePassword@2x.png
deleted file mode 100644
index 3a191b07b..000000000
--- a/iOSClient/Images.xcassets/visiblePassword.imageset/visiblePassword@2x.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Images.xcassets/visiblePassword.imageset/visiblePassword@3x.png b/iOSClient/Images.xcassets/visiblePassword.imageset/visiblePassword@3x.png
deleted file mode 100644
index 80246c39e..000000000
--- a/iOSClient/Images.xcassets/visiblePassword.imageset/visiblePassword@3x.png
+++ /dev/null
Binary files differ
diff --git a/iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift b/iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift
index fd431bd06..6c12e8346 100644
--- a/iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift
+++ b/iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift
@@ -93,7 +93,6 @@ class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate {
if recording.state == .record {
- startDate = Date()
recording.stop()
voiceRecordHUD.update(0.0)
@@ -105,6 +104,7 @@ class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate {
do {
try recording.record()
+ startDate = Date()
startStopLabel.text = NSLocalizedString("_voice_memo_stop_", comment: "")
} catch {
print(error)
@@ -188,8 +188,8 @@ open class NCAudioRecorder: NSObject {
// MARK: - Initializers
- public init(to: String) {
- url = URL(fileURLWithPath: NCAudioRecorder.directory).appendingPathComponent(to)
+ public init(to fileName: String) {
+ url = URL(fileURLWithPath: NCAudioRecorder.directory).appendingPathComponent(fileName)
super.init()
do {
@@ -278,7 +278,6 @@ open class NCAudioRecorder: NSObject {
}
fileprivate func stopMetering() {
-
link?.invalidate()
link = nil
}
diff --git a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift
index 0ff8de7a5..0b8a7c674 100644
--- a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift
+++ b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift
@@ -44,7 +44,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
internal var metadataFolder: tableMetadata?
internal var dataSource = NCDataSource()
internal var richWorkspaceText: String?
- internal var header: UIView?
+ internal var header: NCSectionHeaderMenu?
internal var layoutForView: NCGlobal.layoutForViewType?
@@ -615,7 +615,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
button.action(for: .touchUpInside) { _ in
let accounts = NCManageDatabase.shared.getAllAccountOrderAlias()
- if accounts.count > 0 {
+ if accounts.count > 0 && !NCBrandOptions.shared.disable_multiaccount && !NCBrandOptions.shared.disable_manage_account {
if let vcAccountRequest = UIStoryboard(name: "NCAccountRequest", bundle: nil).instantiateInitialViewController() as? NCAccountRequest {
@@ -741,6 +741,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
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
@@ -751,6 +752,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
NCUtility.shared.setLayoutForView(key: layoutKey, serverUrl: serverUrl, layout: layoutForView?.layout)
} 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
@@ -789,7 +791,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(objectId) else { return }
- if namedButtonMore == NCGlobal.shared.buttonMoreMore {
+ if namedButtonMore == NCGlobal.shared.buttonMoreMore || namedButtonMore == NCGlobal.shared.buttonMoreLock {
toggleMenu(metadata: metadata, imageIcon: image)
} else if namedButtonMore == NCGlobal.shared.buttonMoreStop {
NCNetworking.shared.cancelTransferMetadata(metadata) { }
@@ -1267,8 +1269,10 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
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
@@ -1388,6 +1392,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
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
@@ -1396,6 +1401,11 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
cell.progressView.progress = 0.0
}
+ var a11yValues: [String] = []
+ if metadata.ownerId != appDelegate.userId, appDelegate.account == metadata.account {
+ a11yValues.append(NSLocalizedString("_shared_with_you_by_", comment: "") + " " + metadata.ownerDisplayName)
+ }
+
if metadata.directory {
if metadata.e2eEncrypted {
@@ -1428,6 +1438,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
// 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
@@ -1437,6 +1448,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
// image Favorite
if metadata.favorite {
cell.imageFavorite.image = NCBrandColor.cacheImages.favorite
+ a11yValues.append(NSLocalizedString("_favorite_", comment: ""))
}
// Share image
@@ -1455,6 +1467,9 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
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)
}
@@ -1490,9 +1505,12 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
break
}
+ cell.accessibilityLabel = metadata.fileNameView + ", " + (cell.labelInfo.text ?? "")
+
// Live Photo
if metadata.livePhoto {
cell.imageStatus.image = NCBrandColor.cacheImages.livePhoto
+ a11yValues.append(NSLocalizedString("_upload_mov_livephoto_", comment: ""))
}
// E2EE
@@ -1514,12 +1532,14 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
cell.selectMode(true)
if selectOcId.contains(metadata.ocId) {
cell.selected(true)
+ a11yValues.append(NSLocalizedString("_selected_", comment: ""))
} else {
cell.selected(false)
}
} else {
cell.selectMode(false)
}
+ cell.accessibilityValue = a11yValues.joined(separator: ", ")
// Disable Share Button
if appDelegate.disableSharesView {
@@ -1559,9 +1579,16 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
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
+ }
+
+ var a11yValues: [String] = []
+ if metadata.ownerId != appDelegate.userId, appDelegate.account == metadata.account {
+ a11yValues.append(NSLocalizedString("_shared_with_you_by_", comment: "") + " " + metadata.ownerDisplayName)
}
if metadata.directory {
@@ -1597,6 +1624,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
// 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
}
@@ -1605,11 +1633,15 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
// image Favorite
if metadata.favorite {
cell.imageFavorite.image = NCBrandColor.cacheImages.favorite
+ a11yValues.append(NSLocalizedString("_favorite_", comment: ""))
}
// 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)
}
@@ -1617,6 +1649,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
// Live Photo
if metadata.livePhoto {
cell.imageStatus.image = NCBrandColor.cacheImages.livePhoto
+ a11yValues.append(NSLocalizedString("_upload_mov_livephoto_", comment: ""))
}
// Edit mode
@@ -1624,12 +1657,14 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
cell.selectMode(true)
if selectOcId.contains(metadata.ocId) {
cell.selected(true)
+ a11yValues.append(NSLocalizedString("_selected_", comment: ""))
} else {
cell.selected(false)
}
} else {
cell.selectMode(false)
}
+ cell.accessibilityValue = a11yValues.joined(separator: ", ")
return cell
}
diff --git a/iOSClient/Main/Collection Common/NCGridCell.swift b/iOSClient/Main/Collection Common/NCGridCell.swift
index e458e3cd2..9fcd361c8 100644
--- a/iOSClient/Main/Collection Common/NCGridCell.swift
+++ b/iOSClient/Main/Collection Common/NCGridCell.swift
@@ -72,6 +72,12 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
override func awakeFromNib() {
super.awakeFromNib()
+ // use entire cell as accessibility element
+ accessibilityHint = nil
+ accessibilityLabel = nil
+ accessibilityValue = nil
+ isAccessibilityElement = true
+
imageItem.layer.cornerRadius = 6
imageItem.layer.masksToBounds = true
@@ -99,6 +105,9 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
override func prepareForReuse() {
super.prepareForReuse()
imageItem.backgroundColor = nil
+ accessibilityHint = nil
+ accessibilityLabel = nil
+ accessibilityValue = nil
}
@IBAction func touchUpInsideMore(_ sender: Any) {
@@ -113,9 +122,21 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
delegate?.longPressGridItem(with: objectId, gestureRecognizer: gestureRecognizer)
}
+ fileprivate func setA11yActions() {
+ let moreName = namedButtonMore == NCGlobal.shared.buttonMoreStop ? "_cancel_" : "_more_"
+
+ self.accessibilityCustomActions = [
+ UIAccessibilityCustomAction(
+ name: NSLocalizedString(moreName, comment: ""),
+ target: self,
+ selector: #selector(touchUpInsideMore))
+ ]
+ }
+
func setButtonMore(named: String, image: UIImage) {
namedButtonMore = named
buttonMore.setImage(image, for: .normal)
+ setA11yActions()
}
func hideButtonMore(_ status: Bool) {
@@ -125,9 +146,11 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
func selectMode(_ status: Bool) {
if status {
imageSelect.isHidden = false
+ accessibilityCustomActions = nil
} else {
imageSelect.isHidden = true
imageVisualEffect.isHidden = true
+ setA11yActions()
}
}
diff --git a/iOSClient/Main/Collection Common/NCListCell.swift b/iOSClient/Main/Collection Common/NCListCell.swift
index 9e0266f65..71e3bd43a 100755
--- a/iOSClient/Main/Collection Common/NCListCell.swift
+++ b/iOSClient/Main/Collection Common/NCListCell.swift
@@ -80,6 +80,12 @@ class NCListCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
imageItem.layer.cornerRadius = 6
imageItem.layer.masksToBounds = true
+ // use entire cell as accessibility element
+ accessibilityHint = nil
+ accessibilityLabel = nil
+ accessibilityValue = nil
+ isAccessibilityElement = true
+
progressView.tintColor = NCBrandColor.shared.brandElement
progressView.transform = CGAffineTransform(scaleX: 1.0, y: 0.5)
progressView.trackTintColor = .clear
@@ -103,6 +109,9 @@ class NCListCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
override func prepareForReuse() {
super.prepareForReuse()
imageItem.backgroundColor = nil
+ accessibilityHint = nil
+ accessibilityLabel = nil
+ accessibilityValue = nil
}
@IBAction func touchUpInsideShare(_ sender: Any) {
@@ -121,9 +130,25 @@ class NCListCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
delegate?.longPressListItem(with: objectId, gestureRecognizer: gestureRecognizer)
}
+ fileprivate func setA11yActions() {
+ let moreName = namedButtonMore == NCGlobal.shared.buttonMoreStop ? "_cancel_" : "_more_"
+ self.accessibilityCustomActions = [
+ UIAccessibilityCustomAction(
+ name: NSLocalizedString("_share_", comment: ""),
+ target: self,
+ selector: #selector(touchUpInsideShare)),
+ UIAccessibilityCustomAction(
+ name: NSLocalizedString(moreName, comment: ""),
+ target: self,
+ selector: #selector(touchUpInsideMore))
+ ]
+ }
+
func setButtonMore(named: String, image: UIImage) {
namedButtonMore = named
imageMore.image = image
+
+ setA11yActions()
}
func hideButtonMore(_ status: Bool) {
@@ -140,10 +165,12 @@ class NCListCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
if status {
imageItemLeftConstraint.constant = 45
imageSelect.isHidden = false
+ accessibilityCustomActions = nil
} else {
imageItemLeftConstraint.constant = 10
imageSelect.isHidden = true
backgroundView = nil
+ setA11yActions()
}
}
diff --git a/iOSClient/Main/Collection Common/NCSelectableNavigationView.swift b/iOSClient/Main/Collection Common/NCSelectableNavigationView.swift
index 86aa18c8f..84b706e48 100644
--- a/iOSClient/Main/Collection Common/NCSelectableNavigationView.swift
+++ b/iOSClient/Main/Collection Common/NCSelectableNavigationView.swift
@@ -95,6 +95,9 @@ extension NCSelectableNavigationView where Self: UIViewController {
var selectedMetadatas: [tableMetadata] = []
var selectedMediaMetadatas: [tableMetadata] = []
var isAnyOffline = false
+ var isAnyFolder = false
+ var isAnyLocked = false
+ var canUnlock = true
for ocId in selectOcId {
guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { continue }
@@ -102,6 +105,13 @@ extension NCSelectableNavigationView where Self: UIViewController {
if [NCCommunicationCommon.typeClassFile.image.rawValue, NCCommunicationCommon.typeClassFile.video.rawValue].contains(metadata.classFile) {
selectedMediaMetadatas.append(metadata)
}
+ if metadata.directory { isAnyFolder = true }
+ if metadata.lock {
+ isAnyLocked = true
+ if metadata.lockOwner != appDelegate.userId {
+ canUnlock = false
+ }
+ }
guard !isAnyOffline else { continue }
if metadata.directory,
@@ -114,6 +124,10 @@ extension NCSelectableNavigationView where Self: UIViewController {
actions.append(.openInAction(selectedMetadatas: selectedMetadatas, viewController: self, completion: tapSelect))
+ if !isAnyFolder, canUnlock, NCManageDatabase.shared.getCapabilitiesServerInt(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesFilesLockVersion) >= 1 {
+ actions.append(.lockUnlockFiles(shouldLock: !isAnyLocked, metadatas: selectedMetadatas, completion: tapSelect))
+ }
+
if !selectedMediaMetadatas.isEmpty {
actions.append(.saveMediaAction(selectedMediaMetadatas: selectedMediaMetadatas, completion: tapSelect))
}
diff --git a/iOSClient/Main/Create cloud/NCCreateFormUploadAssets.swift b/iOSClient/Main/Create cloud/NCCreateFormUploadAssets.swift
index 686abeefa..adcd666d2 100644
--- a/iOSClient/Main/Create cloud/NCCreateFormUploadAssets.swift
+++ b/iOSClient/Main/Create cloud/NCCreateFormUploadAssets.swift
@@ -415,7 +415,6 @@ class NCCreateFormUploadAssets: XLFormViewController, NCSelectDelegate {
metadataForUpload.assetLocalIdentifier = asset.localIdentifier
metadataForUpload.session = self.session
metadataForUpload.sessionSelector = NCGlobal.shared.selectorUploadFile
- metadataForUpload.size = NCUtilityFileSystem.shared.getFileSize(asset: asset)
metadataForUpload.status = NCGlobal.shared.metadataStatusWaitUpload
if livePhoto {
diff --git a/iOSClient/Main/Create cloud/NCCreateFormUploadConflict.swift b/iOSClient/Main/Create cloud/NCCreateFormUploadConflict.swift
index 0816812c5..48cda3166 100644
--- a/iOSClient/Main/Create cloud/NCCreateFormUploadConflict.swift
+++ b/iOSClient/Main/Create cloud/NCCreateFormUploadConflict.swift
@@ -423,7 +423,7 @@ extension NCCreateFormUploadConflict: UITableViewDataSource {
} else {
- CCUtility.extractImageVideoFromAssetLocalIdentifier(forUpload: metadataNewFile, notification: false) { metadataNew, fileNamePath in
+ CCUtility.extractImageVideoFromAssetLocalIdentifier(forUpload: metadataNewFile) { metadataNew, fileNamePath in
if metadataNew != nil {
self.fileNamesPath[metadataNewFile.fileNameView] = fileNamePath!
diff --git a/iOSClient/Main/Create cloud/NCCreateFormUploadDocuments.swift b/iOSClient/Main/Create cloud/NCCreateFormUploadDocuments.swift
index 6d90735b9..313215913 100644
--- a/iOSClient/Main/Create cloud/NCCreateFormUploadDocuments.swift
+++ b/iOSClient/Main/Create cloud/NCCreateFormUploadDocuments.swift
@@ -328,7 +328,9 @@ import XLForm
if self.editorId == NCGlobal.shared.editorOnlyoffice {
customUserAgent = NCUtility.shared.getCustomUserAgentOnlyOffice()
- }
+ } else if editorId == NCGlobal.shared.editorText {
+ customUserAgent = NCUtility.shared.getCustomUserAgentNCText()
+ } // else: use default
NCCommunication.shared.NCTextCreateFile(fileNamePath: fileNamePath, editorId: editorId, creatorId: creatorId, templateId: templateIdentifier, customUserAgent: customUserAgent) { account, url, errorCode, errorMessage in
@@ -396,7 +398,10 @@ import XLForm
var customUserAgent: String?
if self.editorId == NCGlobal.shared.editorOnlyoffice {
customUserAgent = NCUtility.shared.getCustomUserAgentOnlyOffice()
- }
+ } else if editorId == NCGlobal.shared.editorText {
+ customUserAgent = NCUtility.shared.getCustomUserAgentNCText()
+ } // else: use default
+
NCCommunication.shared.NCTextGetListOfTemplates(customUserAgent: customUserAgent) { account, templates, errorCode, _ in
self.indicator.stopAnimating()
diff --git a/iOSClient/Main/Create cloud/NCCreateFormUploadScanDocument.swift b/iOSClient/Main/Create cloud/NCCreateFormUploadScanDocument.swift
index 7058688f7..565d3fc2b 100644
--- a/iOSClient/Main/Create cloud/NCCreateFormUploadScanDocument.swift
+++ b/iOSClient/Main/Create cloud/NCCreateFormUploadScanDocument.swift
@@ -459,6 +459,7 @@ class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NC
NCContentPresenter.shared.messageNotification("_error_", description: "_error_creation_file_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorCreationFile)
return
}
+ let fileUrl = URL(fileURLWithPath: fileNameGenerateExport)
// Text Recognition TXT
if fileType == "TXT" && self.form.formRow(withTag: "textRecognition")!.value as! Int == 1 {
@@ -489,7 +490,7 @@ class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NC
}
do {
- try textFile.write(to: NSURL(fileURLWithPath: fileNameGenerateExport) as URL, atomically: true, encoding: .utf8)
+ try textFile.write(to: fileUrl, atomically: true, encoding: .utf8)
} catch {
NCUtility.shared.stopActivityIndicator()
NCContentPresenter.shared.messageNotification("_error_", description: "_error_creation_file_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorCreationFile)
@@ -562,7 +563,7 @@ class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NC
UIGraphicsEndPDFContext()
do {
- try pdfData.write(toFile: fileNameGenerateExport, options: .atomic)
+ try pdfData.write(to: fileUrl, options: .atomic)
} catch {
print("error catched")
}
@@ -579,13 +580,14 @@ class NCCreateFormUploadScanDocument: XLFormViewController, NCSelectDelegate, NC
}
do {
- try data.write(to: NSURL.fileURL(withPath: fileNameGenerateExport), options: .atomic)
+ try data.write(to: fileUrl, options: .atomic)
} catch {
NCUtility.shared.stopActivityIndicator()
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()
diff --git a/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift b/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift
index a262b4dc8..795dadedd 100644
--- a/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift
+++ b/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.swift
@@ -245,6 +245,7 @@ class NCCreateFormUploadVoiceNote: XLFormViewController, NCSelectDelegate, AVAud
metadataForUpload.session = NCNetworking.shared.sessionIdentifierBackground
metadataForUpload.sessionSelector = NCGlobal.shared.selectorUploadFile
metadataForUpload.status = NCGlobal.shared.metadataStatusWaitUpload
+ metadataForUpload.size = NCUtilityFileSystem.shared.getFileSize(filePath: fileNamePath)
if NCManageDatabase.shared.getMetadataConflict(account: appDelegate.account, serverUrl: serverUrl, fileName: fileNameSave) != nil {
diff --git a/iOSClient/Main/NCFunctionCenter.swift b/iOSClient/Main/NCFunctionCenter.swift
index 55378f930..52e62224f 100644
--- a/iOSClient/Main/NCFunctionCenter.swift
+++ b/iOSClient/Main/NCFunctionCenter.swift
@@ -77,11 +77,8 @@ import SVGKit
editingMode = true
}
- let viewerQuickLook = NCViewerQuickLook(with: URL(fileURLWithPath: fileNamePath), editingMode: editingMode, metadata: metadata)
- let navigationController = UINavigationController(rootViewController: viewerQuickLook)
- navigationController.modalPresentationStyle = .overFullScreen
-
- self.appDelegate.window?.rootViewController?.present(navigationController, animated: true)
+ let viewerQuickLook = NCViewerQuickLook(with: URL(fileURLWithPath: fileNamePath), isEditingEnabled: editingMode, metadata: metadata)
+ self.appDelegate.window?.rootViewController?.present(viewerQuickLook, animated: true)
case NCGlobal.shared.selectorLoadFileView:
guard UIApplication.shared.applicationState == UIApplication.State.active else { break }
@@ -309,27 +306,18 @@ import SVGKit
func saveAlbum(metadata: tableMetadata) {
let fileNamePath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
- let status = PHPhotoLibrary.authorizationStatus()
-
- if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && status == PHAuthorizationStatus.authorized {
- if let image = UIImage(contentsOfFile: fileNamePath) {
- UIImageWriteToSavedPhotosAlbum(image, self, #selector(saveAlbum(_:didFinishSavingWithError:contextInfo:)), nil)
- } else {
- NCContentPresenter.shared.messageNotification("_save_selected_files_", description: "_file_not_saved_cameraroll_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorFileNotSaved)
+ NCAskAuthorization.shared.askAuthorizationPhotoLibrary(viewController: appDelegate.mainTabBar?.window?.rootViewController) { hasPermission in
+ guard hasPermission else {
+ return NCContentPresenter.shared.messageNotification("_access_photo_not_enabled_", description: "_access_photo_not_enabled_msg_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorFileNotSaved)
}
-
- } else if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue && status == PHAuthorizationStatus.authorized {
-
- if UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(fileNamePath) {
- UISaveVideoAtPathToSavedPhotosAlbum(fileNamePath, self, #selector(saveAlbum(_:didFinishSavingWithError:contextInfo:)), nil)
+ if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue, let image = UIImage(contentsOfFile: fileNamePath) {
+ UIImageWriteToSavedPhotosAlbum(image, self, #selector(self.saveAlbum(_:didFinishSavingWithError:contextInfo:)), nil)
+ } else if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue, UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(fileNamePath) {
+ UISaveVideoAtPathToSavedPhotosAlbum(fileNamePath, self, #selector(self.saveAlbum(_:didFinishSavingWithError:contextInfo:)), nil)
} else {
NCContentPresenter.shared.messageNotification("_save_selected_files_", description: "_file_not_saved_cameraroll_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorFileNotSaved)
}
-
- } else if status != PHAuthorizationStatus.authorized {
-
- NCContentPresenter.shared.messageNotification("_access_photo_not_enabled_", description: "_access_photo_not_enabled_msg_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorFileNotSaved)
}
}
@@ -547,19 +535,19 @@ import SVGKit
}
}
- func openSelectView(items: [Any]) {
+ func openSelectView(items: [tableMetadata]) {
let navigationController = UIStoryboard(name: "NCSelect", bundle: nil).instantiateInitialViewController() as! UINavigationController
let topViewController = navigationController.topViewController as! NCSelect
var listViewController = [NCSelect]()
- var copyItems: [Any] = []
+ var copyItems: [tableMetadata] = []
for item in items {
copyItems.append(item)
}
let homeUrl = NCUtilityFileSystem.shared.getHomeServer(account: appDelegate.account)
- var serverUrl = (copyItems[0] as! Nextcloud.tableMetadata).serverUrl
+ var serverUrl = copyItems[0].serverUrl
// Setup view controllers such that the current view is of the same directory the items to be copied are in
while true {
@@ -628,7 +616,8 @@ import SVGKit
}
}
let titleOffline = isOffline ? NSLocalizedString("_remove_available_offline_", comment: "") : NSLocalizedString("_set_available_offline_", comment: "")
-
+ let titleLock = metadata.lock ? NSLocalizedString("_unlock_file_", comment: "") : NSLocalizedString("_lock_file_", comment: "")
+ let iconLock = metadata.lock ? "lock.open" : "lock"
let copy = UIAction(title: NSLocalizedString("_copy_file_", comment: ""), image: UIImage(systemName: "doc.on.doc")) { _ in
self.copyPasteboard(pasteboardOcIds: [metadata.ocId], hudView: viewController.view)
}
@@ -649,7 +638,10 @@ import SVGKit
viewController.reloadDataSource()
}
}
-
+
+ let lockUnlock = UIAction(title: titleLock, image: UIImage(systemName: iconLock)) { _ in
+ NCNetworking.shared.lockUnlockFile(metadata, shoulLock: !metadata.lock)
+ }
let save = UIAction(title: titleSave, image: UIImage(systemName: "square.and.arrow.down")) { _ in
if metadataMOV != nil {
self.saveLivePhoto(metadata: metadata, metadataMOV: metadataMOV!)
@@ -745,15 +737,29 @@ import SVGKit
// DIR
- if metadata.directory {
-
+ guard !metadata.directory else {
let submenu = UIMenu(title: "", options: .displayInline, children: [favorite, offline, rename, moveCopy, copyPath, delete])
+ guard appDelegate.disableSharesView == false else { return submenu }
return UIMenu(title: "", children: [detail, submenu])
}
// FILE
- var children: [UIMenuElement] = [favorite, offline, openIn, rename, moveCopy, copy, copyPath, delete]
+ var children: [UIMenuElement] = [offline, openIn, moveCopy, copy, copyPath]
+
+ if !metadata.lock {
+ // Workaround: PROPPATCH doesn't work (favorite)
+ // https://github.com/nextcloud/files_lock/issues/68
+ children.insert(favorite, at: 0)
+ children.append(delete)
+ children.insert(rename, at: 3)
+ } else if enableDeleteLocal {
+ children.append(deleteConfirmLocal)
+ }
+
+ if NCManageDatabase.shared.getCapabilitiesServerInt(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesFilesLockVersion) >= 1, metadata.canUnlock(as: appDelegate.userId) {
+ children.insert(lockUnlock, at: metadata.lock ? 0 : 1)
+ }
if (metadata.contentType != "image/svg+xml") && (metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue) {
children.insert(save, at: 2)
@@ -768,22 +774,23 @@ import SVGKit
}
if enableViewInFolder {
- children.insert(viewInFolder, at: children.count-1)
+ children.insert(viewInFolder, at: children.count - 1)
}
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) {
- children.insert(modify, at: children.count-1)
+ 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)
+ 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/NCMainTabBar.swift b/iOSClient/Main/NCMainTabBar.swift
index 7a3dd50fa..ecdc124d5 100644
--- a/iOSClient/Main/NCMainTabBar.swift
+++ b/iOSClient/Main/NCMainTabBar.swift
@@ -144,7 +144,7 @@ class NCMainTabBar: UITabBar {
// Favorite
if let item = items?[1] {
item.title = NSLocalizedString("_favorites_", comment: "")
- item.image = UIImage(named: "tabBarFavorites")?.image(color: NCBrandColor.shared.brandElement, size: 25)
+ item.image = UIImage(named: "star.fill")?.image(color: NCBrandColor.shared.brandElement, size: 25)
item.selectedImage = item.image
}
@@ -158,7 +158,7 @@ class NCMainTabBar: UITabBar {
// Media
if let item = items?[3] {
item.title = NSLocalizedString("_media_", comment: "")
- item.image = UIImage(named: "tabBarMedia")?.image(color: NCBrandColor.shared.brandElement, size: 25)
+ item.image = UIImage(named: "media")?.image(color: NCBrandColor.shared.brandElement, size: 25)
item.selectedImage = item.image
}
diff --git a/iOSClient/Media/NCMedia.swift b/iOSClient/Media/NCMedia.swift
index aebb00c67..c26d26385 100644
--- a/iOSClient/Media/NCMedia.swift
+++ b/iOSClient/Media/NCMedia.swift
@@ -725,10 +725,11 @@ class NCMediaCommandView: UIView {
moreView.layer.masksToBounds = true
controlButtonView.layer.cornerRadius = 20
controlButtonView.layer.masksToBounds = true
+ controlButtonView.effect = UIBlurEffect(style: .dark)
gradient.frame = bounds
- gradient.startPoint = CGPoint(x: 0, y: 0.50)
- gradient.endPoint = CGPoint(x: 0, y: 0.9)
- gradient.colors = [UIColor.black.withAlphaComponent(0.4).cgColor, UIColor.clear.cgColor]
+ gradient.startPoint = CGPoint(x: 0, y: 0.5)
+ gradient.endPoint = CGPoint(x: 0, y: 1)
+ gradient.colors = [UIColor.black.withAlphaComponent(UIAccessibility.isReduceTransparencyEnabled ? 0.8 : 0.4).cgColor, UIColor.clear.cgColor]
layer.insertSublayer(gradient, at: 0)
moreButton.setImage(UIImage(named: "more")!.image(color: .white, size: 25), for: .normal)
title.text = ""
@@ -743,7 +744,7 @@ class NCMediaCommandView: UIView {
}
} else {
UIView.animate(withDuration: 0.3) {
- self.moreView.effect = UIBlurEffect(style: .regular)
+ self.moreView.effect = UIBlurEffect(style: .dark)
self.gradient.isHidden = false
self.controlButtonView.isHidden = false
}
diff --git a/iOSClient/Menu/AppDelegate+Menu.swift b/iOSClient/Menu/AppDelegate+Menu.swift
index 6c693c466..f17217067 100644
--- a/iOSClient/Menu/AppDelegate+Menu.swift
+++ b/iOSClient/Menu/AppDelegate+Menu.swift
@@ -118,29 +118,8 @@ extension AppDelegate {
actions.append(
NCMenuAction(title: NSLocalizedString("_create_folder_", comment: ""),
icon: UIImage(named: "folder")!.image(color: NCBrandColor.shared.brandElement, size: 50), action: { _ in
-
- if appDelegate.activeServerUrl == "" { return }
-
- let alertController = UIAlertController(title: NSLocalizedString("_create_folder_on_", comment: ""), message: nil, preferredStyle: .alert)
-
- alertController.addTextField { textField in
- textField.autocapitalizationType = UITextAutocapitalizationType.sentences
- }
-
- let cancelAction = UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel, handler: nil)
- let okAction = UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in
- if let fileNameFolder = alertController.textFields?.first?.text {
- NCNetworking.shared.createFolder(fileName: fileNameFolder, serverUrl: appDelegate.activeServerUrl, account: appDelegate.account, urlBase: appDelegate.urlBase, overwrite: false) { errorCode, errorDescription in
- if errorCode != 0 {
- NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
- }
- }
- }
- })
-
- alertController.addAction(cancelAction)
- alertController.addAction(okAction)
-
+ guard !appDelegate.activeServerUrl.isEmpty else { return }
+ let alertController = UIAlertController.createFolder(serverUrl: appDelegate.activeServerUrl, urlBase: appDelegate)
appDelegate.window?.rootViewController?.present(alertController, animated: true, completion: nil)
}
)
diff --git a/iOSClient/Menu/NCCollectionViewCommon+Menu.swift b/iOSClient/Menu/NCCollectionViewCommon+Menu.swift
index 2cfb5e7d3..fda43661f 100644
--- a/iOSClient/Menu/NCCollectionViewCommon+Menu.swift
+++ b/iOSClient/Menu/NCCollectionViewCommon+Menu.swift
@@ -71,22 +71,59 @@ extension NCCollectionViewCommon {
)
)
+ if metadata.lock {
+ var lockOwnerName = metadata.lockOwnerDisplayName.isEmpty ? metadata.lockOwner : metadata.lockOwnerDisplayName
+ var lockIcon = NCUtility.shared.loadUserImage(for: metadata.lockOwner, displayName: lockOwnerName, userBaseUrl: metadata)
+ if metadata.lockOwnerType != 0 {
+ lockOwnerName += " app"
+ if !metadata.lockOwnerEditor.isEmpty, let appIcon = UIImage(named: metadata.lockOwnerEditor) {
+ lockIcon = appIcon
+ }
+ }
+
+ var lockTimeString: String?
+ if let lockTime = metadata.lockTimeOut {
+ if lockTime >= Date().addingTimeInterval(60),
+ let timeInterval = (lockTime.timeIntervalSince1970 - Date().timeIntervalSince1970).format() {
+ lockTimeString = String(format: NSLocalizedString("_time_remaining_", comment: ""), timeInterval)
+ } else if lockTime > Date() {
+ lockTimeString = NSLocalizedString("_less_a_minute_", comment: "")
+ } // else: don't show negative time
+ }
+ if let lockTime = metadata.lockTime, lockTimeString == nil {
+ lockTimeString = DateFormatter.localizedString(from: lockTime, dateStyle: .short, timeStyle: .short)
+ }
+
+ actions.append(
+ NCMenuAction(
+ title: String(format: NSLocalizedString("_locked_by_", comment: ""), lockOwnerName),
+ details: lockTimeString,
+ icon: lockIcon,
+ action: nil)
+ )
+ }
+
+ actions.append(.seperator)
+
//
// FAVORITE
- //
- actions.append(
- NCMenuAction(
- title: metadata.favorite ? NSLocalizedString("_remove_favorites_", comment: "") : NSLocalizedString("_add_favorites_", comment: ""),
- icon: NCUtility.shared.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite),
- action: { _ in
- NCNetworking.shared.favoriteMetadata(metadata) { errorCode, errorDescription in
- if errorCode != 0 {
- NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+ // FIXME: PROPPATCH doesn't work
+ // https://github.com/nextcloud/files_lock/issues/68
+ if !metadata.lock {
+ actions.append(
+ NCMenuAction(
+ title: metadata.favorite ? NSLocalizedString("_remove_favorites_", comment: "") : NSLocalizedString("_add_favorites_", comment: ""),
+ icon: NCUtility.shared.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite),
+ action: { _ in
+ NCNetworking.shared.favoriteMetadata(metadata) { errorCode, errorDescription in
+ if errorCode != 0 {
+ NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+ }
}
}
- }
+ )
)
- )
+ }
//
// DETAIL
@@ -102,6 +139,20 @@ extension NCCollectionViewCommon {
)
)
}
+
+ //
+ // LOCK / UNLOCK
+ //
+ let hasLockCapability = NCManageDatabase.shared.getCapabilitiesServerInt(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesFilesLockVersion) >= 1
+ if !metadata.directory, metadata.canUnlock(as: appDelegate.userId), hasLockCapability {
+ let lockAction = NCMenuAction.lockUnlockFiles(shouldLock: !metadata.lock, metadatas: [metadata])
+ if metadata.lock {
+ // make unlock first action, after info rows & seperator
+ actions.insert(lockAction, at: 3)
+ } else {
+ actions.append(lockAction)
+ }
+ }
//
// OFFLINE
@@ -183,7 +234,7 @@ extension NCCollectionViewCommon {
//
// RENAME
//
- if !(isFolderEncrypted && metadata.serverUrl == serverUrlHome) {
+ if !(isFolderEncrypted && metadata.serverUrl == serverUrlHome), !metadata.lock {
actions.append(
NCMenuAction(
title: NSLocalizedString("_rename_", comment: ""),
@@ -322,3 +373,14 @@ extension NCCollectionViewCommon {
presentMenu(with: actions)
}
}
+
+
+extension TimeInterval {
+ func format() -> String? {
+ let formatter = DateComponentsFormatter()
+ formatter.allowedUnits = [.day, .hour, .minute]
+ formatter.unitsStyle = .full
+ formatter.maximumUnitCount = 1
+ return formatter.string(from: self)
+ }
+}
diff --git a/iOSClient/Menu/NCMedia+Menu.swift b/iOSClient/Menu/NCMedia+Menu.swift
index 5454dd3eb..629107aff 100644
--- a/iOSClient/Menu/NCMedia+Menu.swift
+++ b/iOSClient/Menu/NCMedia+Menu.swift
@@ -173,8 +173,10 @@ extension NCMedia {
//
// DELETE
- //
- actions.append(.deleteAction(selectedMetadatas: selectedMetadatas, metadataFolder: nil, viewController: self, completion: tapSelect))
+ // can't delete from cache because is needed for NCMedia view, and if locked can't delete from server either.
+ if !selectedMetadatas.contains(where: { $0.lock && $0.lockOwner != appDelegate.userId }) {
+ actions.append(.deleteAction(selectedMetadatas: selectedMetadatas, metadataFolder: nil, viewController: self, completion: tapSelect))
+ }
}
}
}
diff --git a/iOSClient/Menu/NCMenu+FloatingPanel.swift b/iOSClient/Menu/NCMenu+FloatingPanel.swift
index 053697c80..71735a202 100644
--- a/iOSClient/Menu/NCMenu+FloatingPanel.swift
+++ b/iOSClient/Menu/NCMenu+FloatingPanel.swift
@@ -23,6 +23,7 @@
import Foundation
import FloatingPanel
+import UIKit
class NCMenuFloatingPanelLayout: FloatingPanelLayout {
var position: FloatingPanelPosition = .bottom
@@ -37,7 +38,7 @@ class NCMenuFloatingPanelLayout: FloatingPanelLayout {
let topInset: CGFloat
- init(numberOfActions: Int) {
+ init(actionsHeight: CGFloat) {
// sometimes UIScreen.main.bounds.size.height is not updated correctly
// this ensures we use the correct height value
// can't use `layoutFor size` since menu is dieplayed on top of the whole screen not just the VC
@@ -45,7 +46,7 @@ class NCMenuFloatingPanelLayout: FloatingPanelLayout {
? min(UIScreen.main.bounds.size.width, UIScreen.main.bounds.size.height)
: max(UIScreen.main.bounds.size.width, UIScreen.main.bounds.size.height)
let bottomInset = UIApplication.shared.keyWindow?.rootViewController?.view.safeAreaInsets.bottom ?? 0
- let panelHeight = CGFloat(numberOfActions * 60) + bottomInset
+ let panelHeight = CGFloat(actionsHeight) + bottomInset
topInset = max(48, screenHeight - panelHeight)
}
@@ -75,5 +76,17 @@ class NCMenuPanelController: FloatingPanelController {
self.isRemovalInteractionEnabled = true
self.backdropView.dismissalTapGestureRecognizer.isEnabled = true
self.surfaceView.layer.cornerRadius = 16
+
+ surfaceView.grabberHandle.accessibilityLabel = NSLocalizedString("_cart_controller_", comment: "")
+
+ let collapseName = NSLocalizedString("_dismiss_menu_", comment: "")
+ let collapseAction = UIAccessibilityCustomAction(name: collapseName, target: self, selector: #selector(accessibilityActionCollapsePanel))
+
+ surfaceView.grabberHandle.accessibilityCustomActions = [collapseAction]
+ surfaceView.grabberHandle.isAccessibilityElement = true
}
+
+ @objc private func accessibilityActionCollapsePanel() {
+ self.dismiss(animated: true)
+ }
}
diff --git a/iOSClient/Menu/NCMenu.storyboard b/iOSClient/Menu/NCMenu.storyboard
index ce18c84df..dd46fcc4a 100644
--- a/iOSClient/Menu/NCMenu.storyboard
+++ b/iOSClient/Menu/NCMenu.storyboard
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="dbT-V0-aXb">
+<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="dbT-V0-aXb">
<device id="retina6_1" 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="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@@ -18,7 +18,7 @@
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="menuActionCell" rowHeight="60" id="MT1-Lu-9SA">
- <rect key="frame" x="0.0" y="28" width="414" height="60"/>
+ <rect key="frame" x="0.0" y="44.5" width="414" height="60"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="MT1-Lu-9SA" id="tmT-MO-Dwy">
<rect key="frame" x="0.0" y="0.0" width="414" height="60"/>
@@ -31,19 +31,31 @@
<constraint firstAttribute="width" constant="28" id="gxY-bI-V0v"/>
</constraints>
</imageView>
- <label opaque="NO" userInteractionEnabled="NO" tag="2" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="A8f-xF-j3i">
- <rect key="frame" x="60" y="19.5" width="326" height="21"/>
- <fontDescription key="fontDescription" type="system" pointSize="17"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
+ <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="2" translatesAutoresizingMaskIntoConstraints="NO" id="6vv-IO-HJM">
+ <rect key="frame" x="60" y="19" width="326" height="22"/>
+ <subviews>
+ <label opaque="NO" userInteractionEnabled="NO" tag="2" contentMode="left" horizontalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="A8f-xF-j3i">
+ <rect key="frame" x="0.0" y="0.0" width="326" height="20"/>
+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <label opaque="NO" userInteractionEnabled="NO" tag="3" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="749" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SjQ-O4-Clh">
+ <rect key="frame" x="0.0" y="22" width="326" height="0.0"/>
+ <fontDescription key="fontDescription" type="system" pointSize="15"/>
+ <color key="textColor" systemColor="secondaryLabelColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ </stackView>
</subviews>
<constraints>
- <constraint firstItem="A8f-xF-j3i" firstAttribute="leading" secondItem="RV0-3K-eSN" secondAttribute="trailing" constant="16" id="ADH-SJ-JNh"/>
+ <constraint firstAttribute="trailingMargin" secondItem="6vv-IO-HJM" secondAttribute="trailing" constant="8" id="4pu-DJ-9cK"/>
+ <constraint firstItem="6vv-IO-HJM" firstAttribute="leading" secondItem="RV0-3K-eSN" secondAttribute="trailing" constant="16" id="8tD-ZW-Y88"/>
<constraint firstItem="RV0-3K-eSN" firstAttribute="leading" secondItem="tmT-MO-Dwy" secondAttribute="leading" constant="16" id="QQt-st-4hA"/>
<constraint firstItem="RV0-3K-eSN" firstAttribute="centerY" secondItem="tmT-MO-Dwy" secondAttribute="centerY" id="R6O-om-tEz"/>
- <constraint firstAttribute="trailingMargin" secondItem="A8f-xF-j3i" secondAttribute="trailing" constant="8" id="fia-KH-ier"/>
- <constraint firstItem="A8f-xF-j3i" firstAttribute="centerY" secondItem="tmT-MO-Dwy" secondAttribute="centerY" id="kPV-bd-AAL"/>
+ <constraint firstItem="6vv-IO-HJM" firstAttribute="top" secondItem="tmT-MO-Dwy" secondAttribute="topMargin" constant="8" id="d50-c3-Ofv"/>
+ <constraint firstAttribute="bottomMargin" secondItem="6vv-IO-HJM" secondAttribute="bottom" constant="8" id="zte-5x-B8K"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
@@ -60,6 +72,9 @@
</scene>
</scenes>
<resources>
+ <systemColor name="secondaryLabelColor">
+ <color red="0.23529411764705882" green="0.23529411764705882" blue="0.2627450980392157" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
+ </systemColor>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
diff --git a/iOSClient/Menu/NCMenu.swift b/iOSClient/Menu/NCMenu.swift
index 4c0e2a50a..cf7f99e44 100644
--- a/iOSClient/Menu/NCMenu.swift
+++ b/iOSClient/Menu/NCMenu.swift
@@ -28,6 +28,10 @@
import UIKit
import FloatingPanel
+extension Array where Element == NCMenuAction {
+ var listHeight: CGFloat { reduce(0, { $0 + $1.rowHeight }) }
+}
+
class NCMenu: UITableViewController {
var actions = [NCMenuAction]()
@@ -42,6 +46,8 @@ class NCMenu: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
+ tableView.estimatedRowHeight = 60
+ tableView.rowHeight = UITableView.automaticDimension
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
@@ -63,15 +69,25 @@ class NCMenu: UITableViewController {
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+ let action = actions[indexPath.row]
+ guard action.title != NCMenuAction.seperatorIdentifier else {
+ let cell = UITableViewCell()
+ cell.backgroundColor = NCBrandColor.shared.separator
+ return cell
+ }
let cell = tableView.dequeueReusableCell(withIdentifier: "menuActionCell", for: indexPath)
cell.tintColor = NCBrandColor.shared.customer
- let action = actions[indexPath.row]
let actionIconView = cell.viewWithTag(1) as? UIImageView
let actionNameLabel = cell.viewWithTag(2) as? UILabel
+ let actionDetailLabel = cell.viewWithTag(3) as? UILabel
if action.action == nil {
cell.selectionStyle = .none
}
+ if let details = action.details {
+ actionDetailLabel?.text = details
+ actionNameLabel?.isHidden = false
+ } else { actionDetailLabel?.isHidden = true }
if action.isOn {
actionIconView?.image = action.onIcon
@@ -89,17 +105,17 @@ class NCMenu: UITableViewController {
// MARK: - Tabel View Layout
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
- return 60
+ actions[indexPath.row].title == NCMenuAction.seperatorIdentifier ? NCMenuAction.seperatorHeight : UITableView.automaticDimension
}
}
extension NCMenu: FloatingPanelControllerDelegate {
func floatingPanel(_ fpc: FloatingPanelController, layoutFor size: CGSize) -> FloatingPanelLayout {
- return NCMenuFloatingPanelLayout(numberOfActions: self.actions.count)
+ return NCMenuFloatingPanelLayout(actionsHeight: self.actions.listHeight)
}
func floatingPanel(_ fpc: FloatingPanelController, layoutFor newCollection: UITraitCollection) -> FloatingPanelLayout {
- return NCMenuFloatingPanelLayout(numberOfActions: self.actions.count)
+ return NCMenuFloatingPanelLayout(actionsHeight: self.actions.listHeight)
}
func floatingPanel(_ fpc: FloatingPanelController, animatorForDismissingWith velocity: CGVector) -> UIViewPropertyAnimator {
diff --git a/iOSClient/Menu/NCMenuAction.swift b/iOSClient/Menu/NCMenuAction.swift
index 03f17b2c1..6aff1a224 100644
--- a/iOSClient/Menu/NCMenuAction.swift
+++ b/iOSClient/Menu/NCMenuAction.swift
@@ -5,12 +5,29 @@
// Created by Henrik Storch on 17.02.22.
// Copyright © 2022 Marino Faggiana. All rights reserved.
//
+// Author Henrik Storch <henrik.storch@nextcloud.com>
+// 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 NCMenuAction {
let title: String
+ let details: String?
let icon: UIImage
let selectable: Bool
var onTitle: String?
@@ -18,16 +35,19 @@ class NCMenuAction {
var selected: Bool = false
var isOn: Bool = false
var action: ((_ menuAction: NCMenuAction) -> Void)?
+ var rowHeight: CGFloat { self.title == NCMenuAction.seperatorIdentifier ? NCMenuAction.seperatorHeight : self.details != nil ? 80 : 60 }
- init(title: String, icon: UIImage, action: ((_ menuAction: NCMenuAction) -> Void)?) {
+ init(title: String, details: String? = nil, icon: UIImage, action: ((_ menuAction: NCMenuAction) -> Void)?) {
self.title = title
+ self.details = details
self.icon = icon
self.action = action
self.selectable = false
}
- init(title: String, icon: UIImage, onTitle: String? = nil, onIcon: UIImage? = nil, selected: Bool, on: Bool, action: ((_ menuAction: NCMenuAction) -> Void)?) {
+ init(title: String, details: String? = nil, icon: UIImage, onTitle: String? = nil, onIcon: UIImage? = nil, selected: Bool, on: Bool, action: ((_ menuAction: NCMenuAction) -> Void)?) {
self.title = title
+ self.details = details
self.icon = icon
self.onTitle = onTitle ?? title
self.onIcon = onIcon ?? icon
@@ -41,6 +61,13 @@ class NCMenuAction {
// MARK: - Actions
extension NCMenuAction {
+ static let seperatorIdentifier = "NCMenuAction.SEPARATOR"
+ static let seperatorHeight: CGFloat = 0.5
+
+ /// A static seperator, with no actions, text, or icons
+ static var seperator: NCMenuAction {
+ return NCMenuAction(title: seperatorIdentifier, icon: UIImage(), action: nil)
+ }
/// Select all items
static func selectAllAction(action: @escaping () -> Void) -> NCMenuAction {
@@ -86,6 +113,7 @@ extension NCMenuAction {
}
} // else: no metadata selected
+ let canDeleteServer = selectedMetadatas.allSatisfy { !$0.lock }
var fileList = ""
for (ix, metadata) in selectedMetadatas.enumerated() {
guard ix < 3 else { fileList += "\n - ..."; break }
@@ -100,10 +128,12 @@ extension NCMenuAction {
title: titleDelete,
message: NSLocalizedString("_want_delete_", comment: "") + fileList,
preferredStyle: .alert)
- alertController.addAction(UIAlertAction(title: NSLocalizedString("_yes_delete_", comment: ""), style: .default) { (_: UIAlertAction) in
- selectedMetadatas.forEach({ NCOperationQueue.shared.delete(metadata: $0, onlyLocalCache: false) })
- completion?()
- })
+ if canDeleteServer {
+ alertController.addAction(UIAlertAction(title: NSLocalizedString("_yes_delete_", comment: ""), style: .default) { (_: UIAlertAction) in
+ selectedMetadatas.forEach({ NCOperationQueue.shared.delete(metadata: $0, onlyLocalCache: false) })
+ completion?()
+ })
+ }
// NCMedia removes image from collection view if removed from cache
if !(viewController is NCMedia) {
@@ -212,4 +242,25 @@ extension NCMenuAction {
}
)
}
+
+ /// Lock or unlock a file using *files_lock*
+ static func lockUnlockFiles(shouldLock: Bool, metadatas: [tableMetadata], completion: (() -> Void)? = nil) -> NCMenuAction {
+ let titleKey: String
+ if metadatas.count == 1 {
+ titleKey = shouldLock ? "_lock_file_" : "_unlock_file_"
+ } else {
+ titleKey = shouldLock ? "_lock_selected_files_" : "_unlock_selected_files_"
+ }
+ let imageName = !shouldLock ? "lock_open" : "lock"
+ return NCMenuAction(
+ title: NSLocalizedString(titleKey, comment: ""),
+ icon: NCUtility.shared.loadImage(named: imageName),
+ action: { _ in
+ for metadata in metadatas where metadata.lock != shouldLock {
+ NCNetworking.shared.lockUnlockFile(metadata, shoulLock: shouldLock)
+ }
+ completion?()
+ }
+ )
+ }
}
diff --git a/iOSClient/Menu/NCShare+Menu.swift b/iOSClient/Menu/NCShare+Menu.swift
new file mode 100644
index 000000000..0ec28c6e3
--- /dev/null
+++ b/iOSClient/Menu/NCShare+Menu.swift
@@ -0,0 +1,121 @@
+//
+// NCShare+Menu.swift
+// Nextcloud
+//
+// Created by Henrik Storch on 16.03.22.
+// Copyright © 2022 Henrik Storch. All rights reserved.
+//
+// Author Henrik Storch <henrik.storch@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 NCShare {
+ func toggleShareMenu(for share: tableShare) {
+
+ var actions = [NCMenuAction]()
+
+ if share.shareType == 3, canReshare {
+ actions.append(
+ NCMenuAction(
+ title: NSLocalizedString("_share_add_sharelink_", comment: ""),
+ icon: NCUtility.shared.loadImage(named: "shareAdd"),
+ action: { _ in
+ self.makeNewLinkShare()
+ }
+ )
+ )
+ }
+
+ actions.append(
+ NCMenuAction(
+ title: NSLocalizedString("_details_", comment: ""),
+ icon: NCUtility.shared.loadImage(named: "pencil"),
+ action: { _ in
+ guard
+ let advancePermission = UIStoryboard(name: "NCShare", bundle: nil).instantiateViewController(withIdentifier: "NCShareAdvancePermission") as? NCShareAdvancePermission,
+ let navigationController = self.navigationController, !share.isInvalidated else { return }
+ advancePermission.networking = self.networking
+ advancePermission.share = tableShare(value: share)
+ advancePermission.oldTableShare = tableShare(value: share)
+ advancePermission.metadata = self.metadata
+ navigationController.pushViewController(advancePermission, animated: true)
+ }
+ )
+ )
+
+ actions.append(
+ NCMenuAction(
+ title: NSLocalizedString("_share_unshare_", comment: ""),
+ icon: NCUtility.shared.loadImage(named: "trash"),
+ action: { _ in
+ self.networking?.unShare(idShare: share.idShare)
+ }
+ )
+ )
+
+ self.presentMenu(with: actions)
+ }
+
+ func toggleUserPermissionMenu(isDirectory: Bool, tableShare: tableShare) {
+ var actions = [NCMenuAction]()
+
+ actions.append(
+ NCMenuAction(
+ title: NSLocalizedString("_share_read_only_", comment: ""),
+ icon: NCUtility.shared.loadImage(named: "eye"),
+ selected: tableShare.permissions == (NCGlobal.shared.permissionReadShare + NCGlobal.shared.permissionShareShare) || tableShare.permissions == NCGlobal.shared.permissionReadShare,
+ on: false,
+ action: { _ in
+ let canShare = CCUtility.isPermission(toCanShare: tableShare.permissions)
+ let permissions = CCUtility.getPermissionsValue(byCanEdit: false, andCanCreate: false, andCanChange: false, andCanDelete: false, andCanShare: canShare, andIsFolder: isDirectory)
+ self.updateSharePermissions(share: tableShare, permissions: permissions)
+ }
+ )
+ )
+
+ actions.append(
+ NCMenuAction(
+ title: isDirectory ? NSLocalizedString("_share_allow_upload_", comment: "") : NSLocalizedString("_share_editing_", comment: ""),
+ icon: NCUtility.shared.loadImage(named: "pencil"),
+ selected: hasUploadPermission(tableShare: tableShare),
+ on: false,
+ action: { _ in
+ let canShare = CCUtility.isPermission(toCanShare: tableShare.permissions)
+ let permissions = CCUtility.getPermissionsValue(byCanEdit: true, andCanCreate: true, andCanChange: true, andCanDelete: true, andCanShare: canShare, andIsFolder: isDirectory)
+ self.updateSharePermissions(share: tableShare, permissions: permissions)
+ }
+ )
+ )
+
+ self.presentMenu(with: actions)
+ }
+
+ fileprivate func hasUploadPermission(tableShare: tableShare) -> Bool {
+ let uploadPermissions = [
+ NCGlobal.shared.permissionMaxFileShare,
+ NCGlobal.shared.permissionMaxFolderShare,
+ NCGlobal.shared.permissionDefaultFileRemoteShareNoSupportShareOption,
+ NCGlobal.shared.permissionDefaultFolderRemoteShareNoSupportShareOption]
+ return uploadPermissions.contains(tableShare.permissions)
+ }
+
+ func updateSharePermissions(share: tableShare, permissions: Int) {
+ let updatedShare = tableShare(value: share)
+ updatedShare.permissions = permissions
+ networking?.updateShare(option: updatedShare)
+ }
+}
diff --git a/iOSClient/Menu/NCViewer+Menu.swift b/iOSClient/Menu/NCViewer+Menu.swift
index e85354bce..5b18d6a6f 100644
--- a/iOSClient/Menu/NCViewer+Menu.swift
+++ b/iOSClient/Menu/NCViewer+Menu.swift
@@ -40,20 +40,23 @@ extension NCViewer {
//
// FAVORITE
- //
- actions.append(
- NCMenuAction(
- title: titleFavorite,
- icon: NCUtility.shared.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite),
- action: { _ in
- NCNetworking.shared.favoriteMetadata(metadata) { errorCode, errorDescription in
- if errorCode != 0 {
- NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+ // Workaround: PROPPATCH doesn't work
+ // https://github.com/nextcloud/files_lock/issues/68
+ if !metadata.lock {
+ actions.append(
+ NCMenuAction(
+ title: titleFavorite,
+ icon: NCUtility.shared.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite),
+ action: { _ in
+ NCNetworking.shared.favoriteMetadata(metadata) { errorCode, errorDescription in
+ if errorCode != 0 {
+ NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+ }
}
}
- }
+ )
)
- )
+ }
//
// DETAIL
@@ -102,7 +105,7 @@ extension NCViewer {
//
// CONVERSION VIDEO TO MPEG4 (MFFF Lib)
//
- #if MFFFLIB
+#if MFFFLIB
if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue {
actions.append(
@@ -117,7 +120,7 @@ extension NCViewer {
)
)
}
- #endif
+#endif
//
// SAVE IMAGE / VIDEO
@@ -146,7 +149,7 @@ extension NCViewer {
//
// RENAME
//
- if !webView {
+ if !webView, !metadata.lock {
actions.append(
NCMenuAction(
title: NSLocalizedString("_rename_", comment: ""),
@@ -226,31 +229,6 @@ extension NCViewer {
)
)
- var title = ""
- var icon = UIImage()
-
- if CCUtility.getPDFDisplayDirection() == .horizontal {
- title = NSLocalizedString("_pdf_vertical_", comment: "")
- icon = UIImage(named: "pdf-vertical")!.image(color: NCBrandColor.shared.gray, size: 50)
- } else {
- title = NSLocalizedString("_pdf_horizontal_", comment: "")
- icon = UIImage(named: "pdf-horizontal")!.image(color: NCBrandColor.shared.gray, size: 50)
- }
-
- actions.append(
- NCMenuAction(
- title: title,
- icon: icon,
- action: { _ in
- if CCUtility.getPDFDisplayDirection() == .horizontal {
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterMenuPDFDisplayDirection, userInfo: ["direction": PDFDisplayDirection.vertical])
- } else {
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterMenuPDFDisplayDirection, userInfo: ["direction": PDFDisplayDirection.horizontal])
- }
- }
- )
- )
-
actions.append(
NCMenuAction(
title: NSLocalizedString("_go_to_page_", comment: ""),
diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift
index bae04f0cc..af5f23ab2 100644
--- a/iOSClient/NCGlobal.swift
+++ b/iOSClient/NCGlobal.swift
@@ -112,7 +112,7 @@ class NCGlobal: NSObject {
// Database Realm
//
let databaseDefault = "nextcloud.realm"
- let databaseSchemaVersion: UInt64 = 216
+ let databaseSchemaVersion: UInt64 = 222
// Intro selector
//
@@ -176,6 +176,7 @@ class NCGlobal: NSObject {
//
let buttonMoreMore = "more"
let buttonMoreStop = "stop"
+ let buttonMoreLock = "moreLock"
// Text - OnlyOffice - Collabora - QuickLook
//
@@ -344,15 +345,12 @@ class NCGlobal: NSObject {
let notificationCenterFavoriteFile = "favoriteFile" // userInfo: ocId
let notificationCenterMenuSearchTextPDF = "menuSearchTextPDF"
- let notificationCenterMenuPDFDisplayDirection = "menuPDFDisplayDirection" // userInfo: direction
let notificationCenterMenuGotToPageInPDF = "menuGotToPageInPDF"
let notificationCenterMenuDetailClose = "menuDetailClose"
let notificationCenterChangedLocation = "changedLocation"
let notificationStatusAuthorizationChangedLocation = "statusAuthorizationChangedLocation"
- let notificationCenterShareChangePermissions = "shareChangePermissions" // userInfo: idShare, permissions, hideDownload
-
let notificationCenterDownloadedThumbnail = "DownloadedThumbnail" // userInfo: ocId
let notificationCenterHidePlayerToolBar = "hidePlayerToolBar" // userInfo: ocId
@@ -362,4 +360,8 @@ class NCGlobal: NSObject {
let notificationCenterReloadMediaPage = "reloadMediaPage"
let notificationCenterPlayMedia = "playMedia"
let notificationCenterPauseMedia = "pauseMedia"
+
+ // Tip
+ //
+ let tipNCViewerPDFThumbnail = "tipncviewerpdfthumbnail"
}
diff --git a/iOSClient/Networking/NCAutoUpload.swift b/iOSClient/Networking/NCAutoUpload.swift
index ce5017567..2e080974c 100644
--- a/iOSClient/Networking/NCAutoUpload.swift
+++ b/iOSClient/Networking/NCAutoUpload.swift
@@ -25,78 +25,17 @@ import UIKit
import CoreLocation
import NCCommunication
-class NCAutoUpload: NSObject, CLLocationManagerDelegate {
+class NCAutoUpload: NSObject {
@objc static let shared: NCAutoUpload = {
let instance = NCAutoUpload()
return instance
}()
private let appDelegate = UIApplication.shared.delegate as! AppDelegate
- public var locationManager: CLLocationManager?
private var endForAssetToUpload: Bool = false
// MARK: -
- @objc func startSignificantChangeUpdates() {
-
- if locationManager == nil {
-
- locationManager = CLLocationManager()
- locationManager?.delegate = self
- locationManager?.distanceFilter = 10
- }
-
- locationManager?.requestAlwaysAuthorization()
- locationManager?.startMonitoringSignificantLocationChanges()
- }
-
- @objc func stopSignificantChangeUpdates() {
-
- locationManager?.stopMonitoringSignificantLocationChanges()
- }
-
- func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
-
- let location = locations.last
- guard let latitude = location?.coordinate.latitude else { return }
- guard let longitude = location?.coordinate.longitude else { return }
-
- NCCommunicationCommon.shared.writeLog("Location manager: latitude \(latitude) longitude \(longitude)")
-
- if let activeAccount = NCManageDatabase.shared.getActiveAccount() {
- if activeAccount.autoUpload && activeAccount.autoUploadBackground && UIApplication.shared.applicationState == UIApplication.State.background {
- NCAskAuthorization.shared.askAuthorizationPhotoLibrary(viewController: nil) { hasPermission in
- if hasPermission {
- self.uploadAssetsNewAndFull(viewController: nil, selector: NCGlobal.shared.selectorUploadAutoUpload, log: "Change location") { items in
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUpdateBadgeNumber)
- if items > 0 {
- self.appDelegate.networkingProcessUpload?.startProcess()
- }
- }
- }
- }
- }
- }
- }
-
- func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
- if CLLocationManager.authorizationStatus() != CLAuthorizationStatus.authorizedAlways {
- NCManageDatabase.shared.setAccountAutoUploadProperty("autoUploadBackground", state: false)
- self.stopSignificantChangeUpdates()
- }
- }
-
- func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
- NCAskAuthorization.shared.askAuthorizationLocationManager { hasFullPermissions in
- if !hasFullPermissions {
- NCManageDatabase.shared.setAccountAutoUploadProperty("autoUploadBackground", state: false)
- self.stopSignificantChangeUpdates()
- }
- }
- }
-
- // MARK: -
-
@objc func initAutoUpload(viewController: UIViewController?, completion: @escaping (_ items: Int) -> Void) {
if let activeAccount = NCManageDatabase.shared.getActiveAccount() {
if activeAccount.autoUpload {
@@ -108,19 +47,9 @@ class NCAutoUpload: NSObject, CLLocationManagerDelegate {
}
completion(items)
}
- if activeAccount.autoUploadBackground {
- NCAskAuthorization.shared.askAuthorizationLocationManager { hasFullPermissions in
- if hasFullPermissions {
- self.startSignificantChangeUpdates()
- } else {
- NCManageDatabase.shared.setAccountAutoUploadProperty("autoUploadBackground", state: false)
- self.stopSignificantChangeUpdates()
- }
- }
- }
+
} else {
NCManageDatabase.shared.setAccountAutoUploadProperty("autoUpload", state: false)
- self.stopSignificantChangeUpdates()
completion(0)
}
}
@@ -128,7 +57,6 @@ class NCAutoUpload: NSObject, CLLocationManagerDelegate {
completion(0)
}
} else {
- stopSignificantChangeUpdates()
completion(0)
}
}
@@ -241,7 +169,6 @@ class NCAutoUpload: NSObject, CLLocationManagerDelegate {
metadataForUpload.assetLocalIdentifier = asset.localIdentifier
metadataForUpload.session = session
metadataForUpload.sessionSelector = selector
- metadataForUpload.size = NCUtilityFileSystem.shared.getFileSize(asset: asset)
metadataForUpload.status = NCGlobal.shared.metadataStatusWaitUpload
if assetMediaType == PHAssetMediaType.video {
metadataForUpload.classFile = NCCommunicationCommon.typeClassFile.video.rawValue
@@ -250,7 +177,7 @@ class NCAutoUpload: NSObject, CLLocationManagerDelegate {
}
if selector == NCGlobal.shared.selectorUploadAutoUpload {
- NCCommunicationCommon.shared.writeLog("Automatic upload added \(metadataForUpload.fileNameView) (\(metadataForUpload.size) bytes) with Identifier \(metadataForUpload.assetLocalIdentifier)")
+ NCCommunicationCommon.shared.writeLog("Automatic upload added \(metadataForUpload.fileNameView) with Identifier \(metadataForUpload.assetLocalIdentifier)")
self.appDelegate.networkingProcessUpload?.createProcessUploads(metadatas: [metadataForUpload], verifyAlreadyExists: true)
NCManageDatabase.shared.addPhotoLibrary([asset], account: account.account)
} else if selector == NCGlobal.shared.selectorUploadAutoUploadAll {
@@ -276,7 +203,7 @@ class NCAutoUpload: NSObject, CLLocationManagerDelegate {
metadataForUpload.classFile = NCCommunicationCommon.typeClassFile.video.rawValue
if selector == NCGlobal.shared.selectorUploadAutoUpload {
- NCCommunicationCommon.shared.writeLog("Automatic upload added Live Photo \(metadataForUpload.fileNameView) (\(metadataForUpload.size) bytes) with Identifier \(metadataForUpload.assetLocalIdentifier)")
+ 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 {
diff --git a/iOSClient/Networking/NCNetworking.swift b/iOSClient/Networking/NCNetworking.swift
index 19dccaedc..84c074ac9 100644
--- a/iOSClient/Networking/NCNetworking.swift
+++ b/iOSClient/Networking/NCNetworking.swift
@@ -413,10 +413,24 @@ import Queuer
@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)
-
+
+ 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
@@ -448,7 +462,7 @@ import Queuer
let metadata = tableMetadata.init(value: metadata)
- if CCUtility.fileProviderStorageExists(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)
@@ -467,7 +481,7 @@ import Queuer
} else {
- CCUtility.extractImageVideoFromAssetLocalIdentifier(forUpload: metadata, notification: true) { extractMetadata, fileNamePath in
+ CCUtility.extractImageVideoFromAssetLocalIdentifier(forUpload: metadata) { extractMetadata, fileNamePath in
guard let metadata = extractMetadata else {
NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
@@ -523,8 +537,9 @@ import Queuer
}) { _, ocId, etag, date, size, _, _, errorCode, errorDescription in
self.uploadRequest[fileNameLocalPath] = nil
- self.uploadComplete(fileName: metadata.fileName, serverUrl: metadata.serverUrl, ocId: ocId, etag: etag, date: date, size: size, description: description, task: uploadTask!, errorCode: errorCode, errorDescription: errorDescription)
-
+ 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)
+ }
completion(errorCode, errorDescription)
}
}
@@ -545,7 +560,7 @@ import Queuer
start()
// Check file dim > 0
- if NCUtilityFileSystem.shared.getFileSize(filePath: fileNameLocalPath) == 0 {
+ if NCUtilityFileSystem.shared.getFileSize(filePath: fileNameLocalPath) == 0 && metadata.size != 0 {
NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
@@ -570,97 +585,87 @@ import Queuer
}
func uploadComplete(fileName: String, serverUrl: String, ocId: String?, etag: String?, date: NSDate?, size: Int64, description: String?, task: URLSessionTask, errorCode: Int, errorDescription: String) {
- if delegate != nil {
+ 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)
- } else {
-
- guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(description) else { return }
- guard let tableAccount = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", metadata.account)) else { return }
- let ocIdTemp = metadata.ocId
- var errorDescription = errorDescription
-
- if errorCode == 0 && ocId != nil && size > 0 {
-
- let metadata = tableMetadata.init(value: metadata)
+ return
+ }
- NCUtilityFileSystem.shared.moveFileInBackground(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId), toPath: CCUtility.getDirectoryProviderStorageOcId(ocId))
+ guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(description) else { return }
+ let ocIdTemp = metadata.ocId
+ var errorDescription = errorDescription
- metadata.uploadDate = date ?? NSDate()
- metadata.etag = etag ?? ""
- metadata.ocId = ocId!
+ if errorCode == 0, let ocId = ocId, size == metadata.size {
- if let fileId = NCUtility.shared.ocIdToFileId(ocId: ocId) {
- metadata.fileId = fileId
- }
+ let metadata = tableMetadata.init(value: metadata)
- metadata.session = ""
- metadata.sessionError = ""
- metadata.sessionTaskIdentifier = 0
- metadata.status = NCGlobal.shared.metadataStatusNormal
+ NCUtilityFileSystem.shared.moveFileInBackground(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId), toPath: CCUtility.getDirectoryProviderStorageOcId(ocId))
- // Delete Asset on Photos album
- if tableAccount.autoUploadDeleteAssetLocalIdentifier && metadata.assetLocalIdentifier != "" && metadata.sessionSelector == NCGlobal.shared.selectorUploadAutoUpload {
- metadata.deleteAssetLocalIdentifier = true
- }
+ metadata.uploadDate = date ?? NSDate()
+ metadata.etag = etag ?? ""
+ metadata.ocId = ocId
- if CCUtility.getDisableLocalCacheAfterUpload() {
- CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
- } else {
- NCManageDatabase.shared.addLocalFile(metadata: metadata)
- }
- NCManageDatabase.shared.addMetadata(metadata)
- NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp))
+ if let fileId = NCUtility.shared.ocIdToFileId(ocId: ocId) {
+ metadata.fileId = fileId
+ }
- #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
+ metadata.session = ""
+ metadata.sessionError = ""
+ metadata.sessionTaskIdentifier = 0
+ metadata.status = NCGlobal.shared.metadataStatusNormal
- 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": ""])
+ // Delete Asset on Photos album
+ if CCUtility.getRemovePhotoCameraRoll() && !metadata.assetLocalIdentifier.isEmpty {
+ metadata.deleteAssetLocalIdentifier = true
+ }
+ if CCUtility.getDisableLocalCacheAfterUpload() {
+ CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
} else {
+ NCManageDatabase.shared.addLocalFile(metadata: metadata)
+ }
+ NCManageDatabase.shared.addMetadata(metadata)
+ NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocIdTemp))
- 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])
-
- } else if errorCode == 401 || errorCode == 403 {
-
- #if !EXTENSION
- NCNetworkingCheckRemoteUser.shared.checkRemoteUser(account: metadata.account, errorCode: errorCode, errorDescription: errorDescription)
- #endif
+#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
- NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
+ 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 {
- } else {
+ CCUtility.removeFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId))
+ NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
- if size == 0 {
- errorDescription = "File length 0"
- NCCommunicationCommon.shared.writeLog("Upload error 0 length " + serverUrl + "/" + fileName + ", result: success(\(size) bytes)")
- }
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadCancelFile, userInfo: ["ocId": metadata.ocId, "serverUrl": metadata.serverUrl, "account": metadata.account])
- NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
+ } 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)")
}
-
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUploadedFile, userInfo: ["ocId": metadata.ocId, "ocIdTemp": ocIdTemp, "errorCode": errorCode, "errorDescription": ""])
+ NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId, session: nil, sessionError: errorDescription, sessionTaskIdentifier: 0, status: NCGlobal.shared.metadataStatusUploadError)
}
-
- #if !EXTENSION
- DispatchQueue.main.async { (UIApplication.shared.delegate as! AppDelegate).listProgress[metadata.ocId] = nil }
- #endif
-
- // Delete
- self.uploadMetadataInBackground[fileName+serverUrl] = nil
+ 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
}
func uploadProgress(_ progress: Float, totalBytes: Int64, totalBytesExpected: Int64, fileName: String, serverUrl: String, session: URLSession, task: URLSessionTask) {
@@ -1177,6 +1182,23 @@ import Queuer
}
}
+ // MARK: - Lock Files
+
+ @objc func lockUnlockFile(_ metadata: tableMetadata, shoulLock: Bool) {
+ NCCommunication.shared.lockUnlockFile(serverUrlFileName: metadata.serverUrl + "/" + metadata.fileName, shouldLock: shoulLock) { errorCode, errorDescription in
+ // 0: lock was successful; 412: lock did not change, no error, refresh
+ guard errorCode == 0 || errorCode == 412 else {
+ 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
+ guard errorCode == 0, let metadata = metadata else { return }
+ NCManageDatabase.shared.addMetadata(metadata)
+ NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource)
+ }
+ }
+ }
+
// MARK: - WebDav Rename
@objc func renameMetadata(_ metadata: tableMetadata, fileNameNew: String, viewController: UIViewController?, completion: @escaping (_ errorCode: Int, _ errorDescription: String?) -> Void) {
diff --git a/iOSClient/Networking/NCNetworkingChunkedUpload.swift b/iOSClient/Networking/NCNetworkingChunkedUpload.swift
index f9a134c7a..684484fe9 100644
--- a/iOSClient/Networking/NCNetworkingChunkedUpload.swift
+++ b/iOSClient/Networking/NCNetworkingChunkedUpload.swift
@@ -149,6 +149,7 @@ extension NCNetworking {
if errorCode == 0 {
let serverUrl = metadata.serverUrl
+ let assetLocalIdentifier = metadata.assetLocalIdentifier
NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
NCManageDatabase.shared.deleteChunks(account: metadata.account, ocId: metadata.ocId)
@@ -158,6 +159,11 @@ extension NCNetworking {
if errorCode == 0, let metadata = metadata {
+ 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])
diff --git a/iOSClient/Networking/NCNetworkingProcessUpload.swift b/iOSClient/Networking/NCNetworkingProcessUpload.swift
index 5b7bb01e5..b2f5eac52 100644
--- a/iOSClient/Networking/NCNetworkingProcessUpload.swift
+++ b/iOSClient/Networking/NCNetworkingProcessUpload.swift
@@ -160,11 +160,9 @@ 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, sessionSelector: NCGlobal.shared.selectorUploadAutoUpload) {
+ self.deleteAssetLocalIdentifiers(account: self.appDelegate.account) {
self.startTimer()
}
} else {
@@ -173,7 +171,7 @@ class NCNetworkingProcessUpload: NSObject {
}
}
- private func deleteAssetLocalIdentifiers(account: String, sessionSelector: String, completition: @escaping () -> Void) {
+ private func deleteAssetLocalIdentifiers(account: String, completition: @escaping () -> Void) {
if UIApplication.shared.applicationState != .active {
completition()
@@ -184,7 +182,7 @@ class NCNetworkingProcessUpload: NSObject {
completition()
return
}
- let localIdentifiers = NCManageDatabase.shared.getAssetLocalIdentifiersUploaded(account: account, sessionSelector: sessionSelector)
+ let localIdentifiers = NCManageDatabase.shared.getAssetLocalIdentifiersUploaded(account: account)
if localIdentifiers.isEmpty {
completition()
return
@@ -215,20 +213,7 @@ class NCNetworkingProcessUpload: NSObject {
}
}
- // E2EE
- if CCUtility.isFolderEncrypted(metadata.serverUrl, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase) {
- metadata.e2eEncrypted = true
- }
-
- // CHUNCK
- let chunckSize = CCUtility.getChunkSize() * 1000000
- if chunckSize == 0 || metadata.size <= chunckSize {
- metadatasForUpload.append(metadata)
- } else {
- metadata.chunk = true
- metadata.session = NCCommunicationCommon.shared.sessionIdentifierUpload
- metadatasForUpload.append(tableMetadata.init(value: metadata))
- }
+ metadatasForUpload.append(metadata)
}
NCManageDatabase.shared.addMetadatas(metadatasForUpload)
diff --git a/iOSClient/Select/NCSelect.storyboard b/iOSClient/Select/NCSelect.storyboard
index ee4fae6ba..1602e151d 100644
--- a/iOSClient/Select/NCSelect.storyboard
+++ b/iOSClient/Select/NCSelect.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="EAU-PF-EEd">
+<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="EAU-PF-EEd">
<device id="retina6_5" 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"/>
@@ -18,7 +18,7 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="0HI-k1-SD0">
- <rect key="frame" x="0.0" y="0.0" width="414" height="862"/>
+ <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="0.0" minimumInteritemSpacing="0.0" id="D7P-75-aB1">
<size key="itemSize" width="0.0" height="0.0"/>
@@ -38,7 +38,7 @@
<constraints>
<constraint firstItem="vaA-85-uNN" firstAttribute="trailing" secondItem="0HI-k1-SD0" secondAttribute="trailing" id="Dk4-c3-6wl"/>
<constraint firstItem="0HI-k1-SD0" firstAttribute="top" secondItem="MaM-Im-7sc" secondAttribute="top" id="GKj-QM-2Yy"/>
- <constraint firstItem="vaA-85-uNN" firstAttribute="bottom" secondItem="0HI-k1-SD0" secondAttribute="bottom" id="onM-VP-itM"/>
+ <constraint firstAttribute="bottom" secondItem="0HI-k1-SD0" secondAttribute="bottom" id="onM-VP-itM"/>
<constraint firstItem="0HI-k1-SD0" firstAttribute="leading" secondItem="vaA-85-uNN" secondAttribute="leading" id="uLL-RT-YFO"/>
</constraints>
</view>
@@ -50,6 +50,7 @@
</barButtonItem>
</navigationItem>
<connections>
+ <outlet property="bottomContraint" destination="onM-VP-itM" id="kqE-5e-xj2"/>
<outlet property="buttonCancel" destination="qHj-AF-EN7" id="Fky-XJ-BxL"/>
<outlet property="collectionView" destination="0HI-k1-SD0" id="xme-mG-bnz"/>
</connections>
diff --git a/iOSClient/Select/NCSelect.swift b/iOSClient/Select/NCSelect.swift
index 7ab1f908e..76f0ecaa5 100644
--- a/iOSClient/Select/NCSelect.swift
+++ b/iOSClient/Select/NCSelect.swift
@@ -30,8 +30,9 @@ import NCCommunication
class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresentationControllerDelegate, NCListCellDelegate, NCGridCellDelegate, NCSectionHeaderMenuDelegate, NCEmptyDataSetDelegate {
- @IBOutlet fileprivate weak var collectionView: UICollectionView!
- @IBOutlet fileprivate weak var buttonCancel: UIBarButtonItem!
+ @IBOutlet private var collectionView: UICollectionView!
+ @IBOutlet private var buttonCancel: UIBarButtonItem!
+ @IBOutlet private var bottomContraint: NSLayoutConstraint?
private var selectCommandViewSelect: NCSelectCommandView?
@@ -49,7 +50,7 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
@objc var includeImages = false
@objc var enableSelectFile = false
@objc var type = ""
- @objc var items: [Any] = []
+ @objc var items: [tableMetadata] = []
var titleCurrentFolder = NCBrandOptions.shared.brand
var serverUrl = ""
@@ -79,7 +80,7 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
private let headerHeight: CGFloat = 50
private var headerRichWorkspaceHeight: CGFloat = 0
- private let footerHeight: CGFloat = 100
+ private let footerHeight: CGFloat = 50
private var shares: [tableShare]?
@@ -116,6 +117,8 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
buttonCancel.title = NSLocalizedString("_cancel_", comment: "")
+ bottomContraint?.constant = UIApplication.shared.keyWindow?.rootViewController?.view.safeAreaInsets.bottom ?? 0
+
// Empty
emptyDataSet = NCEmptyDataSet(view: collectionView, offset: headerHeight, delegate: self)
@@ -134,6 +137,8 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
selectCommandViewSelect?.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
selectCommandViewSelect?.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
selectCommandViewSelect?.heightAnchor.constraint(equalToConstant: 80).isActive = true
+
+ bottomContraint?.constant = 80
}
if typeOfCommandView == .copyMove {
@@ -141,11 +146,16 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
self.view.addSubview(selectCommandViewSelect!)
selectCommandViewSelect?.selectView = self
selectCommandViewSelect?.translatesAutoresizingMaskIntoConstraints = false
-
+ if items.contains(where: { $0.lock }) {
+ selectCommandViewSelect?.moveButton?.isEnabled = false
+ selectCommandViewSelect?.moveButton?.titleLabel?.isEnabled = false
+ }
selectCommandViewSelect?.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
selectCommandViewSelect?.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
selectCommandViewSelect?.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
selectCommandViewSelect?.heightAnchor.constraint(equalToConstant: 150).isActive = true
+
+ bottomContraint?.constant = 150
}
NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil)
@@ -255,26 +265,7 @@ class NCSelect: UIViewController, UIGestureRecognizerDelegate, UIAdaptivePresent
}
func createFolderButtonPressed(_ sender: UIButton) {
-
- let alertController = UIAlertController(title: NSLocalizedString("_create_folder_", comment: ""), message: "", preferredStyle: .alert)
-
- alertController.addTextField { textField in
- textField.autocapitalizationType = UITextAutocapitalizationType.words
- }
-
- let actionSave = UIAlertAction(title: NSLocalizedString("_save_", comment: ""), style: .default) { (_: UIAlertAction) in
- if let fileName = alertController.textFields?.first?.text {
- self.createFolder(with: fileName)
- }
- }
-
- let actionCancel = UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel) { (_: UIAlertAction) in
- print("You've pressed cancel button")
- }
-
- alertController.addAction(actionSave)
- alertController.addAction(actionCancel)
-
+ let alertController = UIAlertController.createFolder(serverUrl: serverUrl, urlBase: activeAccount)
self.present(alertController, animated: true, completion: nil)
}
@@ -710,16 +701,6 @@ extension NCSelect {
}
}
- func createFolder(with fileName: String) {
-
- NCNetworking.shared.createFolder(fileName: fileName, serverUrl: serverUrl, account: activeAccount.account, urlBase: activeAccount.urlBase) { errorCode, errorDescription in
-
- if errorCode != 0 {
- NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
- }
- }
- }
-
func loadFolder() {
networkInProgress = true
diff --git a/iOSClient/Settings/Acknowledgements.m b/iOSClient/Settings/Acknowledgements.m
index 971bdf17f..a808f36de 100644
--- a/iOSClient/Settings/Acknowledgements.m
+++ b/iOSClient/Settings/Acknowledgements.m
@@ -31,12 +31,13 @@
- (void)viewDidLoad
{
[super viewDidLoad];
-
+
NSURL *rtfPath = [[NSBundle mainBundle] URLForResource:@"Acknowledgements" withExtension:@"rtf"];
NSAttributedString *attributedStringWithRtf = [[NSAttributedString alloc] initWithURL:rtfPath options:@{NSDocumentTypeDocumentAttribute:NSRTFTextDocumentType} documentAttributes:nil error:nil];
self.txtTermini.attributedText = attributedStringWithRtf;
-
+
+ self.navigationController.navigationBar.backgroundColor = [UIColor whiteColor];
self.view.backgroundColor = [UIColor whiteColor];
self.title = NSLocalizedString(@"_acknowledgements_", nil);
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(cancelPressed)];
diff --git a/iOSClient/Settings/Acknowledgements.rtf b/iOSClient/Settings/Acknowledgements.rtf
index 57bd9041d..d947cf932 100644
--- a/iOSClient/Settings/Acknowledgements.rtf
+++ b/iOSClient/Settings/Acknowledgements.rtf
@@ -1,4 +1,4 @@
-{\rtf1\ansi\ansicpg1252\cocoartf2636
+{\rtf1\ansi\ansicpg1252\cocoartf2638
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fswiss\fcharset0 Helvetica-Bold;}
{\colortbl;\red255\green255\blue255;}
{\*\expandedcolortbl;;}
@@ -8,7 +8,7 @@
\f0\fs24 \cf0 \
This software contains additional third party software. \
All the third party software included or linked is redistributed under the terms and conditions of their original licenses. \
-____________________________________________\
+__________________________________\
\
\f1\b Nextcloud iOS Communication Library\
@@ -29,12 +29,12 @@ SwiftyXMLParser -
\f1\b \
SwiftyJSON -
\f0\b0 MIT License (MIT) \
-____________________________________________\
+__________________________________\
\
\f1\b NYMnemonic - BIP 39 style mnemonic codes\
-\f0\b0 ____________________________________________\
+\f0\b0 __________________________________\
\
\f1\b OpenSSL\
@@ -45,7 +45,7 @@ ____________________________________________\
\f1\b \
\f0\b0 Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\
-____________________________________________\
+__________________________________\
\
\f1\b Realm
@@ -54,7 +54,7 @@ ____________________________________________\
Apache License 2.0\
\
Copyright (c) 2014-2017 https://realm.io\
-____________________________________________\
+__________________________________\
\
\f1\b UICKeyChainStore
@@ -63,7 +63,7 @@ ____________________________________________\
MIT License\
\
Copyright (c) kishikawa katsumi\
-____________________________________________\
+__________________________________\
\
\f1\b XLForm
@@ -72,7 +72,7 @@ ____________________________________________\
MIT License\
\
Copyright (c) Xmartlabs ( http://xmartlabs.com )\
-____________________________________________\
+__________________________________\
\
\f1\b KTVHTTPCache
@@ -81,7 +81,7 @@ ____________________________________________\
MIT License\
\
Copyright (c) libobjc\
-____________________________________________\
+__________________________________\
\
\f1\b SVGKit
@@ -90,7 +90,7 @@ ____________________________________________\
https://github.com/SVGKit/SVGKit/blob/3.x/LICENSE\
\
Copyright (c) 2010-2011 Matt Rajca, 2011-2015 various authors (c) Tipbit Inc\
-____________________________________________\
+__________________________________\
\
\f1\b SwiftRichString
@@ -99,7 +99,7 @@ ____________________________________________\
MIT License\
\
Copyright (c) Daniele Margutti\
-____________________________________________\
+__________________________________\
\
\f1\b QRCodeReader
@@ -108,7 +108,7 @@ ____________________________________________\
MIT License\
\
Copyright (c) Yannick Loriot\
-____________________________________________\
+__________________________________\
\
\f1\b Parchment
@@ -117,16 +117,7 @@ ____________________________________________\
MIT License\
\
Copyright (c) Martin Rechsteiner\
-____________________________________________\
-\
-
-\f1\b FSCalendar
-\f0\b0 \
-\
-MIT License\
-\
-Copyright (c) Wenchao Ding\
-____________________________________________\
+__________________________________\
\
\f1\b DropDown
@@ -135,7 +126,7 @@ ____________________________________________\
MIT License\
\
Copyright (c) Kevin Hirsch\
-____________________________________________\
+__________________________________\
\
\f1\b TLPhotoPicker
@@ -144,7 +135,7 @@ ____________________________________________\
MIT License\
\
Copyright (c) wade.hawk, junhyi.park@gmail.com\
-____________________________________________\
+__________________________________\
\
\f1\b SwiftEntryKit
@@ -153,7 +144,7 @@ ____________________________________________\
MIT License\
\
Copyright (c) Daniel Huri, huri000@gmail.com\
-____________________________________________\
+__________________________________\
\
\f1\b FloatingPanel
@@ -162,14 +153,14 @@ ____________________________________________\
MIT License\
\
Copyright (c) Shin Yamamoto shin@scenee.com\
-____________________________________________\
+__________________________________\
\
\f1\b MarkdownKit
\f0\b0 \
\
MIT License\
-____________________________________________\
+__________________________________\
\
\f1\b Firebase Crashlytics
@@ -178,7 +169,7 @@ ____________________________________________\
Apache License 2.0\
\
Copyright (c) Google Inc.\
-____________________________________________\
+__________________________________\
\
\f1\b Queuer
@@ -187,7 +178,7 @@ ____________________________________________\
MIT License\
\
Copyright (c) Fabrizio Brancati\
-____________________________________________\
+__________________________________\
\
\f1\b TOPasscodeViewController
@@ -196,7 +187,7 @@ ____________________________________________\
MIT License\
\
Copyright (c) Tim Oliver\
-____________________________________________\
+__________________________________\
\
\f1\b JGProgressHUD
@@ -205,5 +196,15 @@ ____________________________________________\
MIT License\
\
Copyright (c) Jonas Gessner\
-____________________________________________\
+__________________________________\
+\
+
+\f1\b EasyTipView
+\f0\b0 \
+\
+MIT License\
+\
+Copyright (c) Teodor Patras\
+__________________________________\
+\
} \ No newline at end of file
diff --git a/iOSClient/Settings/CCAdvanced.m b/iOSClient/Settings/CCAdvanced.m
index 65c255791..625e94c2d 100755
--- a/iOSClient/Settings/CCAdvanced.m
+++ b/iOSClient/Settings/CCAdvanced.m
@@ -54,11 +54,11 @@
[row.cellConfig setObject:NCBrandColor.shared.label forKey:@"textLabel.textColor"];
[section addFormRow:row];
- // Format Compatibility + Live Photo
+ // Format Compatibility + Live Photo + Delete asset
section = [XLFormSectionDescriptor formSection];
[form addFormSection:section];
- section.footerTitle = [NSString stringWithFormat:@"%@\n%@", NSLocalizedString(@"_format_compatibility_footer_", nil), NSLocalizedString(@"_upload_mov_livephoto_footer_", nil)];
+ section.footerTitle = [NSString stringWithFormat:@"%@\n%@\n%@", NSLocalizedString(@"_format_compatibility_footer_", nil), NSLocalizedString(@"_upload_mov_livephoto_footer_", nil), NSLocalizedString(@"_remove_photo_CameraRoll_desc_", nil)];
row = [XLFormRowDescriptor formRowDescriptorWithTag:@"formatCompatibility" rowType:XLFormRowDescriptorTypeBooleanSwitch title:NSLocalizedString(@"_format_compatibility_", nil)];
row.cellConfigAtConfigure[@"backgroundColor"] = NCBrandColor.shared.secondarySystemGroupedBackground;
@@ -75,6 +75,14 @@
[row.cellConfig setObject:[UIFont systemFontOfSize:15.0] forKey:@"textLabel.font"];
[row.cellConfig setObject:NCBrandColor.shared.label forKey:@"textLabel.textColor"];
[section addFormRow:row];
+
+ row = [XLFormRowDescriptor formRowDescriptorWithTag:@"removePhotoCameraRoll" rowType:XLFormRowDescriptorTypeBooleanSwitch title:NSLocalizedString(@"_remove_photo_CameraRoll_", nil)];
+ row.cellConfigAtConfigure[@"backgroundColor"] = NCBrandColor.shared.secondarySystemGroupedBackground;
+ if ([CCUtility getRemovePhotoCameraRoll]) 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];
// Disable Local Cache After Upload
@@ -173,12 +181,8 @@
row.action.formBlock = ^(XLFormRowDescriptor * sender) {
[self deselectFormRow:sender];
-
- NCViewerQuickLook *viewerQuickLook = [[NCViewerQuickLook alloc] initWith:[NSURL fileURLWithPath:NCCommunicationCommon.shared.filenamePathLog] editingMode:false metadata:nil];
- UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewerQuickLook];
- navigationController.modalPresentationStyle = UIModalPresentationFullScreen;
-
- [self presentViewController:navigationController animated:YES completion:nil];
+ NCViewerQuickLook *viewerQuickLook = [[NCViewerQuickLook alloc] initWith:[NSURL fileURLWithPath:NCCommunicationCommon.shared.filenamePathLog] isEditingEnabled:false metadata:nil];
+ [self presentViewController:viewerQuickLook animated:YES completion:nil];
};
[section addFormRow:row];
@@ -355,6 +359,11 @@
[CCUtility setLivePhoto:[[rowDescriptor.value valueData] boolValue]];
}
+
+ if ([rowDescriptor.tag isEqualToString:@"removePhotoCameraRoll"]) {
+
+ [CCUtility setRemovePhotoCameraRoll:[[rowDescriptor.value valueData] boolValue]];
+ }
if ([rowDescriptor.tag isEqualToString:@"disableLocalCacheAfterUpload"]) {
@@ -419,9 +428,11 @@
[CCUtility removeGroupDirectoryProviderStorage];
[CCUtility removeGroupLibraryDirectory];
-
+
[CCUtility removeDocumentsDirectory];
[CCUtility removeTemporaryDirectory];
+
+ [[NCKTVHTTPCache shared] deleteAllCache];
[CCUtility createDirectoryStandard];
diff --git a/iOSClient/Settings/CCManageAutoUpload.m b/iOSClient/Settings/CCManageAutoUpload.m
index e5fe1d773..a3c9e2c02 100644
--- a/iOSClient/Settings/CCManageAutoUpload.m
+++ b/iOSClient/Settings/CCManageAutoUpload.m
@@ -118,34 +118,6 @@
[row.cellConfig setObject:NCBrandColor.shared.label forKey:@"textLabel.textColor"];
[section addFormRow:row];
- // Delete asset
-
- section = [XLFormSectionDescriptor formSection];
- [form addFormSection:section];
-
- row = [XLFormRowDescriptor formRowDescriptorWithTag:@"removePhotoCameraRoll" rowType:XLFormRowDescriptorTypeBooleanSwitch title:NSLocalizedString(@"_remove_photo_CameraRoll_", nil)];
- row.cellConfigAtConfigure[@"backgroundColor"] = NCBrandColor.shared.secondarySystemGroupedBackground;
- row.hidden = [NSString stringWithFormat:@"$%@==0", @"autoUpload"];
- if (activeAccount.autoUploadDeleteAssetLocalIdentifier) 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];
-
- // Auto Upload Background
-
- section = [XLFormSectionDescriptor formSection];
- [form addFormSection:section];
-
- row = [XLFormRowDescriptor formRowDescriptorWithTag:@"autoUploadBackground" rowType:XLFormRowDescriptorTypeBooleanSwitch title:NSLocalizedString(@"_autoupload_background_", nil)];
- row.cellConfigAtConfigure[@"backgroundColor"] = NCBrandColor.shared.secondarySystemGroupedBackground;
- row.hidden = [NSString stringWithFormat:@"$%@==0", @"autoUpload"];
- if (activeAccount.autoUploadBackground) 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];
-
// Auto Upload Full
section = [XLFormSectionDescriptor formSection];
[form addFormSection:section];
@@ -219,20 +191,7 @@
[super viewWillAppear:animated];
appDelegate.activeViewController = self;
-
- // Request permission for camera roll access
- [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
- switch (status) {
- case PHAuthorizationStatusRestricted:
- NSLog(@"[LOG] user can't grant access to camera roll");
- break;
- case PHAuthorizationStatusDenied:
- NSLog(@"[LOG] user denied access to camera roll");
- break;
- default:
- break;
- }
- }];
+ [[NCAskAuthorization shared] askAuthorizationPhotoLibraryWithViewController:self completion:^(BOOL status) { }];
}
- (void)initialize
@@ -280,41 +239,6 @@
[self reloadForm];
}
-
- if ([rowDescriptor.tag isEqualToString:@"removePhotoCameraRoll"]) {
-
- [[NCManageDatabase shared] setAccountAutoUploadProperty:@"autoUploadDeleteAssetLocalIdentifier" state:[[rowDescriptor.value valueData] boolValue]];
- }
-
- if ([rowDescriptor.tag isEqualToString:@"autoUploadBackground"]) {
-
- if ([[rowDescriptor.value valueData] boolValue] == YES) {
-
- [[NCAskAuthorization shared] askAuthorizationLocationManagerWithCompletion: ^(BOOL hasFullPermissions) {
-
- if (hasFullPermissions == YES) {
-
- UIAlertController *alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"_autoupload_background_title_", nil) message:NSLocalizedString(@"_autoupload_background_msg_", nil) preferredStyle:UIAlertControllerStyleAlert];
- UIAlertAction *okAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"_ok_", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {}];
-
- [alertController addAction:okAction];
- [self presentViewController:alertController animated:YES completion:nil];
-
- [[NCManageDatabase shared] setAccountAutoUploadProperty:@"autoUploadBackground" state:YES];
- [[NCAutoUpload shared] startSignificantChangeUpdates];
-
- } else {
-
- [self reloadForm];
- }
- }];
-
- } else {
-
- [[NCManageDatabase shared] setAccountAutoUploadProperty:@"autoUploadBackground" state:NO];
- [[NCAutoUpload shared] stopSignificantChangeUpdates];
- }
- }
if ([rowDescriptor.tag isEqualToString:@"autoUploadFull"]) {
@@ -380,11 +304,7 @@
XLFormRowDescriptor *rowAutoUploadVideo = [self.form formRowWithTag:@"autoUploadVideo"];
XLFormRowDescriptor *rowAutoUploadWWAnVideo = [self.form formRowWithTag:@"autoUploadWWAnVideo"];
-
- XLFormRowDescriptor *rowRemovePhotoCameraRoll = [self.form formRowWithTag:@"removePhotoCameraRoll"];
- XLFormRowDescriptor *rowAutoUploadBackground = [self.form formRowWithTag:@"autoUploadBackground"];
-
XLFormRowDescriptor *rowAutoUploadFull = [self.form formRowWithTag:@"autoUploadFull"];
XLFormRowDescriptor *rowAutoUploadCreateSubfolder = [self.form formRowWithTag:@"autoUploadCreateSubfolder"];
@@ -408,13 +328,7 @@
if (activeAccount.autoUploadWWAnVideo)
[rowAutoUploadWWAnVideo setValue:@1]; else [rowAutoUploadWWAnVideo setValue:@0];
-
- if (activeAccount.autoUploadDeleteAssetLocalIdentifier)
- [rowRemovePhotoCameraRoll setValue:@1]; else [rowRemovePhotoCameraRoll setValue:@0];
-
- if (activeAccount.autoUploadBackground)
- [rowAutoUploadBackground setValue:@1]; else [rowAutoUploadBackground setValue:@0];
-
+
if (activeAccount.autoUploadFull)
[rowAutoUploadFull setValue:@1]; else [rowAutoUploadFull setValue:@0];
@@ -428,11 +342,7 @@
rowAutoUploadVideo.hidden = [NSString stringWithFormat:@"$%@==0", @"autoUpload"];
rowAutoUploadWWAnVideo.hidden = [NSString stringWithFormat:@"$%@==0", @"autoUpload"];
-
- rowRemovePhotoCameraRoll.hidden = [NSString stringWithFormat:@"$%@==0", @"autoUpload"];
- rowAutoUploadBackground.hidden = [NSString stringWithFormat:@"$%@==0", @"autoUpload"];
-
rowAutoUploadFull.hidden = [NSString stringWithFormat:@"$%@==0", @"autoUpload"];
rowAutoUploadCreateSubfolder.hidden = [NSString stringWithFormat:@"$%@==0", @"autoUpload"];
@@ -466,22 +376,14 @@
else sectionName = @"";
break;
case 4:
- if (activeAccount.autoUpload) sectionName = NSLocalizedString(@"_remove_photo_CameraRoll_desc_", nil);
- else sectionName = @"";
- break;
- case 5:
- if (activeAccount.autoUpload) sectionName = NSLocalizedString(@"_autoupload_description_background_", nil);
- else sectionName = @"";
- break;
- case 6:
if (activeAccount.autoUpload) sectionName = NSLocalizedString(@"_autoupload_fullphotos_footer_", nil);
else sectionName = @"";
break;
- case 7:
+ case 5:
if (activeAccount.autoUpload) sectionName = NSLocalizedString(@"_autoupload_create_subfolder_footer_", nil);
else sectionName = @"";
break;
- case 8:
+ case 6:
if (activeAccount.autoUpload) sectionName = NSLocalizedString(@"_autoupload_filenamemask_footer_", nil);
else sectionName = @"";
break;
diff --git a/iOSClient/Settings/NCManageAutoUploadFileName.swift b/iOSClient/Settings/NCManageAutoUploadFileName.swift
index b402f4739..3f4774c7f 100644
--- a/iOSClient/Settings/NCManageAutoUploadFileName.swift
+++ b/iOSClient/Settings/NCManageAutoUploadFileName.swift
@@ -213,10 +213,4 @@ class NCManageAutoUploadFileName: XLFormViewController {
return String(format: NSLocalizedString("_preview_filename_", comment: ""), "MM,MMM,DD,YY,YYYY and HH,hh,mm,ss,ampm") + ":" + "\n\n" + returnString
}
-
- // MARK: -
-
- override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
- return NCGlobal.shared.heightCellSettings
- }
}
diff --git a/iOSClient/Settings/NCSettings.m b/iOSClient/Settings/NCSettings.m
index 223241d21..6f9ab8b11 100644
--- a/iOSClient/Settings/NCSettings.m
+++ b/iOSClient/Settings/NCSettings.m
@@ -74,7 +74,7 @@
// Lock active YES/NO
row = [XLFormRowDescriptor formRowDescriptorWithTag:@"bloccopasscode" rowType:XLFormRowDescriptorTypeButton title:NSLocalizedString(@"_lock_not_active_", nil)];
row.cellConfigAtConfigure[@"backgroundColor"] = NCBrandColor.shared.secondarySystemGroupedBackground;
- [row.cellConfig setObject:[[UIImage imageNamed:@"lock.open"] imageWithColor:NCBrandColor.shared.gray size:25] forKey:@"imageView.image"];
+ [row.cellConfig setObject:[[UIImage imageNamed:@"lock_open"] imageWithColor:NCBrandColor.shared.gray size:25] forKey:@"imageView.image"];
[row.cellConfig setObject:[UIFont systemFontOfSize:15.0] forKey:@"textLabel.font"];
[row.cellConfig setObject:NCBrandColor.shared.label forKey:@"textLabel.textColor"];
[row.cellConfig setObject:@(NSTextAlignmentLeft) forKey:@"textLabel.textAlignment"];
@@ -239,7 +239,7 @@
[rowBloccoPasscode.cellConfig setObject:[[UIImage imageNamed:@"lock"] imageWithColor:NCBrandColor.shared.gray size:25] forKey:@"imageView.image"];
} else {
rowBloccoPasscode.title = NSLocalizedString(@"_lock_not_active_", nil);
- [rowBloccoPasscode.cellConfig setObject:[[UIImage imageNamed:@"lock.open"] imageWithColor:NCBrandColor.shared.gray size:25] forKey:@"imageView.image"];
+ [rowBloccoPasscode.cellConfig setObject:[[UIImage imageNamed:@"lock_open"] imageWithColor:NCBrandColor.shared.gray size:25] forKey:@"imageView.image"];
}
if ([CCUtility getEnableTouchFaceID]) [rowEnableTouchDaceID setValue:@1]; else [rowEnableTouchDaceID setValue:@0];
diff --git a/iOSClient/Share/Advanced/NCShareAdvancePermission.swift b/iOSClient/Share/Advanced/NCShareAdvancePermission.swift
new file mode 100644
index 000000000..2e0da22c0
--- /dev/null
+++ b/iOSClient/Share/Advanced/NCShareAdvancePermission.swift
@@ -0,0 +1,192 @@
+//
+// NCShareAdvancePermission.swift
+// Nextcloud
+//
+// Created by T-systems on 09/08/21.
+// Copyright © 2022 Henrik Storch. All rights reserved.
+//
+// Author Henrik Storch <henrik.storch@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
+import SVGKit
+import CloudKit
+
+class NCShareAdvancePermission: UITableViewController, NCShareAdvanceFotterDelegate, NCShareDetail {
+ func dismissShareAdvanceView(shouldSave: Bool) {
+ guard shouldSave else {
+ guard oldTableShare?.hasChanges(comparedTo: share) != false else {
+ navigationController?.popViewController(animated: true)
+ return
+ }
+ let alert = UIAlertController(
+ title: NSLocalizedString("_cancel_request_", comment: ""),
+ message: NSLocalizedString("_discard_changes_info_", comment: ""),
+ preferredStyle: .alert)
+ alert.addAction(UIAlertAction(
+ title: NSLocalizedString("_discard_changes_", comment: ""),
+ style: .destructive,
+ handler: { _ in self.navigationController?.popViewController(animated: true) }))
+ alert.addAction(UIAlertAction(title: NSLocalizedString("_continue_editing_", comment: ""), style: .default))
+ self.present(alert, animated: true)
+ return
+ }
+ if isNewShare {
+ networking?.createShare(option: share)
+ } else {
+ networking?.updateShare(option: share)
+ }
+ navigationController?.popViewController(animated: true)
+ }
+
+ var oldTableShare: tableShare?
+ var share: NCTableShareable!
+ var isNewShare: Bool { share is NCTableShareOptions }
+ var metadata: tableMetadata!
+ var shareConfig: NCShareConfig!
+ var networking: NCShareNetworking?
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ self.shareConfig = NCShareConfig(parentMetadata: metadata, share: share)
+
+ tableView.estimatedRowHeight = tableView.rowHeight
+ tableView.rowHeight = UITableView.automaticDimension
+ self.setNavigationTitle()
+ self.navigationItem.hidesBackButton = true
+ if #available(iOS 13.0, *) {
+ // disbale pull to dimiss
+ isModalInPresentation = true
+ }
+ }
+
+ override func viewWillLayoutSubviews() {
+ super.viewWillLayoutSubviews()
+ guard tableView.tableHeaderView == nil, tableView.tableFooterView == nil else { return }
+ setupHeaderView()
+ setupFooterView()
+ }
+
+ func setupFooterView() {
+ guard let footerView = (Bundle.main.loadNibNamed("NCShareAdvancePermissionFooter", owner: self, options: nil)?.first as? NCShareAdvancePermissionFooter) else { return }
+ footerView.setupUI(delegate: self)
+
+ // tableFooterView can't use auto layout directly
+ let container = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 120))
+ container.addSubview(footerView)
+ tableView.tableFooterView = container
+ footerView.translatesAutoresizingMaskIntoConstraints = false
+ footerView.bottomAnchor.constraint(equalTo: container.bottomAnchor).isActive = true
+ footerView.heightAnchor.constraint(equalTo: container.heightAnchor).isActive = true
+ footerView.widthAnchor.constraint(equalTo: container.widthAnchor).isActive = true
+ }
+
+ func setupHeaderView() {
+ guard let headerView = (Bundle.main.loadNibNamed("NCShareAdvancePermissionHeader", owner: self, options: nil)?.first as? NCShareAdvancePermissionHeader) else { return }
+ headerView.setupUI(with: metadata)
+
+ let container = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 220))
+ container.addSubview(headerView)
+ tableView.tableHeaderView = container
+ headerView.translatesAutoresizingMaskIntoConstraints = false
+ headerView.topAnchor.constraint(equalTo: container.topAnchor).isActive = true
+ headerView.heightAnchor.constraint(equalTo: container.heightAnchor).isActive = true
+ headerView.widthAnchor.constraint(equalTo: container.widthAnchor).isActive = true
+ }
+
+ override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
+ if section == 0 {
+ return NSLocalizedString("_permissions_", comment: "")
+ } else if section == 1 {
+ return NSLocalizedString("_advanced_", comment: "")
+ } else { return nil }
+ }
+
+ override func numberOfSections(in tableView: UITableView) -> Int {
+ return 2
+ }
+
+ override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+ if section == 0 {
+ // check reshare permission, if restricted add note
+ let maxPermission = metadata.directory ? NCGlobal.shared.permissionMaxFolderShare : NCGlobal.shared.permissionMaxFileShare
+ return shareConfig.resharePermission != maxPermission ? shareConfig.permissions.count + 1 : shareConfig.permissions.count
+ } else if section == 1 {
+ return shareConfig.advanced.count
+ } else { return 0 }
+ }
+
+ override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+ guard let cell = shareConfig.cellFor(indexPath: indexPath) else {
+ let noteCell = UITableViewCell(style: .subtitle, reuseIdentifier: "noteCell")
+ noteCell.detailTextLabel?.text = NSLocalizedString("_share_reshare_restricted_", comment: "")
+ noteCell.detailTextLabel?.isEnabled = false
+ noteCell.isUserInteractionEnabled = false
+ noteCell.detailTextLabel?.numberOfLines = 0
+ return noteCell
+ }
+ if let cell = cell as? NCShareDateCell { cell.onReload = tableView.reloadData }
+ return cell
+ }
+
+ override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+ tableView.deselectRow(at: indexPath, animated: true)
+ guard let cellConfig = shareConfig.config(for: indexPath) else { return }
+ guard let cellConfig = cellConfig as? NCShareDetails else {
+ cellConfig.didSelect(for: share)
+ tableView.reloadData()
+ return
+ }
+
+ switch cellConfig {
+ case .hideDownload:
+ share.hideDownload.toggle()
+ tableView.reloadData()
+ case .expirationDate:
+ let cell = tableView.cellForRow(at: indexPath) as? NCShareDateCell
+ cell?.textField.becomeFirstResponder()
+ case .password:
+ guard share.password.isEmpty else {
+ share.password = ""
+ tableView.reloadData()
+ return
+ }
+ let alertController = UIAlertController.password(titleKey: "_share_password_") { password in
+ self.share.password = password ?? ""
+ tableView.reloadData()
+ }
+ self.present(alertController, animated: true)
+ case .note:
+ let storyboard = UIStoryboard(name: "NCShare", bundle: nil)
+ guard let viewNewUserComment = storyboard.instantiateViewController(withIdentifier: "NCShareNewUserAddComment") as? NCShareNewUserAddComment else { return }
+ viewNewUserComment.metadata = self.metadata
+ viewNewUserComment.share = self.share
+ viewNewUserComment.onDismiss = tableView.reloadData
+ self.navigationController?.pushViewController(viewNewUserComment, animated: true)
+ case .label:
+ let alertController = UIAlertController.withTextField(titleKey: "_share_link_name_") { textField in
+ textField.placeholder = cellConfig.title
+ textField.text = self.share.label
+ } completion: { newValue in
+ self.share.label = newValue ?? ""
+ self.setNavigationTitle()
+ tableView.reloadData()
+ }
+ self.present(alertController, animated: true)
+ }
+ }
+}
diff --git a/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.swift b/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.swift
new file mode 100644
index 000000000..ffad1f97e
--- /dev/null
+++ b/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.swift
@@ -0,0 +1,66 @@
+//
+// NCShareAdvancePermissionFooter.swift
+// Nextcloud
+//
+// Created by T-systems on 09/08/21.
+// Copyright © 2022 Henrik Storch. All rights reserved.
+//
+// Author Henrik Storch <henrik.storch@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
+
+protocol NCShareAdvanceFotterDelegate: AnyObject {
+ var isNewShare: Bool { get }
+ func dismissShareAdvanceView(shouldSave: Bool)
+}
+
+class NCShareAdvancePermissionFooter: UIView {
+ @IBOutlet weak var buttonCancel: UIButton!
+ @IBOutlet weak var buttonNext: UIButton!
+ weak var delegate: NCShareAdvanceFotterDelegate?
+
+ func setupUI(delegate: NCShareAdvanceFotterDelegate?) {
+ self.delegate = delegate
+ backgroundColor = .clear
+
+ buttonCancel.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)
+
+ 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)
+ }
+
+ @objc func cancelClicked() {
+ delegate?.dismissShareAdvanceView(shouldSave: false)
+ }
+
+ @objc func nextClicked() {
+ delegate?.dismissShareAdvanceView(shouldSave: true)
+ }
+}
diff --git a/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.xib b/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.xib
new file mode 100644
index 000000000..40b515e7d
--- /dev/null
+++ b/iOSClient/Share/Advanced/NCShareAdvancePermissionFooter.xib
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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="retina6_1" 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>
+ <objects>
+ <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+ <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="NCShareAdvancePermissionFooter" customModule="Nextcloud" customModuleProvider="target">
+ <rect key="frame" x="0.0" y="0.0" width="688" height="376"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="rCI-63-PtL">
+ <rect key="frame" x="16" y="168" width="320" height="50"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="50" id="vdI-sH-cTb"/>
+ </constraints>
+ <fontDescription key="fontDescription" type="system" pointSize="18"/>
+ <color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+ <state key="normal" title="Cancel">
+ <color key="titleColor" systemColor="labelColor"/>
+ </state>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="249" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Mg2-Ou-yoX">
+ <rect key="frame" x="352" y="168" width="320" height="50"/>
+ <color key="backgroundColor" systemColor="systemBlueColor"/>
+ <fontDescription key="fontDescription" type="system" pointSize="18"/>
+ <state key="normal" title="Send share">
+ <color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </state>
+ </button>
+ </subviews>
+ <viewLayoutGuide key="safeArea" id="sWQ-1v-CIt"/>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <constraints>
+ <constraint firstItem="Mg2-Ou-yoX" firstAttribute="leading" secondItem="rCI-63-PtL" secondAttribute="trailing" constant="16" id="4Px-cS-Hta"/>
+ <constraint firstItem="sWQ-1v-CIt" firstAttribute="trailing" secondItem="Mg2-Ou-yoX" secondAttribute="trailing" constant="16" id="Jdi-WJ-zVF"/>
+ <constraint firstItem="sWQ-1v-CIt" firstAttribute="centerY" secondItem="Mg2-Ou-yoX" secondAttribute="centerY" id="SzT-aI-aUz"/>
+ <constraint firstItem="Mg2-Ou-yoX" firstAttribute="height" secondItem="rCI-63-PtL" secondAttribute="height" id="bNp-Nf-uMw"/>
+ <constraint firstItem="Mg2-Ou-yoX" firstAttribute="width" secondItem="rCI-63-PtL" secondAttribute="width" id="dfu-GZ-P99"/>
+ <constraint firstItem="rCI-63-PtL" firstAttribute="centerY" secondItem="Mg2-Ou-yoX" secondAttribute="centerY" id="hEl-ij-sMX"/>
+ <constraint firstItem="rCI-63-PtL" firstAttribute="leading" secondItem="sWQ-1v-CIt" secondAttribute="leading" constant="16" id="s9t-ud-ofw"/>
+ </constraints>
+ <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+ <connections>
+ <outlet property="buttonCancel" destination="rCI-63-PtL" id="SoT-Ko-LL5"/>
+ <outlet property="buttonNext" destination="Mg2-Ou-yoX" id="F2d-L5-dHo"/>
+ </connections>
+ <point key="canvasLocation" x="139.13043478260872" y="43.526785714285715"/>
+ </view>
+ </objects>
+ <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>
+ </resources>
+</document>
diff --git a/iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.swift b/iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.swift
new file mode 100644
index 000000000..8ff5828b7
--- /dev/null
+++ b/iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.swift
@@ -0,0 +1,51 @@
+//
+// NCShareAdvancePermissionHeader.swift
+// Nextcloud
+//
+// Created by T-systems on 10/08/21.
+// Copyright © 2022 Henrik Storch. All rights reserved.
+//
+// Author Henrik Storch <henrik.storch@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 NCShareAdvancePermissionHeader: UIView {
+ @IBOutlet weak var imageView: UIImageView!
+ @IBOutlet weak var fileName: UILabel!
+ @IBOutlet weak var info: UILabel!
+ @IBOutlet weak var fullWidthImageView: UIImageView!
+
+ func setupUI(with metadata: tableMetadata) {
+ if FileManager.default.fileExists(atPath: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) {
+ fullWidthImageView.image = NCUtility.shared.getImageMetadata(metadata, for: frame.height)
+ fullWidthImageView.contentMode = .scaleAspectFill
+ imageView.isHidden = true
+ } else {
+ if metadata.directory {
+ imageView.image = NCBrandColor.cacheImages.folder
+ } else if !metadata.iconName.isEmpty {
+ imageView.image = UIImage(named: metadata.iconName)
+ } else {
+ imageView.image = NCBrandColor.cacheImages.file
+ }
+ }
+ fileName.text = metadata.fileNameView
+ fileName.textColor = NCBrandColor.shared.label
+ info.textColor = NCBrandColor.shared.secondaryLabel
+ info.text = CCUtility.transformedSize(metadata.size) + ", " + CCUtility.dateDiff(metadata.date as Date)
+ }
+}
diff --git a/iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.xib b/iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.xib
new file mode 100644
index 000000000..beb60d8c5
--- /dev/null
+++ b/iOSClient/Share/Advanced/NCShareAdvancePermissionHeader.xib
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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="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"/>
+ <view contentMode="scaleToFill" id="wbW-yR-MZC" customClass="NCShareAdvancePermissionHeader" customModule="Nextcloud" customModuleProvider="target">
+ <rect key="frame" x="0.0" y="0.0" width="414" height="210"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="cki-Ql-o1I">
+ <rect key="frame" x="0.0" y="0.0" width="414" height="150"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="150" id="9GH-KF-f8P"/>
+ </constraints>
+ </imageView>
+ <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Dkw-QP-be6">
+ <rect key="frame" x="16" y="27" width="96" height="96"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="96" id="TW7-8v-NRJ"/>
+ <constraint firstAttribute="width" constant="96" id="Vbz-xZ-L5k"/>
+ </constraints>
+ </imageView>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pu4-Nd-M08">
+ <rect key="frame" x="16" y="166" width="382" height="18"/>
+ <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="15"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="VaC-Fz-kHk">
+ <rect key="frame" x="16" y="188" width="383" height="16"/>
+ <fontDescription key="fontDescription" type="system" pointSize="13"/>
+ <color key="textColor" red="0.76862745099999996" green="0.77647058820000003" blue="0.77647058820000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ <viewLayoutGuide key="safeArea" id="KLE-vd-Dsn"/>
+ <constraints>
+ <constraint firstItem="pu4-Nd-M08" firstAttribute="leading" secondItem="KLE-vd-Dsn" secondAttribute="leading" constant="16" id="0Uy-ra-MtM"/>
+ <constraint firstItem="pu4-Nd-M08" firstAttribute="top" secondItem="cki-Ql-o1I" secondAttribute="bottom" constant="16" id="Cce-7Y-iw9"/>
+ <constraint firstAttribute="trailing" secondItem="VaC-Fz-kHk" secondAttribute="trailing" constant="15" id="Ebg-3T-03W"/>
+ <constraint firstItem="Dkw-QP-be6" firstAttribute="leading" secondItem="KLE-vd-Dsn" secondAttribute="leading" constant="16" id="KPc-al-RWN"/>
+ <constraint firstItem="KLE-vd-Dsn" firstAttribute="top" secondItem="cki-Ql-o1I" secondAttribute="top" id="KsC-jf-M6F"/>
+ <constraint firstAttribute="trailing" secondItem="cki-Ql-o1I" secondAttribute="trailing" id="Wdl-Rb-Pjy"/>
+ <constraint firstItem="VaC-Fz-kHk" firstAttribute="leading" secondItem="pu4-Nd-M08" secondAttribute="leading" id="Ycb-wy-uL6"/>
+ <constraint firstItem="cki-Ql-o1I" firstAttribute="leading" secondItem="KLE-vd-Dsn" secondAttribute="leading" id="ZlH-LU-x2x"/>
+ <constraint firstItem="KLE-vd-Dsn" firstAttribute="trailing" secondItem="pu4-Nd-M08" secondAttribute="trailing" constant="16" id="bO0-yQ-OWX"/>
+ <constraint firstItem="Dkw-QP-be6" firstAttribute="centerY" secondItem="cki-Ql-o1I" secondAttribute="centerY" id="dME-jJ-PwO"/>
+ <constraint firstItem="VaC-Fz-kHk" firstAttribute="top" secondItem="pu4-Nd-M08" secondAttribute="bottom" constant="4" id="zkb-Jm-sin"/>
+ </constraints>
+ <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+ <connections>
+ <outlet property="fileName" destination="pu4-Nd-M08" id="iLj-ya-6hM"/>
+ <outlet property="fullWidthImageView" destination="cki-Ql-o1I" id="KYn-3Y-SZH"/>
+ <outlet property="imageView" destination="Dkw-QP-be6" id="wzX-Sb-Ajt"/>
+ <outlet property="info" destination="VaC-Fz-kHk" id="n9O-6c-qsd"/>
+ </connections>
+ <point key="canvasLocation" x="35.625" y="27.5"/>
+ </view>
+ </objects>
+</document>
diff --git a/iOSClient/Share/Advanced/NCShareCells.swift b/iOSClient/Share/Advanced/NCShareCells.swift
new file mode 100644
index 000000000..4806f6350
--- /dev/null
+++ b/iOSClient/Share/Advanced/NCShareCells.swift
@@ -0,0 +1,304 @@
+//
+// NCShareCells.swift
+// Nextcloud
+//
+// Created by Henrik Storch on 18.03.22.
+// Copyright © 2022 Henrik Storch. All rights reserved.
+//
+// Author Henrik Storch <henrik.storch@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
+
+protocol NCShareCellConfig {
+ var title: String { get }
+ func getCell(for share: NCTableShareable) -> UITableViewCell
+ func didSelect(for share: NCTableShareable)
+}
+
+protocol NCToggleCellConfig: NCShareCellConfig {
+ func isOn(for share: NCTableShareable) -> Bool
+ func didChange(_ share: NCTableShareable, to newValue: Bool)
+}
+
+extension NCToggleCellConfig {
+ func getCell(for share: NCTableShareable) -> UITableViewCell {
+ return NCShareToggleCell(isOn: isOn(for: share))
+ }
+
+ func didSelect(for share: NCTableShareable) {
+ didChange(share, to: !isOn(for: share))
+ }
+}
+
+protocol NCPermission: NCToggleCellConfig {
+ static var forDirectory: [Self] { get }
+ static var forFile: [Self] { get }
+ func hasResharePermission(for parentPermission: Int) -> Bool
+}
+
+enum NCUserPermission: CaseIterable, NCPermission {
+ func hasResharePermission(for parentPermission: Int) -> Bool {
+ return ((permissionBitFlag & parentPermission) != 0)
+ }
+
+ var permissionBitFlag: Int {
+ switch self {
+ case .reshare: return NCGlobal.shared.permissionShareShare
+ case .edit: return NCGlobal.shared.permissionUpdateShare
+ case .create: return NCGlobal.shared.permissionCreateShare
+ case .delete: return NCGlobal.shared.permissionDeleteShare
+ }
+ }
+
+ func didChange(_ share: NCTableShareable, to newValue: Bool) {
+ share.permissions ^= permissionBitFlag
+ }
+
+ func isOn(for share: NCTableShareable) -> Bool {
+ return (share.permissions & permissionBitFlag) != 0
+ }
+
+ case reshare, edit, create, delete
+ static let forDirectory: [NCUserPermission] = NCUserPermission.allCases
+ static let forFile: [NCUserPermission] = [.reshare, .edit]
+
+ var title: String {
+ switch self {
+ case .reshare: return NSLocalizedString("_share_can_reshare_", comment: "")
+ case .edit: return NSLocalizedString("_share_can_change_", comment: "")
+ case .create: return NSLocalizedString("_share_can_create_", comment: "")
+ case .delete: return NSLocalizedString("_share_can_delete_", comment: "")
+ }
+ }
+}
+
+enum NCLinkPermission: NCPermission {
+ func didChange(_ share: NCTableShareable, to newValue: Bool) {
+ guard self != .allowEdit || newValue else {
+ share.permissions = NCGlobal.shared.permissionReadShare
+ return
+ }
+ share.permissions = permissionValue
+ }
+
+ func hasResharePermission(for parentPermission: Int) -> Bool {
+ permissionValue & parentPermission == permissionValue
+ }
+
+ var permissionValue: Int {
+ switch self {
+ case .allowEdit:
+ return CCUtility.getPermissionsValue(
+ byCanEdit: true,
+ andCanCreate: true,
+ andCanChange: true,
+ andCanDelete: true,
+ andCanShare: false,
+ andIsFolder: false)
+ case .viewOnly:
+ return CCUtility.getPermissionsValue(
+ byCanEdit: false,
+ andCanCreate: false,
+ andCanChange: false,
+ andCanDelete: false,
+ // not possible to create "read-only" shares without reshare option
+ // https://github.com/nextcloud/server/blame/f99876997a9119518fe5f7ad3a3a51d33459d4cc/apps/files_sharing/lib/Controller/ShareAPIController.php#L1104-L1107
+ andCanShare: true,
+ andIsFolder: true)
+ case .uploadEdit:
+ return CCUtility.getPermissionsValue(
+ byCanEdit: true,
+ andCanCreate: true,
+ andCanChange: true,
+ andCanDelete: true,
+ andCanShare: false,
+ andIsFolder: true)
+ case .fileDrop:
+ return NCGlobal.shared.permissionCreateShare
+ }
+ }
+
+ func isOn(for share: NCTableShareable) -> Bool {
+ switch self {
+ case .allowEdit: return CCUtility.isAnyPermission(toEdit: share.permissions)
+ case .viewOnly: return !CCUtility.isAnyPermission(toEdit: share.permissions) && share.permissions != NCGlobal.shared.permissionCreateShare
+ case .uploadEdit: return CCUtility.isAnyPermission(toEdit: share.permissions) && share.permissions != NCGlobal.shared.permissionCreateShare
+ case .fileDrop: return share.permissions == NCGlobal.shared.permissionCreateShare
+ }
+ }
+
+ var title: String {
+ switch self {
+ case .allowEdit: return NSLocalizedString("_share_can_change_", comment: "")
+ case .viewOnly: return NSLocalizedString("_share_read_only_", comment: "")
+ case .uploadEdit: return NSLocalizedString("_share_allow_upload_", comment: "")
+ case .fileDrop: return NSLocalizedString("_share_file_drop_", comment: "")
+ }
+ }
+
+ case allowEdit, viewOnly, uploadEdit, fileDrop
+ static let forDirectory: [NCLinkPermission] = [.viewOnly, .uploadEdit, .fileDrop]
+ static let forFile: [NCLinkPermission] = [.allowEdit]
+}
+
+enum NCShareDetails: CaseIterable, NCShareCellConfig {
+ func didSelect(for share: NCTableShareable) {
+ switch self {
+ case .hideDownload: share.hideDownload.toggle()
+ case .expirationDate: return
+ case .password: return
+ case .note: return
+ case .label: return
+ }
+ }
+
+ func getCell(for share: NCTableShareable) -> UITableViewCell {
+ switch self {
+ case .hideDownload:
+ return NCShareToggleCell(isOn: share.hideDownload)
+ case .expirationDate:
+ return NCShareDateCell(share: share)
+ case .password: return NCShareToggleCell(isOn: !share.password.isEmpty, customIcons: ("lock", "lock_open"))
+ case .note:
+ let cell = UITableViewCell(style: .value1, reuseIdentifier: "shareNote")
+ cell.detailTextLabel?.text = share.note
+ cell.accessoryType = .disclosureIndicator
+ return cell
+ case .label:
+ let cell = UITableViewCell(style: .value1, reuseIdentifier: "shareLabel")
+ cell.detailTextLabel?.text = share.label
+ return cell
+ }
+ }
+
+ var title: String {
+ switch self {
+ case .hideDownload: return NSLocalizedString("_share_hide_download_", comment: "")
+ case .expirationDate: return NSLocalizedString("_share_expiration_date_", comment: "")
+ case .password: return NSLocalizedString("_share_password_protect_", comment: "")
+ case .note: return NSLocalizedString("_share_note_recipient_", comment: "")
+ case .label: return NSLocalizedString("_share_link_name_", comment: "")
+ }
+ }
+
+ case label, hideDownload, expirationDate, password, note
+ static let forLink: [NCShareDetails] = NCShareDetails.allCases
+ static let forUser: [NCShareDetails] = [.expirationDate, .note]
+}
+
+struct NCShareConfig {
+ let permissions: [NCPermission]
+ let advanced: [NCShareDetails]
+ let share: NCTableShareable
+ let resharePermission: Int
+
+ init(parentMetadata: tableMetadata, share: NCTableShareable) {
+ self.share = share
+ self.resharePermission = parentMetadata.sharePermissionsCollaborationServices
+ let type: NCPermission.Type = share.shareType == NCShareCommon.shared.SHARE_TYPE_LINK ? NCLinkPermission.self : NCUserPermission.self
+ self.permissions = parentMetadata.directory ? type.forDirectory : type.forFile
+ self.advanced = share.shareType == NCShareCommon.shared.SHARE_TYPE_LINK ? NCShareDetails.forLink : NCShareDetails.forUser
+ }
+
+ func cellFor(indexPath: IndexPath) -> UITableViewCell? {
+ let cellConfig = config(for: indexPath)
+ let cell = cellConfig?.getCell(for: share)
+ cell?.textLabel?.text = cellConfig?.title
+ if let cellConfig = cellConfig as? NCPermission, !cellConfig.hasResharePermission(for: resharePermission) {
+ cell?.isUserInteractionEnabled = false
+ cell?.textLabel?.isEnabled = false
+ }
+ return cell
+ }
+
+ func didSelectRow(at indexPath: IndexPath) {
+ let cellConfig = config(for: indexPath)
+ cellConfig?.didSelect(for: share)
+ }
+
+ func config(for indexPath: IndexPath) -> NCShareCellConfig? {
+ if indexPath.section == 0, indexPath.row < permissions.count {
+ return permissions[indexPath.row]
+ } else if indexPath.section == 1, indexPath.row < advanced.count {
+ return advanced[indexPath.row]
+ } else { return nil }
+ }
+}
+
+class NCShareToggleCell: UITableViewCell {
+ typealias CustomToggleIcon = (onIconName: String?, offIconName: String?)
+ init(isOn: Bool, customIcons: CustomToggleIcon? = nil) {
+ super.init(style: .default, reuseIdentifier: "toggleCell")
+ self.accessibilityValue = isOn ? NSLocalizedString("_on_", comment: "") : NSLocalizedString("_off_", comment: "")
+
+ guard let customIcons = customIcons,
+ let iconName = isOn ? customIcons.onIconName : customIcons.offIconName else {
+ self.accessoryType = isOn ? .checkmark : .none
+ return
+ }
+ let image = NCUtility.shared.loadImage(named: iconName, color: NCBrandColor.shared.brandElement, size: self.frame.height - 26)
+ self.accessoryView = UIImageView(image: image)
+ }
+
+ required init?(coder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+}
+
+class NCShareDateCell: UITableViewCell {
+ let picker = UIDatePicker()
+ let textField = UITextField()
+
+ var onReload: (() -> Void)?
+
+ init(share: NCTableShareable) {
+ super.init(style: .value1, reuseIdentifier: "shareExpDate")
+ picker.datePickerMode = .date
+ picker.minimumDate = Date()
+ if #available(iOS 13.4, *) {
+ picker.preferredDatePickerStyle = .wheels
+ }
+ picker.action(for: .valueChanged) { datePicker in
+ guard let datePicker = datePicker as? UIDatePicker else { return }
+ self.detailTextLabel?.text = DateFormatter.shareExpDate.string(from: datePicker.date)
+ }
+ accessoryView = textField
+
+ let toolbar = UIToolbar.toolbar {
+ self.resignFirstResponder()
+ share.expirationDate = nil
+ self.onReload?()
+ } completion: {
+ self.resignFirstResponder()
+ share.expirationDate = self.picker.date as NSDate
+ self.onReload?()
+ }
+
+ textField.isAccessibilityElement = false
+ textField.accessibilityElementsHidden = true
+ textField.inputAccessoryView = toolbar.wrappedSafeAreaContainer
+ textField.inputView = picker
+
+ if let expDate = share.expirationDate {
+ detailTextLabel?.text = DateFormatter.shareExpDate.string(from: expDate as Date)
+ }
+ }
+
+ required public init?(coder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+}
diff --git a/iOSClient/Share/Advanced/NCShareNewUserAddComment.swift b/iOSClient/Share/Advanced/NCShareNewUserAddComment.swift
new file mode 100644
index 000000000..73af68588
--- /dev/null
+++ b/iOSClient/Share/Advanced/NCShareNewUserAddComment.swift
@@ -0,0 +1,95 @@
+//
+// NCShareNewUserAddComment.swift
+// Nextcloud
+//
+// Created by TSI-mc on 21/06/21.
+// Copyright © 2022 Henrik Storch. All rights reserved.
+//
+// Author Henrik Storch <henrik.storch@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
+import SVGKit
+
+class NCShareNewUserAddComment: UIViewController, NCShareDetail {
+
+ @IBOutlet weak var headerContainerView: UIView!
+ @IBOutlet weak var sharingLabel: UILabel!
+ @IBOutlet weak var noteTextField: UITextView!
+
+ let contentInsets: CGFloat = 16
+ var onDismiss: (() -> Void)?
+
+ public var share: NCTableShareable!
+ public var metadata: tableMetadata!
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ self.setNavigationTitle()
+
+ NotificationCenter.default.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillHideNotification, object: nil)
+ NotificationCenter.default.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
+
+ sharingLabel.text = NSLocalizedString("_share_note_recipient_", comment: "")
+
+ noteTextField.textContainerInset = UIEdgeInsets(top: contentInsets, left: contentInsets, bottom: contentInsets, right: contentInsets)
+ noteTextField.text = share.note
+ let toolbar = UIToolbar.toolbar {
+ self.noteTextField.resignFirstResponder()
+ self.noteTextField.text = ""
+ self.share.note = ""
+ } completion: {
+ self.noteTextField.resignFirstResponder()
+ self.share.note = self.noteTextField.text
+ }
+
+ noteTextField.inputAccessoryView = toolbar.wrappedSafeAreaContainer
+
+ guard let headerView = (Bundle.main.loadNibNamed("NCShareAdvancePermissionHeader", owner: self, options: nil)?.first as? NCShareAdvancePermissionHeader) else { return }
+ headerContainerView.addSubview(headerView)
+ headerView.frame = headerContainerView.frame
+ headerView.translatesAutoresizingMaskIntoConstraints = false
+ headerView.topAnchor.constraint(equalTo: headerContainerView.topAnchor).isActive = true
+ headerView.bottomAnchor.constraint(equalTo: headerContainerView.bottomAnchor).isActive = true
+ headerView.leftAnchor.constraint(equalTo: headerContainerView.leftAnchor).isActive = true
+ headerView.rightAnchor.constraint(equalTo: headerContainerView.rightAnchor).isActive = true
+
+ headerView.setupUI(with: metadata)
+ }
+
+ override func viewWillDisappear(_ animated: Bool) {
+ super.viewWillDisappear(animated)
+ share.note = noteTextField.text
+ onDismiss?()
+ }
+
+ @objc func adjustForKeyboard(notification: Notification) {
+ guard let keyboardValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue,
+ let globalTextViewFrame = noteTextField.superview?.convert(noteTextField.frame, to: nil) else { return }
+
+ let keyboardScreenEndFrame = keyboardValue.cgRectValue
+ let portionCovoredByLeyboard = globalTextViewFrame.maxY - keyboardScreenEndFrame.minY
+
+ if notification.name == UIResponder.keyboardWillHideNotification || portionCovoredByLeyboard < 0 {
+ noteTextField.contentInset = .zero
+ } else {
+ noteTextField.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: portionCovoredByLeyboard, right: 0)
+ }
+
+ noteTextField.scrollIndicatorInsets = noteTextField.contentInset
+ }
+}
diff --git a/iOSClient/Share/NCShareUserDropDownCell.xib b/iOSClient/Share/NCSearchUserDropDownCell.xib
index 9701c08c8..fa63960bc 100755
--- a/iOSClient/Share/NCShareUserDropDownCell.xib
+++ b/iOSClient/Share/NCSearchUserDropDownCell.xib
@@ -1,15 +1,15 @@
<?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" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19455" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="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="19454"/>
<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"/>
- <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="NCShareUserDropDownCell" customModule="Nextcloud" customModuleProvider="target">
+ <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="NCSearchUserDropDownCell" customModule="Nextcloud" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="487" height="50"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
diff --git a/iOSClient/Share/NCShare+Helper.swift b/iOSClient/Share/NCShare+Helper.swift
new file mode 100644
index 000000000..bb108652c
--- /dev/null
+++ b/iOSClient/Share/NCShare+Helper.swift
@@ -0,0 +1,109 @@
+//
+// NCShare+Helper.swift
+// Nextcloud
+//
+// Created by Henrik Storch on 19.03.22.
+// Copyright © 2022 Henrik Storch. All rights reserved.
+//
+// Author Henrik Storch <henrik.storch@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
+
+extension tableShare: NCTableShareable { }
+extension NCCommunicationShare: NCTableShareable { }
+
+protocol NCTableShareable: AnyObject {
+ var shareType: Int { get set }
+ var permissions: Int { get set }
+
+ var idShare: Int { get set }
+ var shareWith: String { get set }
+
+ var hideDownload: Bool { get set }
+ var password: String { get set }
+ var label: String { get set }
+ var note: String { get set }
+ var expirationDate: NSDate? { get set }
+ var shareWithDisplayname: String { get set }
+}
+
+extension NCTableShareable {
+ var expDateString: String? {
+ guard let date = expirationDate else { return nil }
+ let dateFormatter = DateFormatter()
+ dateFormatter.dateFormat = "YYYY-MM-dd HH:mm:ss"
+ return dateFormatter.string(from: date as Date)
+ }
+
+ func hasChanges(comparedTo other: NCTableShareable) -> Bool {
+ return other.shareType != shareType
+ || other.permissions != permissions
+ || other.hideDownload != hideDownload
+ || other.password != password
+ || other.label != label
+ || other.note != note
+ || other.expirationDate != expirationDate
+ }
+}
+
+class NCTableShareOptions: NCTableShareable {
+ var shareType: Int
+ var permissions: Int
+
+ var idShare: Int = 0
+ var shareWith: String = ""
+
+ var hideDownload: Bool = false
+ var password: String = ""
+ var label: String = ""
+ var note: String = ""
+ var expirationDate: NSDate?
+ var shareWithDisplayname: String = ""
+
+ private init(shareType: Int, metadata: tableMetadata, password: String?) {
+ self.permissions = NCManageDatabase.shared.getCapabilitiesServerInt(account: metadata.account, elements: ["ocs", "data", "capabilities", "files_sharing", "default_permissions"]) & metadata.sharePermissionsCollaborationServices
+ self.shareType = shareType
+ if let password = password {
+ self.password = password
+ }
+ }
+
+ convenience init(sharee: NCCommunicationSharee, metadata: tableMetadata, password: String?) {
+ self.init(shareType: sharee.shareType, metadata: metadata, password: password)
+ self.shareWith = sharee.shareWith
+ }
+
+ static func shareLink(metadata: tableMetadata, password: String?) -> NCTableShareOptions {
+ return NCTableShareOptions(shareType: NCShareCommon.shared.SHARE_TYPE_LINK, metadata: metadata, password: password)
+ }
+}
+
+protocol NCShareDetail {
+ var share: NCTableShareable! { get }
+}
+
+extension NCShareDetail where Self: UIViewController {
+ func setNavigationTitle() {
+ title = NSLocalizedString("_share_", comment: "") + " – "
+ if share.shareType == NCShareCommon.shared.SHARE_TYPE_LINK {
+ title! += share.label.isEmpty ? NSLocalizedString("_share_link_", comment: "") : share.label
+ } else {
+ title! += share.shareWithDisplayname.isEmpty ? share.shareWith : share.shareWithDisplayname
+ }
+ }
+}
diff --git a/iOSClient/Share/NCShare+NCCellDelegate.swift b/iOSClient/Share/NCShare+NCCellDelegate.swift
new file mode 100644
index 000000000..78dfd1074
--- /dev/null
+++ b/iOSClient/Share/NCShare+NCCellDelegate.swift
@@ -0,0 +1,69 @@
+//
+// NCShare+NCCellDelegate.swift
+// Nextcloud
+//
+// Created by Henrik Storch on 03.01.22.
+// Copyright © 2022 Henrik Storch. All rights reserved.
+//
+// Author Henrik Storch <henrik.storch@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
+
+// MARK: - NCCell Delegates
+extension NCShare: NCShareLinkCellDelegate, NCShareUserCellDelegate {
+
+ func copyInternalLink(sender: Any) {
+ 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
+ if errorCode == 0, let metadata = metadata {
+ let internalLink = appDelegate.urlBase + "/index.php/f/" + metadata.fileId
+ NCShareCommon.shared.copyLink(link: internalLink, viewController: self, sender: sender)
+ } else {
+ NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+ }
+ }
+ }
+
+ func tapCopy(with tableShare: tableShare?, sender: Any) {
+ guard let tableShare = tableShare else {
+ return copyInternalLink(sender: sender)
+ }
+ NCShareCommon.shared.copyLink(link: tableShare.url, viewController: self, sender: sender)
+ }
+
+ func tapMenu(with tableShare: tableShare?, sender: Any) {
+ if let tableShare = tableShare {
+ self.toggleShareMenu(for: tableShare)
+ } else {
+ self.makeNewLinkShare()
+ }
+ }
+
+ func showProfile(with tableShare: tableShare?, sender: Any) {
+ guard let tableShare = tableShare else { return }
+ showProfileMenu(userId: tableShare.shareWith)
+ }
+
+ func quickStatus(with tableShare: tableShare?, sender: Any) {
+ guard let tableShare = tableShare,
+ let metadata = metadata,
+ tableShare.shareType != NCGlobal.shared.permissionDefaultFileRemoteShareNoSupportShareOption else { return }
+ self.toggleUserPermissionMenu(isDirectory: metadata.directory, tableShare: tableShare)
+ }
+}
diff --git a/iOSClient/Share/NCShare.storyboard b/iOSClient/Share/NCShare.storyboard
index 23d454487..05040c5e5 100644
--- a/iOSClient/Share/NCShare.storyboard
+++ b/iOSClient/Share/NCShare.storyboard
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19455" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Ts3-RO-A9l">
+<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="Ts3-RO-A9l">
<device id="retina5_5" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19454"/>
+ <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>
@@ -54,66 +55,9 @@
<rect key="frame" x="5" y="0.0" width="404" height="726"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="c94-b9-Sim">
- <rect key="frame" x="0.0" y="250" width="404" height="476"/>
+ <rect key="frame" x="0.0" y="133" width="404" height="593"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</tableView>
- <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="8Cj-cK-AKZ">
- <rect key="frame" x="5" y="139" width="40" height="40"/>
- <constraints>
- <constraint firstAttribute="height" constant="40" id="CCv-Uu-Vel"/>
- <constraint firstAttribute="width" constant="40" id="egJ-xl-yj4"/>
- </constraints>
- </imageView>
- <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="HPl-mj-r5E">
- <rect key="frame" x="5" y="199" width="40" height="40"/>
- <constraints>
- <constraint firstAttribute="width" constant="40" id="6IE-lI-M6i"/>
- <constraint firstAttribute="height" constant="40" id="Odq-bX-Hoz"/>
- </constraints>
- </imageView>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Share link" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SQW-aQ-ydN">
- <rect key="frame" x="53" y="150" width="261" height="18"/>
- <fontDescription key="fontDescription" type="system" pointSize="15"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Share link" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YYp-o8-YJP">
- <rect key="frame" x="53" y="195" width="317" height="18"/>
- <fontDescription key="fontDescription" type="system" pointSize="15"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="wordWrap" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pfo-D0-W7b">
- <rect key="frame" x="53" y="216.66666666666666" width="317" height="35"/>
- <constraints>
- <constraint firstAttribute="height" constant="35" id="f8b-mp-xLJ"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="14"/>
- <color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- <nil key="highlightedColor"/>
- </label>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Qek-aQ-NjE" userLabel="ButtonMenu">
- <rect key="frame" x="374" y="149" width="20" height="20"/>
- <constraints>
- <constraint firstAttribute="width" constant="20" id="BAT-jK-rUt"/>
- <constraint firstAttribute="height" constant="20" id="zc5-W6-SXG"/>
- </constraints>
- <state key="normal" image="shareMenu"/>
- <connections>
- <action selector="touchUpInsideButtonMenu:" destination="bgO-Rz-2M1" eventType="touchUpInside" id="ogE-7H-hMG"/>
- </connections>
- </button>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="cLd-wD-cSC" userLabel="ButtonCopy">
- <rect key="frame" x="324" y="149" width="20" height="20"/>
- <constraints>
- <constraint firstAttribute="width" constant="20" id="Bzl-zW-yzd"/>
- <constraint firstAttribute="height" constant="20" id="RIV-EC-kwC"/>
- </constraints>
- <state key="normal" image="shareCopy"/>
- <connections>
- <action selector="touchUpInsideButtonCopy:" destination="bgO-Rz-2M1" eventType="touchUpInside" id="ccu-6N-Tm4"/>
- </connections>
- </button>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oBQ-TP-qof" userLabel="View Shared with you by">
<rect key="frame" x="-5" y="10" width="409" height="90"/>
<subviews>
@@ -172,46 +116,17 @@
<action selector="searchFieldDidEndOnExitWithTextField:" destination="bgO-Rz-2M1" eventType="editingDidEndOnExit" id="xH6-YR-5W9"/>
</connections>
</textField>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FFi-7t-C8U" userLabel="ButtonCopy">
- <rect key="frame" x="375" y="209" width="20" height="20"/>
- <constraints>
- <constraint firstAttribute="height" constant="20" id="0KI-54-GMc"/>
- <constraint firstAttribute="width" constant="20" id="fcI-Wc-4GE"/>
- </constraints>
- <state key="normal" image="shareCopy"/>
- <connections>
- <action selector="touchUpInsideButtonCopyInernalLink:" destination="bgO-Rz-2M1" eventType="touchUpInside" id="fmb-gx-9PH"/>
- </connections>
- </button>
</subviews>
<constraints>
<constraint firstItem="oBQ-TP-qof" firstAttribute="top" secondItem="X2m-IC-J1u" secondAttribute="top" constant="10" id="09Y-bm-RvQ"/>
- <constraint firstItem="HPl-mj-r5E" firstAttribute="top" secondItem="8Cj-cK-AKZ" secondAttribute="bottom" constant="20" id="0dX-Ni-vDj"/>
<constraint firstAttribute="trailing" secondItem="c94-b9-Sim" secondAttribute="trailing" id="BtN-cJ-TTc"/>
- <constraint firstItem="c94-b9-Sim" firstAttribute="top" secondItem="iSO-mc-0TB" secondAttribute="bottom" constant="125" id="Co6-l6-HiT"/>
- <constraint firstItem="FFi-7t-C8U" firstAttribute="leading" secondItem="YYp-o8-YJP" secondAttribute="trailing" constant="5" id="IE6-R3-yOv"/>
- <constraint firstItem="SQW-aQ-ydN" firstAttribute="centerY" secondItem="8Cj-cK-AKZ" secondAttribute="centerY" id="LtS-8d-L7a"/>
- <constraint firstItem="Qek-aQ-NjE" firstAttribute="centerY" secondItem="8Cj-cK-AKZ" secondAttribute="centerY" id="NYZ-hc-SBk"/>
- <constraint firstItem="SQW-aQ-ydN" firstAttribute="leading" secondItem="8Cj-cK-AKZ" secondAttribute="trailing" constant="8" id="Oby-Ea-MaC"/>
- <constraint firstItem="cLd-wD-cSC" firstAttribute="leading" secondItem="SQW-aQ-ydN" secondAttribute="trailing" constant="10" id="PFh-qU-yXY"/>
- <constraint firstItem="YYp-o8-YJP" firstAttribute="leading" secondItem="HPl-mj-r5E" secondAttribute="trailing" constant="8" id="R36-FW-w0B"/>
- <constraint firstItem="pfo-D0-W7b" firstAttribute="centerY" secondItem="HPl-mj-r5E" secondAttribute="centerY" constant="15" id="Rji-xW-vn7"/>
+ <constraint firstItem="c94-b9-Sim" firstAttribute="top" secondItem="iSO-mc-0TB" secondAttribute="bottom" constant="8" id="Co6-l6-HiT"/>
<constraint firstAttribute="bottom" secondItem="c94-b9-Sim" secondAttribute="bottom" id="Svm-RV-vnl"/>
<constraint firstAttribute="trailing" secondItem="iSO-mc-0TB" secondAttribute="trailing" constant="10" id="Vhu-GP-EJN"/>
- <constraint firstItem="8Cj-cK-AKZ" firstAttribute="leading" secondItem="X2m-IC-J1u" secondAttribute="leading" constant="5" id="WlZ-CY-x4s"/>
<constraint firstAttribute="trailing" secondItem="oBQ-TP-qof" secondAttribute="trailing" id="ZuM-2G-aoM"/>
- <constraint firstItem="Qek-aQ-NjE" firstAttribute="leading" secondItem="cLd-wD-cSC" secondAttribute="trailing" constant="30" id="bSw-vM-d12"/>
<constraint firstItem="iSO-mc-0TB" firstAttribute="leading" secondItem="X2m-IC-J1u" secondAttribute="leading" constant="5" id="d8E-WM-YfC"/>
- <constraint firstItem="FFi-7t-C8U" firstAttribute="centerY" secondItem="HPl-mj-r5E" secondAttribute="centerY" id="fkL-uP-Iob"/>
- <constraint firstItem="YYp-o8-YJP" firstAttribute="centerY" secondItem="HPl-mj-r5E" secondAttribute="centerY" constant="-15" id="iu4-c5-p5k"/>
<constraint firstItem="iSO-mc-0TB" firstAttribute="top" secondItem="X2m-IC-J1u" secondAttribute="top" constant="95" id="jPM-Uo-0lS"/>
- <constraint firstItem="pfo-D0-W7b" firstAttribute="leading" secondItem="HPl-mj-r5E" secondAttribute="trailing" constant="8" symbolic="YES" id="oKN-Ui-VIn"/>
- <constraint firstAttribute="trailing" secondItem="Qek-aQ-NjE" secondAttribute="trailing" constant="10" id="puY-4D-ARy"/>
<constraint firstItem="c94-b9-Sim" firstAttribute="leading" secondItem="X2m-IC-J1u" secondAttribute="leading" id="rvD-u3-Dug"/>
- <constraint firstItem="8Cj-cK-AKZ" firstAttribute="top" secondItem="iSO-mc-0TB" secondAttribute="bottom" constant="14" id="shO-sV-GWB"/>
- <constraint firstItem="cLd-wD-cSC" firstAttribute="centerY" secondItem="8Cj-cK-AKZ" secondAttribute="centerY" id="xia-sb-RNk"/>
- <constraint firstItem="FFi-7t-C8U" firstAttribute="leading" secondItem="pfo-D0-W7b" secondAttribute="trailing" constant="5" id="zez-7B-WAb"/>
- <constraint firstItem="HPl-mj-r5E" firstAttribute="leading" secondItem="X2m-IC-J1u" secondAttribute="leading" constant="5" id="zpN-ax-gny"/>
</constraints>
</view>
</subviews>
@@ -223,20 +138,11 @@
<constraint firstItem="X2m-IC-J1u" firstAttribute="top" secondItem="aV2-U6-JTf" secondAttribute="top" id="aXO-v9-CBF"/>
<constraint firstItem="eAi-wv-a4Y" firstAttribute="trailing" secondItem="X2m-IC-J1u" secondAttribute="trailing" constant="5" id="hVX-vu-qJn"/>
<constraint firstItem="oBQ-TP-qof" firstAttribute="leading" secondItem="eAi-wv-a4Y" secondAttribute="leading" id="r7R-MU-9cw"/>
- <constraint firstItem="eAi-wv-a4Y" firstAttribute="trailing" secondItem="FFi-7t-C8U" secondAttribute="trailing" constant="14" id="xLc-ai-2T1"/>
</constraints>
</view>
<connections>
- <outlet property="buttonCopy" destination="cLd-wD-cSC" id="Sib-oL-uQx"/>
- <outlet property="buttonInternalCopy" destination="FFi-7t-C8U" id="2ez-LZ-iZ0"/>
- <outlet property="buttonMenu" destination="Qek-aQ-NjE" id="xfp-a1-YDn"/>
<outlet property="searchField" destination="iSO-mc-0TB" id="1vY-Js-dGQ"/>
<outlet property="searchFieldTopConstraint" destination="jPM-Uo-0lS" id="yfd-cG-1mu"/>
- <outlet property="shareInternalLinkDescription" destination="pfo-D0-W7b" id="uRy-U9-bQu"/>
- <outlet property="shareInternalLinkImage" destination="HPl-mj-r5E" id="CDi-ev-3eO"/>
- <outlet property="shareInternalLinkLabel" destination="YYp-o8-YJP" id="rir-aT-bt5"/>
- <outlet property="shareLinkImage" destination="8Cj-cK-AKZ" id="dIZ-nv-gyf"/>
- <outlet property="shareLinkLabel" destination="SQW-aQ-ydN" id="nBK-WJ-oKy"/>
<outlet property="sharedWithYouByImage" destination="fKv-xM-rVY" id="EJ0-sV-By8"/>
<outlet property="sharedWithYouByLabel" destination="ngi-GT-jvv" id="Qay-IG-tZh"/>
<outlet property="sharedWithYouByNote" destination="KHG-xj-wfG" id="4m5-u6-7RW"/>
@@ -250,6 +156,130 @@
</objects>
<point key="canvasLocation" x="2689.8550724637685" y="-167.41071428571428"/>
</scene>
+ <!--Share New User Add Comment-->
+ <scene sceneID="JJ2-tz-qZ7">
+ <objects>
+ <viewController storyboardIdentifier="NCShareNewUserAddComment" id="VvU-6J-pzy" customClass="NCShareNewUserAddComment" customModule="Nextcloud" customModuleProvider="target" sceneMemberID="viewController">
+ <view key="view" contentMode="scaleToFill" id="EtF-Pb-SYb">
+ <rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="UNN-v3-g1S">
+ <rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
+ <subviews>
+ <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="rZ9-oE-c21">
+ <rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
+ <subviews>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qVy-Qr-W7j">
+ <rect key="frame" x="0.0" y="0.0" width="414" height="200"/>
+ <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="200" id="GX8-Mb-uqf"/>
+ </constraints>
+ </view>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="YMG-hf-HEX">
+ <rect key="frame" x="0.0" y="200" width="414" height="536"/>
+ <subviews>
+ <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" canCancelContentTouches="NO" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="VT0-1l-5HI">
+ <rect key="frame" x="16" y="60.333333333333286" width="382" height="423.66666666666674"/>
+ <color key="backgroundColor" systemColor="secondarySystemBackgroundColor"/>
+ <constraints>
+ <constraint firstAttribute="height" relation="greaterThanOrEqual" constant="100" id="wqE-G9-M95"/>
+ </constraints>
+ <inset key="scrollIndicatorInsets" minX="0.0" minY="0.0" maxX="10" maxY="0.0"/>
+ <color key="textColor" systemColor="labelColor"/>
+ <fontDescription key="fontDescription" type="system" pointSize="14"/>
+ <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
+ <userDefinedRuntimeAttributes>
+ <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+ <integer key="value" value="10"/>
+ </userDefinedRuntimeAttribute>
+ </userDefinedRuntimeAttributes>
+ <connections>
+ <outlet property="delegate" destination="VvU-6J-pzy" id="cAt-UZ-6KT"/>
+ </connections>
+ </textView>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Sharing" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vkm-Pe-6qd">
+ <rect key="frame" x="16.000000000000004" y="24" width="61.333333333333343" height="20.333333333333329"/>
+ <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="17"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <constraints>
+ <constraint firstItem="vkm-Pe-6qd" firstAttribute="leading" secondItem="YMG-hf-HEX" secondAttribute="leading" constant="16" id="Auk-mC-Mie"/>
+ <constraint firstAttribute="bottom" secondItem="VT0-1l-5HI" secondAttribute="bottom" priority="100" constant="52" id="FYk-Lv-5f6"/>
+ <constraint firstItem="vkm-Pe-6qd" firstAttribute="top" secondItem="YMG-hf-HEX" secondAttribute="top" constant="24" id="L0w-Cz-uK2"/>
+ <constraint firstAttribute="trailing" secondItem="VT0-1l-5HI" secondAttribute="trailing" constant="16" id="TgX-1J-iTO"/>
+ <constraint firstItem="VT0-1l-5HI" firstAttribute="leading" secondItem="YMG-hf-HEX" secondAttribute="leading" constant="16" id="gEq-qv-UTR"/>
+ <constraint firstItem="VT0-1l-5HI" firstAttribute="top" secondItem="vkm-Pe-6qd" secondAttribute="bottom" constant="16" id="ghe-aR-N1L"/>
+ <constraint firstAttribute="height" constant="536" id="oYk-ib-hVx"/>
+ </constraints>
+ </view>
+ </subviews>
+ </stackView>
+ </subviews>
+ <constraints>
+ <constraint firstItem="rZ9-oE-c21" firstAttribute="trailing" secondItem="cdt-uF-sLc" secondAttribute="trailing" id="JLe-cg-49Y"/>
+ <constraint firstItem="rZ9-oE-c21" firstAttribute="bottom" secondItem="cdt-uF-sLc" secondAttribute="bottom" id="fHi-hu-MpS"/>
+ <constraint firstItem="rZ9-oE-c21" firstAttribute="top" secondItem="cdt-uF-sLc" secondAttribute="top" id="od8-4k-3u3"/>
+ <constraint firstItem="rZ9-oE-c21" firstAttribute="width" secondItem="yeM-rG-mCp" secondAttribute="width" id="v9J-mK-SfO"/>
+ <constraint firstItem="rZ9-oE-c21" firstAttribute="leading" secondItem="cdt-uF-sLc" secondAttribute="leading" id="xze-Xh-I92"/>
+ </constraints>
+ <viewLayoutGuide key="contentLayoutGuide" id="cdt-uF-sLc"/>
+ <viewLayoutGuide key="frameLayoutGuide" id="yeM-rG-mCp"/>
+ </scrollView>
+ </subviews>
+ <viewLayoutGuide key="safeArea" id="8hH-o3-iQD"/>
+ <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+ <constraints>
+ <constraint firstItem="UNN-v3-g1S" firstAttribute="top" secondItem="8hH-o3-iQD" secondAttribute="top" id="UD6-u2-ckg"/>
+ <constraint firstItem="8hH-o3-iQD" firstAttribute="bottom" secondItem="UNN-v3-g1S" secondAttribute="bottom" id="WzJ-jl-e33"/>
+ <constraint firstItem="VT0-1l-5HI" firstAttribute="height" relation="lessThanOrEqual" secondItem="EtF-Pb-SYb" secondAttribute="height" constant="-150" id="h3K-2H-qDr"/>
+ <constraint firstItem="UNN-v3-g1S" firstAttribute="leading" secondItem="8hH-o3-iQD" secondAttribute="leading" id="r39-yL-F9v"/>
+ <constraint firstItem="8hH-o3-iQD" firstAttribute="trailing" secondItem="UNN-v3-g1S" secondAttribute="trailing" id="rNm-B2-hl3"/>
+ </constraints>
+ </view>
+ <navigationItem key="navigationItem" id="uC3-gg-Wos"/>
+ <connections>
+ <outlet property="headerContainerView" destination="qVy-Qr-W7j" id="LaE-WS-v1X"/>
+ <outlet property="noteTextField" destination="VT0-1l-5HI" id="Ilz-T9-5BL"/>
+ <outlet property="sharingLabel" destination="vkm-Pe-6qd" id="NVy-Ug-ipx"/>
+ </connections>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="LJ3-hs-98b" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="4261" y="-168"/>
+ </scene>
+ <!--Share Advance Permission-->
+ <scene sceneID="59b-BB-FLA">
+ <objects>
+ <tableViewController storyboardIdentifier="NCShareAdvancePermission" id="r5U-VP-Qhs" customClass="NCShareAdvancePermission" customModule="Nextcloud" customModuleProvider="target" sceneMemberID="viewController">
+ <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="-1" estimatedSectionHeaderHeight="-1" sectionFooterHeight="-1" estimatedSectionFooterHeight="-1" id="lDu-k5-2hT">
+ <rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+ <prototypes>
+ <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" id="0qP-1F-pHW">
+ <rect key="frame" x="0.0" y="44.666666030883789" width="414" height="43.666667938232422"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="0qP-1F-pHW" id="z1u-eI-gTZ">
+ <rect key="frame" x="0.0" y="0.0" width="414" height="43.666667938232422"/>
+ <autoresizingMask key="autoresizingMask"/>
+ </tableViewCellContentView>
+ </tableViewCell>
+ </prototypes>
+ <connections>
+ <outlet property="dataSource" destination="r5U-VP-Qhs" id="OET-a5-qea"/>
+ <outlet property="delegate" destination="r5U-VP-Qhs" id="cDp-4z-0Xt"/>
+ </connections>
+ </tableView>
+ </tableViewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="ITy-jR-JVD" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="3510" y="-169"/>
+ </scene>
</scenes>
<designables>
<designable name="KHG-xj-wfG">
@@ -258,7 +288,14 @@
</designables>
<resources>
<image name="note.text" width="24" height="24"/>
- <image name="shareCopy" width="329" height="329"/>
- <image name="shareMenu" width="329" height="329"/>
+ <systemColor name="labelColor">
+ <color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </systemColor>
+ <systemColor name="secondarySystemBackgroundColor">
+ <color red="0.94901960784313721" green="0.94901960784313721" blue="0.96862745098039216" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ </systemColor>
+ <systemColor name="systemBackgroundColor">
+ <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </systemColor>
</resources>
</document>
diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift
index b43ce3e48..fdad3c3f0 100644
--- a/iOSClient/Share/NCShare.swift
+++ b/iOSClient/Share/NCShare.swift
@@ -4,6 +4,7 @@
//
// Created by Marino Faggiana on 17/07/2019.
// Copyright © 2019 Marino Faggiana. All rights reserved.
+// Copyright © 2022 Henrik Storch. All rights reserved.
//
// Author Marino Faggiana <marino.faggiana@nextcloud.com>
// Author Henrik Storch <henrik.storch@nextcloud.com>
@@ -28,7 +29,7 @@ import DropDown
import NCCommunication
import MarqueeLabel
-class NCShare: UIViewController, UIGestureRecognizerDelegate, NCShareNetworkingDelegate {
+class NCShare: UIViewController, NCShareNetworkingDelegate, NCSharePagingContent {
@IBOutlet weak var viewContainerConstraint: NSLayoutConstraint!
@IBOutlet weak var sharedWithYouByView: UIView!
@@ -38,27 +39,25 @@ class NCShare: UIViewController, UIGestureRecognizerDelegate, NCShareNetworkingD
@IBOutlet weak var sharedWithYouByNote: MarqueeLabel!
@IBOutlet weak var searchFieldTopConstraint: NSLayoutConstraint!
@IBOutlet weak var searchField: UITextField!
- @IBOutlet weak var shareLinkImage: UIImageView!
- @IBOutlet weak var shareLinkLabel: UILabel!
- @IBOutlet weak var shareInternalLinkImage: UIImageView!
- @IBOutlet weak var shareInternalLinkLabel: UILabel!
- @IBOutlet weak var shareInternalLinkDescription: UILabel!
- @IBOutlet weak var buttonInternalCopy: UIButton!
- @IBOutlet weak var buttonCopy: UIButton!
- @IBOutlet weak var buttonMenu: UIButton!
+ var textField: UITextField? { searchField }
+
@IBOutlet weak var tableView: UITableView!
- private let appDelegate = UIApplication.shared.delegate as! AppDelegate
+ weak var appDelegate = UIApplication.shared.delegate as? AppDelegate
public var metadata: tableMetadata?
public var sharingEnabled = true
public var height: CGFloat = 0
- private var shareLinkMenuView: NCShareLinkMenuView?
- private var shareUserMenuView: NCShareUserMenuView?
- private var shareMenuViewWindow: UIView?
+ var canReshare: Bool {
+ guard let metadata = metadata else { return true }
+ return ((metadata.sharePermissionsCollaborationServices & NCGlobal.shared.permissionShareShare) != 0)
+ }
+
+ var shares: (firstShareLink: tableShare?, share: [tableShare]?) = (nil, nil)
+
private var dropDown = DropDown()
- private var networking: NCShareNetworking?
+ var networking: NCShareNetworking?
// MARK: - View Life Cycle
@@ -72,16 +71,6 @@ class NCShare: UIViewController, UIGestureRecognizerDelegate, NCShareNetworkingD
searchField.placeholder = NSLocalizedString("_shareLinksearch_placeholder_", comment: "")
- shareLinkImage.image = NCShareCommon.shared.createLinkAvatar(imageName: "sharebylink", colorCircle: NCBrandColor.shared.brandElement)
- shareLinkLabel.text = NSLocalizedString("_share_link_", comment: "")
- shareLinkLabel.textColor = NCBrandColor.shared.label
- buttonCopy.setImage(UIImage(named: "shareCopy")?.image(color: .gray, size: 50), for: .normal)
-
- shareInternalLinkImage.image = NCShareCommon.shared.createLinkAvatar(imageName: "shareInternalLink", colorCircle: .gray)
- shareInternalLinkLabel.text = NSLocalizedString("_share_internal_link_", comment: "")
- shareInternalLinkDescription.text = NSLocalizedString("_share_internal_link_des_", comment: "")
- buttonInternalCopy.setImage(UIImage(named: "shareCopy")?.image(color: .gray, size: 50), for: .normal)
-
tableView.dataSource = self
tableView.delegate = self
tableView.allowsSelection = false
@@ -92,58 +81,13 @@ class NCShare: UIViewController, UIGestureRecognizerDelegate, NCShareNetworkingD
NotificationCenter.default.addObserver(self, selector: #selector(reloadData), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataNCShare), object: nil)
- // Shared with you by ...
- if let metadata = metadata, !metadata.ownerId.isEmpty, metadata.ownerId != self.appDelegate.userId {
-
- searchFieldTopConstraint.constant = 65
- sharedWithYouByView.isHidden = false
- sharedWithYouByLabel.text = NSLocalizedString("_shared_with_you_by_", comment: "") + " " + metadata.ownerDisplayName
- sharedWithYouByImage.image = NCUtility.shared.loadUserImage(
- for: metadata.ownerId,
- displayName: metadata.ownerDisplayName,
- userBaseUrl: appDelegate)
- let shareAction = UITapGestureRecognizer(target: self, action: #selector(openShareProfile))
- sharedWithYouByImage.addGestureRecognizer(shareAction)
- let shareLabelAction = UITapGestureRecognizer(target: self, action: #selector(openShareProfile))
- sharedWithYouByLabel.addGestureRecognizer(shareLabelAction)
-
- if metadata.note.count > 0 {
- searchFieldTopConstraint.constant = 95
- sharedWithYouByNoteImage.isHidden = false
- sharedWithYouByNoteImage.image = NCUtility.shared.loadImage(named: "note.text", color: .gray)
- sharedWithYouByNote.isHidden = false
- sharedWithYouByNote.text = metadata.note
- sharedWithYouByNote.textColor = NCBrandColor.shared.label
- sharedWithYouByNote.trailingBuffer = sharedWithYouByNote.frame.width
- } else {
- sharedWithYouByNoteImage.isHidden = true
- sharedWithYouByNote.isHidden = true
- }
-
- let fileName = appDelegate.userBaseUrl + "-" + metadata.ownerId + ".png"
-
- if NCManageDatabase.shared.getImageAvatarLoaded(fileName: fileName) == nil {
- let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName
- let etag = NCManageDatabase.shared.getTableAvatar(fileName: fileName)?.etag
-
- NCCommunication.shared.downloadAvatar(user: metadata.ownerId, fileNameLocalPath: fileNameLocalPath, sizeImage: NCGlobal.shared.avatarSize, avatarSizeRounded: NCGlobal.shared.avatarSizeRounded, etag: etag) { _, imageAvatar, _, etag, errorCode, _ in
-
- if errorCode == 0, let etag = etag, let imageAvatar = imageAvatar {
-
- NCManageDatabase.shared.addAvatar(fileName: fileName, etag: etag)
- self.sharedWithYouByImage.image = imageAvatar
-
- } else if errorCode == NCGlobal.shared.errorNotModified, let imageAvatar = NCManageDatabase.shared.setAvatarLoaded(fileName: fileName) {
+ guard let appDelegate = appDelegate, let metadata = metadata else { return }
- self.sharedWithYouByImage.image = imageAvatar
- }
- }
- }
- }
+ checkSharedWithYou()
reloadData()
- networking = NCShareNetworking(metadata: metadata!, urlBase: appDelegate.urlBase, view: self.view, delegate: self)
+ networking = NCShareNetworking(metadata: metadata, urlBase: appDelegate.urlBase, view: self.view, delegate: self)
if sharingEnabled {
let isVisible = (self.navigationController?.topViewController as? NCSharePaging)?.indexPage == .sharing
networking?.readShare(showLoadingIndicator: isVisible)
@@ -151,11 +95,81 @@ class NCShare: UIViewController, UIGestureRecognizerDelegate, NCShareNetworkingD
// changeTheming
NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil)
- NotificationCenter.default.addObserver(self, selector: #selector(changePermissions(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterShareChangePermissions), object: nil)
changeTheming()
}
+ func makeNewLinkShare() {
+ guard
+ let advancePermission = UIStoryboard(name: "NCShare", bundle: nil).instantiateViewController(withIdentifier: "NCShareAdvancePermission") as? NCShareAdvancePermission,
+ let navigationController = self.navigationController,
+ let metadata = self.metadata else { return }
+ self.checkEnforcedPassword(shareType: NCShareCommon.shared.SHARE_TYPE_LINK) { password in
+ advancePermission.networking = self.networking
+ advancePermission.share = NCTableShareOptions.shareLink(metadata: metadata, password: password)
+ advancePermission.metadata = self.metadata
+ navigationController.pushViewController(advancePermission, animated: true)
+ }
+ }
+
+ // Shared with you by ...
+ func checkSharedWithYou() {
+ guard let appDelegate = self.appDelegate, let metadata = metadata, !metadata.ownerId.isEmpty, metadata.ownerId != appDelegate.userId else { return }
+
+ if !canReshare {
+ searchField.isEnabled = false
+ searchField.placeholder = NSLocalizedString("_share_reshare_disabled_", comment: "")
+ }
+
+ searchFieldTopConstraint.constant = 65
+ sharedWithYouByView.isHidden = false
+ sharedWithYouByLabel.text = NSLocalizedString("_shared_with_you_by_", comment: "") + " " + metadata.ownerDisplayName
+ sharedWithYouByImage.image = NCUtility.shared.loadUserImage(
+ for: metadata.ownerId,
+ displayName: metadata.ownerDisplayName,
+ userBaseUrl: appDelegate)
+ sharedWithYouByLabel.accessibilityHint = NSLocalizedString("_show_profile_", comment: "")
+
+ let shareAction = UITapGestureRecognizer(target: self, action: #selector(openShareProfile))
+ sharedWithYouByImage.addGestureRecognizer(shareAction)
+ let shareLabelAction = UITapGestureRecognizer(target: self, action: #selector(openShareProfile))
+ sharedWithYouByLabel.addGestureRecognizer(shareLabelAction)
+
+ if !metadata.note.isEmpty {
+ searchFieldTopConstraint.constant = 95
+ sharedWithYouByNoteImage.isHidden = false
+ sharedWithYouByNoteImage.image = NCUtility.shared.loadImage(named: "note.text", color: .gray)
+ sharedWithYouByNote.isHidden = false
+ sharedWithYouByNote.text = metadata.note
+ sharedWithYouByNote.textColor = NCBrandColor.shared.label
+ sharedWithYouByNote.trailingBuffer = sharedWithYouByNote.frame.width
+ } else {
+ sharedWithYouByNoteImage.isHidden = true
+ sharedWithYouByNote.isHidden = true
+ }
+
+ let fileName = appDelegate.userBaseUrl + "-" + metadata.ownerId + ".png"
+
+ if NCManageDatabase.shared.getImageAvatarLoaded(fileName: fileName) == nil {
+ let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName
+ let etag = NCManageDatabase.shared.getTableAvatar(fileName: fileName)?.etag
+
+ NCCommunication.shared.downloadAvatar(
+ user: metadata.ownerId,
+ fileNameLocalPath: fileNameLocalPath,
+ sizeImage: NCGlobal.shared.avatarSize,
+ avatarSizeRounded: NCGlobal.shared.avatarSizeRounded,
+ etag: etag) { _, imageAvatar, _, etag, errorCode, _ in
+ if errorCode == 0, let etag = etag, let imageAvatar = imageAvatar {
+ NCManageDatabase.shared.addAvatar(fileName: fileName, etag: etag)
+ self.sharedWithYouByImage.image = imageAvatar
+ } else if errorCode == NCGlobal.shared.errorNotModified, let imageAvatar = NCManageDatabase.shared.setAvatarLoaded(fileName: fileName) {
+ self.sharedWithYouByImage.image = imageAvatar
+ }
+ }
+ }
+ }
+
// MARK: - Notification Center
@objc func openShareProfile() {
@@ -167,34 +181,11 @@ class NCShare: UIViewController, UIGestureRecognizerDelegate, NCShareNetworkingD
tableView.reloadData()
}
- @objc func changePermissions(_ notification: NSNotification) {
-
- if let userInfo = notification.userInfo as NSDictionary? {
- if let idShare = userInfo["idShare"] as? Int, let permissions = userInfo["permissions"] as? Int, let hideDownload = userInfo["hideDownload"] as? Bool {
- networking?.updateShare(idShare: idShare, password: nil, permissions: permissions, note: nil, label: nil, expirationDate: nil, hideDownload: hideDownload)
- }
- }
- }
-
// MARK: -
@objc func reloadData() {
- let shares = NCManageDatabase.shared.getTableShares(metadata: metadata!)
- if shares.firstShareLink == nil {
- buttonMenu.setImage(UIImage(named: "shareAdd")?.image(color: .gray, size: 50), for: .normal)
- buttonCopy.isHidden = true
- } else {
- buttonMenu.setImage(UIImage(named: "shareMenu")?.image(color: .gray, size: 50), for: .normal)
- buttonCopy.isHidden = false
-
- shareLinkLabel.text = NSLocalizedString("_share_link_", comment: "")
- if shares.firstShareLink?.label.count ?? 0 > 0 {
- if let shareLinkLabel = shareLinkLabel {
- if let label = shares.firstShareLink?.label {
- shareLinkLabel.text = NSLocalizedString("_share_link_", comment: "") + " (" + label + ")"
- }
- }
- }
+ if let metadata = metadata {
+ shares = NCManageDatabase.shared.getTableShares(metadata: metadata)
}
tableView.reloadData()
}
@@ -202,78 +193,17 @@ class NCShare: UIViewController, UIGestureRecognizerDelegate, NCShareNetworkingD
// MARK: - IBAction
@IBAction func searchFieldDidEndOnExit(textField: UITextField) {
-
- guard let searchString = textField.text else { return }
-
+ guard let searchString = textField.text, !searchString.isEmpty else { return }
networking?.getSharees(searchString: searchString)
}
- @IBAction func touchUpInsideButtonCopy(_ sender: Any) {
-
- guard let metadata = self.metadata else { return }
-
- let shares = NCManageDatabase.shared.getTableShares(metadata: metadata)
- tapCopy(with: shares.firstShareLink, sender: sender)
- }
-
- @IBAction func touchUpInsideButtonCopyInernalLink(_ sender: Any) {
-
- guard let metadata = self.metadata else { return }
-
- let serverUrlFileName = metadata.serverUrl + "/" + metadata.fileName
- NCNetworking.shared.readFile(serverUrlFileName: serverUrlFileName, account: metadata.account, queue: .main) { _, metadata, errorCode, errorDescription in
- if errorCode == 0 && metadata != nil {
- let internalLink = self.appDelegate.urlBase + "/index.php/f/" + metadata!.fileId
- NCShareCommon.shared.copyLink(link: internalLink, viewController: self, sender: sender)
- } else {
- NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
- }
- }
- }
-
- func checkEnforcedPassword(callback: @escaping (String?) -> Void) {
+ func checkEnforcedPassword(shareType: Int, completion: @escaping (String?) -> Void) {
guard let metadata = self.metadata,
- NCManageDatabase.shared.getCapabilitiesServerBool(account: metadata.account, elements: NCElementsJSON.shared.capabilitiesFileSharingPubPasswdEnforced, exists: false)
- else { return callback(nil) }
-
- let alertController = UIAlertController(title: NSLocalizedString("_enforce_password_protection_", comment: ""), message: "", preferredStyle: .alert)
- alertController.addTextField { textField in
- textField.isSecureTextEntry = true
- }
- alertController.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .default) { _ in })
- let okAction = UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default) { _ in
- let password = alertController.textFields?.first?.text
- callback(password)
- }
+ NCManageDatabase.shared.getCapabilitiesServerBool(account: metadata.account, elements: NCElementsJSON.shared.capabilitiesFileSharingPubPasswdEnforced, exists: false),
+ shareType == NCShareCommon.shared.SHARE_TYPE_LINK || shareType == NCShareCommon.shared.SHARE_TYPE_EMAIL
+ else { return completion(nil) }
- alertController.addAction(okAction)
-
- self.present(alertController, animated: true, completion:nil)
- }
-
- @IBAction func touchUpInsideButtonMenu(_ sender: Any) {
-
- guard let metadata = self.metadata else { return }
- let shares = NCManageDatabase.shared.getTableShares(metadata: metadata)
-
- if shares.firstShareLink == nil {
- checkEnforcedPassword { password in
- self.networking?.createShareLink(password: password)
- }
- } else {
- tapMenu(with: shares.firstShareLink!, sender: sender)
- }
- }
-
- @objc func tapLinkMenuViewWindow(gesture: UITapGestureRecognizer) {
- shareLinkMenuView?.unLoad()
- shareLinkMenuView = nil
- shareUserMenuView?.unLoad()
- shareUserMenuView = nil
- }
-
- func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
- return gestureRecognizer.view == touch.view
+ self.present(UIAlertController.password(titleKey: "_enforce_password_protection_", completion: completion), animated: true)
}
// MARK: - NCShareNetworkingDelegate
@@ -286,7 +216,9 @@ class NCShare: UIViewController, UIGestureRecognizerDelegate, NCShareNetworkingD
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataNCShare)
}
- func unShareCompleted() { }
+ func unShareCompleted() {
+ self.reloadData()
+ }
func updateShareWithError(idShare: Int) {
self.reloadData()
@@ -294,7 +226,7 @@ class NCShare: UIViewController, UIGestureRecognizerDelegate, NCShareNetworkingD
func getSharees(sharees: [NCCommunicationSharee]?) {
- guard let sharees = sharees else { return }
+ guard let sharees = sharees, let appDelegate = appDelegate else { return }
dropDown = DropDown()
let appearance = DropDown.appearance()
@@ -311,7 +243,7 @@ class NCShare: UIViewController, UIGestureRecognizerDelegate, NCShareNetworkingD
for sharee in sharees {
var label = sharee.label
if sharee.shareType == NCShareCommon.shared.SHARE_TYPE_CIRCLE {
- label += " (" + sharee.circleInfo + ", " + sharee.circleOwner + ")"
+ label += " (\(sharee.circleInfo), \(sharee.circleOwner))"
}
dropDown.dataSource.append(label)
}
@@ -321,50 +253,25 @@ class NCShare: UIViewController, UIGestureRecognizerDelegate, NCShareNetworkingD
dropDown.width = searchField.bounds.width
dropDown.direction = .bottom
- dropDown.cellNib = UINib(nibName: "NCShareUserDropDownCell", bundle: nil)
- dropDown.customCellConfiguration = { (index: Index, _: String, cell: DropDownCell) -> Void in
- guard let cell = cell as? NCShareUserDropDownCell else { return }
+ dropDown.cellNib = UINib(nibName: "NCSearchUserDropDownCell", bundle: nil)
+ dropDown.customCellConfiguration = { (index: Index, _, cell: DropDownCell) -> Void in
+ guard let cell = cell as? NCSearchUserDropDownCell else { return }
let sharee = sharees[index]
- cell.imageItem.image = NCShareCommon.shared.getImageShareType(shareType: sharee.shareType)
- cell.imageShareeType.image = NCShareCommon.shared.getImageShareType(shareType: sharee.shareType)
- let status = NCUtility.shared.getUserStatus(userIcon: sharee.userIcon, userStatus: sharee.userStatus, userMessage: sharee.userMessage)
- cell.imageStatus.image = status.onlineStatus
- cell.status.text = status.statusMessage
- if cell.status.text?.count ?? 0 > 0 {
- cell.centerTitle.constant = -5
- } else {
- cell.centerTitle.constant = 0
- }
-
- cell.imageItem.image = NCUtility.shared.loadUserImage(
- for: sharee.shareWith,
- displayName: nil,
- userBaseUrl: self.appDelegate)
-
- let fileName = self.appDelegate.userBaseUrl + "-" + sharee.shareWith + ".png"
- if NCManageDatabase.shared.getImageAvatarLoaded(fileName: fileName) == nil {
- let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName
- let etag = NCManageDatabase.shared.getTableAvatar(fileName: fileName)?.etag
-
- NCCommunication.shared.downloadAvatar(user: sharee.shareWith, fileNameLocalPath: fileNameLocalPath, sizeImage: NCGlobal.shared.avatarSize, avatarSizeRounded: NCGlobal.shared.avatarSizeRounded, etag: etag) { _, imageAvatar, _, etag, errorCode, _ in
-
- if errorCode == 0, let etag = etag, let imageAvatar = imageAvatar {
-
- NCManageDatabase.shared.addAvatar(fileName: fileName, etag: etag)
- cell.imageItem.image = imageAvatar
-
- } else if errorCode == NCGlobal.shared.errorNotModified, let imageAvatar = NCManageDatabase.shared.setAvatarLoaded(fileName: fileName) {
-
- cell.imageItem.image = imageAvatar
- }
- }
- }
+ cell.setupCell(sharee: sharee, baseUrl: appDelegate)
}
- dropDown.selectionAction = { (index, item) in
+ dropDown.selectionAction = { index, _ in
let sharee = sharees[index]
- self.checkEnforcedPassword { password in
- self.networking?.createShare(shareWith: sharee.shareWith, shareType: sharee.shareType, password: password, metadata: self.metadata!)
+ guard
+ let advancePermission = UIStoryboard(name: "NCShare", bundle: nil).instantiateViewController(withIdentifier: "NCShareAdvancePermission") as? NCShareAdvancePermission,
+ let navigationController = self.navigationController,
+ let metadata = self.metadata else { return }
+ self.checkEnforcedPassword(shareType: sharee.shareType) { password in
+ let shareOptions = NCTableShareOptions(sharee: sharee, metadata: metadata, password: password)
+ advancePermission.share = shareOptions
+ advancePermission.networking = self.networking
+ advancePermission.metadata = metadata
+ navigationController.pushViewController(advancePermission, animated: true)
}
}
@@ -377,6 +284,10 @@ class NCShare: UIViewController, UIGestureRecognizerDelegate, NCShareNetworkingD
extension NCShare: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
+ if indexPath.section == 0, indexPath.row == 0 {
+ // internal cell has description
+ return 90
+ }
return 70
}
}
@@ -386,82 +297,48 @@ extension NCShare: UITableViewDelegate {
extension NCShare: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
- return 1
+ return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-
- var numOfRows = 0
- let shares = NCManageDatabase.shared.getTableShares(metadata: metadata!)
-
- if shares.share != nil {
- numOfRows = shares.share!.count
- }
-
- return numOfRows
+ // don't allow link creation if reshare is disabled
+ guard section != 0 else { return shares.firstShareLink != nil || canReshare ? 2 : 1 }
+ return shares.share?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+ // Setup default share cells
+ guard indexPath.section != 0 else {
+ guard let cell = tableView.dequeueReusableCell(withIdentifier: "cellLink", for: indexPath) as? NCShareLinkCell
+ else { return UITableViewCell() }
+ cell.delegate = self
+ if indexPath.row == 0 {
+ cell.isInternalLink = true
+ } else if shares.firstShareLink?.isInvalidated != true {
+ cell.tableShare = shares.firstShareLink
+ }
+ cell.setupCellUI()
+ return cell
+ }
- let shares = NCManageDatabase.shared.getTableShares(metadata: metadata!)
- let tableShare = shares.share![indexPath.row]
+ guard let appDelegate = appDelegate, let tableShare = shares.share?[indexPath.row] else { return UITableViewCell() }
// LINK
- if tableShare.shareType == 3 {
+ if tableShare.shareType == NCShareCommon.shared.SHARE_TYPE_LINK {
if let cell = tableView.dequeueReusableCell(withIdentifier: "cellLink", for: indexPath) as? NCShareLinkCell {
cell.tableShare = tableShare
cell.delegate = self
- cell.labelTitle.text = NSLocalizedString("_share_link_", comment: "")
- if tableShare.label.count > 0 {
- cell.labelTitle.text = NSLocalizedString("_share_link_", comment: "") + " (" + tableShare.label + ")"
- }
- cell.labelTitle.textColor = NCBrandColor.shared.label
+ cell.setupCellUI()
return cell
}
} else {
- // USER
+ // USER / GROUP etc.
if let cell = tableView.dequeueReusableCell(withIdentifier: "cellUser", for: indexPath) as? NCShareUserCell {
-
cell.tableShare = tableShare
cell.delegate = self
- cell.labelTitle.text = tableShare.shareWithDisplayname
- cell.labelTitle.textColor = NCBrandColor.shared.label
- cell.isUserInteractionEnabled = true
- cell.labelQuickStatus.isHidden = false
- cell.imageDownArrow.isHidden = false
- cell.buttonMenu.isHidden = false
- cell.imageItem.image = NCShareCommon.shared.getImageShareType(shareType: tableShare.shareType)
-
- let status = NCUtility.shared.getUserStatus(userIcon: tableShare.userIcon, userStatus: tableShare.userStatus, userMessage: tableShare.userMessage)
- cell.imageStatus.image = status.onlineStatus
- cell.status.text = status.statusMessage
-
+ 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)
-
- // If the initiator or the recipient is not the current user, show the list of sharees without any options to edit it.
- if tableShare.uidOwner != self.appDelegate.userId && tableShare.uidFileOwner != self.appDelegate.userId {
- cell.isUserInteractionEnabled = false
- cell.labelQuickStatus.isHidden = true
- cell.imageDownArrow.isHidden = true
- cell.buttonMenu.isHidden = true
- }
-
- cell.btnQuickStatus.setTitle("", for: .normal)
- cell.btnQuickStatus.contentHorizontalAlignment = .left
-
- if tableShare.permissions == NCGlobal.shared.permissionCreateShare {
- cell.labelQuickStatus.text = NSLocalizedString("_share_file_drop_", comment: "")
- } else {
- // Read Only
- if CCUtility.isAnyPermission(toEdit: tableShare.permissions) {
- cell.labelQuickStatus.text = NSLocalizedString("_share_editing_", comment: "")
- } else {
- cell.labelQuickStatus.text = NSLocalizedString("_share_read_only_", comment: "")
- }
- }
-
return cell
}
}
@@ -469,53 +346,3 @@ extension NCShare: UITableViewDataSource {
return UITableViewCell()
}
}
-
-// MARK: - NCCell Delegates
-extension NCShare: NCShareLinkCellDelegate, NCShareUserCellDelegate {
-
- func tapCopy(with tableShare: tableShare?, sender: Any) {
-
- if let link = tableShare?.url {
- NCShareCommon.shared.copyLink(link: link, viewController: self, sender: sender)
- }
- }
-
- func tapMenu(with tableShare: tableShare?, sender: Any) {
-
- guard let tableShare = tableShare else { return }
-
- if tableShare.shareType == 3 {
- let views = NCShareCommon.shared.openViewMenuShareLink(shareViewController: self, tableShare: tableShare, metadata: metadata!)
- shareLinkMenuView = views.shareLinkMenuView
- shareMenuViewWindow = views.viewWindow
-
- let tap = UITapGestureRecognizer(target: self, action: #selector(tapLinkMenuViewWindow))
- tap.delegate = self
- shareMenuViewWindow?.addGestureRecognizer(tap)
- } else {
- let views = NCShareCommon.shared.openViewMenuUser(shareViewController: self, tableShare: tableShare, metadata: metadata!)
- shareUserMenuView = views.shareUserMenuView
- shareMenuViewWindow = views.viewWindow
-
- let tap = UITapGestureRecognizer(target: self, action: #selector(tapLinkMenuViewWindow))
- tap.delegate = self
- shareMenuViewWindow?.addGestureRecognizer(tap)
- }
- }
-
- func showProfile(with tableShare: tableShare?, sender: Any) {
- guard let tableShare = tableShare else { return }
- showProfileMenu(userId: tableShare.shareWith)
- }
-
- func quickStatus(with tableShare: tableShare?, sender: Any) {
-
- guard let tableShare = tableShare else { return }
-
- if tableShare.shareType != NCGlobal.shared.permissionDefaultFileRemoteShareNoSupportShareOption {
-
- let quickStatusMenu = NCShareQuickStatusMenu()
- quickStatusMenu.toggleMenu(viewController: self, directory: metadata!.directory, tableShare: tableShare)
- }
- }
-}
diff --git a/iOSClient/Share/NCShareCommentsCell.swift b/iOSClient/Share/NCShareCommentsCell.swift
index 36a31aae7..77335907b 100644
--- a/iOSClient/Share/NCShareCommentsCell.swift
+++ b/iOSClient/Share/NCShareCommentsCell.swift
@@ -38,24 +38,16 @@ class NCShareCommentsCell: UITableViewCell, NCCellProtocol {
weak var delegate: NCShareCommentsCellDelegate?
var filePreviewImageView: UIImageView? {
- get {
- return nil
- }
+ return nil
}
var fileAvatarImageView: UIImageView? {
- get {
- return imageItem
- }
+ return imageItem
}
var fileObjectId: String? {
- get {
- return nil
- }
+ return nil
}
var fileUser: String? {
- get {
- return tableComments?.actorId
- }
+ return tableComments?.actorId
}
override func awakeFromNib() {
diff --git a/iOSClient/Share/NCShareCommon.swift b/iOSClient/Share/NCShareCommon.swift
index 54ad9d29d..a33b7b2e8 100644
--- a/iOSClient/Share/NCShareCommon.swift
+++ b/iOSClient/Share/NCShareCommon.swift
@@ -21,7 +21,6 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import UIKit
-import FSCalendar
import DropDown
class NCShareCommon: NSObject {
@@ -45,7 +44,7 @@ class NCShareCommon: NSObject {
let size: CGFloat = 200
- let bottomImage = UIImage(named: "circle.fill")!.image(color: colorCircle, size: size/2)
+ let bottomImage = UIImage(named: "circle_fill")!.image(color: colorCircle, size: size/2)
let topImage = UIImage(named: imageName)!.image(color: .white, size: size/2)
UIGraphicsBeginImageContextWithOptions(CGSize(width: size, height: size), false, UIScreen.main.scale)
bottomImage.draw(in: CGRect(origin: CGPoint.zero, size: CGSize(width: size, height: size)))
@@ -56,126 +55,6 @@ class NCShareCommon: NSObject {
return image
}
- func openViewMenuShareLink(shareViewController: NCShare, tableShare: tableShare?, metadata: tableMetadata) -> (shareLinkMenuView: NCShareLinkMenuView, viewWindow: UIView) {
-
- var shareLinkMenuView: NCShareLinkMenuView
- let window = UIApplication.shared.keyWindow!
- let viewWindow = UIView(frame: window.bounds)
-
- window.addSubview(viewWindow)
- viewWindow.autoresizingMask = [.flexibleWidth, .flexibleHeight]
-
- if metadata.directory {
- shareLinkMenuView = Bundle.main.loadNibNamed("NCShareLinkFolderMenuView", owner: self, options: nil)?.first as! NCShareLinkMenuView
- } else {
- shareLinkMenuView = Bundle.main.loadNibNamed("NCShareLinkMenuView", owner: self, options: nil)?.first as! NCShareLinkMenuView
- }
-
- shareLinkMenuView.width = 250
- if metadata.directory {
- shareLinkMenuView.height = 600
- } else {
- shareLinkMenuView.height = 500
- }
-
- shareLinkMenuView.backgroundColor = NCBrandColor.shared.systemBackground
- shareLinkMenuView.metadata = metadata
- shareLinkMenuView.viewWindow = viewWindow
- shareLinkMenuView.shareViewController = shareViewController
- shareLinkMenuView.reloadData(idShare: tableShare?.idShare ?? 0)
- shareLinkMenuView.translatesAutoresizingMaskIntoConstraints = false
- viewWindow.addSubview(shareLinkMenuView)
-
- NSLayoutConstraint.activate([
- shareLinkMenuView.widthAnchor.constraint(equalToConstant: shareLinkMenuView.width),
- shareLinkMenuView.heightAnchor.constraint(equalToConstant: shareLinkMenuView.height),
- shareLinkMenuView.centerXAnchor.constraint(equalTo: viewWindow.centerXAnchor),
- shareLinkMenuView.centerYAnchor.constraint(equalTo: viewWindow.centerYAnchor)
- ])
-
- return(shareLinkMenuView: shareLinkMenuView, viewWindow: viewWindow)
- }
-
- func openViewMenuUser(shareViewController: NCShare, tableShare: tableShare?, metadata: tableMetadata) -> (shareUserMenuView: NCShareUserMenuView, viewWindow: UIView) {
-
- var shareUserMenuView: NCShareUserMenuView
- let window = UIApplication.shared.keyWindow!
- let viewWindow = UIView(frame: window.bounds)
-
- window.addSubview(viewWindow)
- viewWindow.autoresizingMask = [.flexibleWidth, .flexibleHeight]
-
- if metadata.directory {
- shareUserMenuView = Bundle.main.loadNibNamed("NCShareUserFolderMenuView", owner: self, options: nil)?.first as! NCShareUserMenuView
- } else {
- shareUserMenuView = Bundle.main.loadNibNamed("NCShareUserMenuView", owner: self, options: nil)?.first as! NCShareUserMenuView
- }
-
- shareUserMenuView.width = 250
- if metadata.directory {
- shareUserMenuView.height = 420
- } else {
- shareUserMenuView.height = 270
- }
-
- shareUserMenuView.backgroundColor = NCBrandColor.shared.systemBackground
- shareUserMenuView.metadata = metadata
- shareUserMenuView.viewWindow = viewWindow
- shareUserMenuView.shareViewController = shareViewController
- shareUserMenuView.reloadData(idShare: tableShare?.idShare ?? 0)
- shareUserMenuView.translatesAutoresizingMaskIntoConstraints = false
- viewWindow.addSubview(shareUserMenuView)
-
- NSLayoutConstraint.activate([
- shareUserMenuView.widthAnchor.constraint(equalToConstant: shareUserMenuView.width),
- shareUserMenuView.heightAnchor.constraint(equalToConstant: shareUserMenuView.height),
- shareUserMenuView.centerXAnchor.constraint(equalTo: viewWindow.centerXAnchor),
- shareUserMenuView.centerYAnchor.constraint(equalTo: viewWindow.centerYAnchor)
- ])
-
- return(shareUserMenuView: shareUserMenuView, viewWindow: viewWindow)
- }
-
- func openCalendar(view: UIView, width: CGFloat, height: CGFloat) -> (calendarView: FSCalendar, viewWindow: UIView) {
-
- let globalPoint = view.superview?.convert(view.frame.origin, to: nil)
-
- let window = UIApplication.shared.keyWindow!
- let viewWindow = UIView(frame: window.bounds)
- window.addSubview(viewWindow)
-
- let calendar = FSCalendar(frame: CGRect(x: globalPoint!.x + 10, y: globalPoint!.y + 10, width: width - 20, height: 300))
-
- if #available(iOS 13.0, *) {
- calendar.appearance.headerTitleColor = .label
- } else {
- calendar.appearance.headerTitleColor = .black
- }
- calendar.backgroundColor = NCBrandColor.shared.systemBackground
- calendar.placeholderType = .none
- calendar.appearance.headerMinimumDissolvedAlpha = 0.0
-
- calendar.layer.borderColor = UIColor.lightGray.cgColor
- calendar.layer.borderWidth = 0.5
- calendar.layer.masksToBounds = false
- calendar.layer.cornerRadius = 5
- calendar.layer.masksToBounds = false
- calendar.layer.shadowOffset = CGSize(width: 2, height: 2)
- calendar.layer.shadowOpacity = 0.2
-
- calendar.appearance.headerTitleFont = UIFont.systemFont(ofSize: 13)
-
- calendar.appearance.weekdayTextColor = NCBrandColor.shared.gray
- calendar.appearance.weekdayFont = UIFont.systemFont(ofSize: 13)
-
- calendar.appearance.todayColor = NCBrandColor.shared.brandElement
- calendar.appearance.titleFont = UIFont.systemFont(ofSize: 13)
-
- viewWindow.addSubview(calendar)
-
- return(calendarView: calendar, viewWindow: viewWindow)
- }
-
func copyLink(link: String, viewController: UIViewController, sender: Any) {
let objectsToShare = [link]
@@ -187,8 +66,9 @@ class NCShareCommon: NSObject {
activityViewController.popoverPresentationController?.sourceRect = (sender as AnyObject).bounds
}
}
-
- viewController.present(activityViewController, animated: true, completion: nil)
+ DispatchQueue.main.async {
+ viewController.present(activityViewController, animated: true, completion: nil)
+ }
}
func getImageShareType(shareType: Int) -> UIImage? {
diff --git a/iOSClient/Share/NCShareHeaderView.xib b/iOSClient/Share/NCShareHeaderView.xib
index 82e614d86..841623f6a 100644
--- a/iOSClient/Share/NCShareHeaderView.xib
+++ b/iOSClient/Share/NCShareHeaderView.xib
@@ -1,27 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19162" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
- <device id="retina4_0" orientation="portrait" appearance="light"/>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+ <device id="retina4_0" orientation="landscape" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19144"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
<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"/>
<view contentMode="scaleToFill" id="iN0-l3-epB" customClass="NCShareHeaderView" customModule="Nextcloud" customModuleProvider="target">
- <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
+ <rect key="frame" x="0.0" y="0.0" width="474" height="100"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="79H-PA-1m2">
- <rect key="frame" x="100" y="70" width="120" height="120"/>
+ <rect key="frame" x="20" y="0.0" width="100" height="100"/>
<constraints>
- <constraint firstAttribute="height" constant="120" id="Imw-QI-Org"/>
- <constraint firstAttribute="width" constant="120" id="YKb-24-fln"/>
+ <constraint firstAttribute="width" secondItem="79H-PA-1m2" secondAttribute="height" id="kPd-Ha-PKN"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="headTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="n1G-pn-D8s" customClass="MarqueeLabel" customModule="MarqueeLabel">
- <rect key="frame" x="15" y="520" width="290" height="18"/>
+ <rect key="frame" x="128" y="8" width="326" height="18"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
@@ -29,43 +28,44 @@
<userDefinedRuntimeAttribute type="boolean" keyPath="tapToScroll" value="YES"/>
</userDefinedRuntimeAttributes>
</label>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bOQ-tC-40T">
- <rect key="frame" x="40" y="543" width="265" height="15"/>
- <fontDescription key="fontDescription" type="system" pointSize="12"/>
- <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="calibratedRGB"/>
- <nil key="highlightedColor"/>
- </label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="EaW-fI-EmD">
- <rect key="frame" x="15" y="542" width="15" height="15"/>
+ <rect key="frame" x="128" y="77" width="15" height="15"/>
<constraints>
- <constraint firstAttribute="height" constant="15" id="Rli-bh-8fJ"/>
- <constraint firstAttribute="width" constant="15" id="cU5-4t-7Qf"/>
+ <constraint firstAttribute="width" constant="15" id="GQs-ak-G4R"/>
+ <constraint firstAttribute="height" constant="15" id="gFH-uD-FZ0"/>
</constraints>
- <state key="normal" image="favorite"/>
+ <state key="normal" image="star.fill"/>
<connections>
<action selector="touchUpInsideFavorite:" destination="iN0-l3-epB" eventType="touchUpInside" id="r4F-nS-R08"/>
</connections>
</button>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bOQ-tC-40T">
+ <rect key="frame" x="148" y="77" width="31" height="15"/>
+ <fontDescription key="fontDescription" type="system" pointSize="12"/>
+ <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="calibratedRGB"/>
+ <nil key="highlightedColor"/>
+ </label>
</subviews>
<constraints>
- <constraint firstItem="EaW-fI-EmD" firstAttribute="top" secondItem="n1G-pn-D8s" secondAttribute="bottom" constant="4" id="8Jc-BA-mYt"/>
- <constraint firstItem="bOQ-tC-40T" firstAttribute="top" secondItem="n1G-pn-D8s" secondAttribute="bottom" constant="5" id="IRS-qU-ubd"/>
- <constraint firstAttribute="bottom" secondItem="bOQ-tC-40T" secondAttribute="bottom" constant="10" id="KvA-Oh-KeQ"/>
- <constraint firstAttribute="trailing" secondItem="bOQ-tC-40T" secondAttribute="trailing" constant="15" id="LAA-Eb-HZj"/>
- <constraint firstItem="n1G-pn-D8s" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="15" id="cpD-9L-mBy"/>
- <constraint firstAttribute="trailing" secondItem="n1G-pn-D8s" secondAttribute="trailing" constant="15" id="g7A-jG-74Q"/>
- <constraint firstItem="79H-PA-1m2" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="70" id="k8q-dk-ofe"/>
- <constraint firstItem="EaW-fI-EmD" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="15" id="oRc-nv-VzO"/>
- <constraint firstItem="79H-PA-1m2" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="t10-qd-7Cn"/>
- <constraint firstItem="bOQ-tC-40T" firstAttribute="leading" secondItem="EaW-fI-EmD" secondAttribute="trailing" constant="10" id="uf6-8A-fN4"/>
+ <constraint firstAttribute="trailing" secondItem="n1G-pn-D8s" secondAttribute="trailing" constant="20" id="0ss-6p-laS"/>
+ <constraint firstItem="EaW-fI-EmD" firstAttribute="leading" secondItem="79H-PA-1m2" secondAttribute="trailing" constant="8" symbolic="YES" id="7jw-Bt-GHm"/>
+ <constraint firstItem="bOQ-tC-40T" firstAttribute="leading" secondItem="EaW-fI-EmD" secondAttribute="trailing" constant="5" id="HNe-K2-JNt"/>
+ <constraint firstAttribute="bottom" secondItem="bOQ-tC-40T" secondAttribute="bottom" constant="8" id="LkB-ps-xwS"/>
+ <constraint firstItem="n1G-pn-D8s" firstAttribute="leading" secondItem="79H-PA-1m2" secondAttribute="trailing" constant="8" symbolic="YES" id="ca1-QS-7XL"/>
+ <constraint firstItem="EaW-fI-EmD" firstAttribute="centerY" secondItem="bOQ-tC-40T" secondAttribute="centerY" id="g7i-UL-F1V"/>
+ <constraint firstItem="n1G-pn-D8s" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="8" id="gf7-1r-fAJ"/>
+ <constraint firstItem="79H-PA-1m2" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="pxE-GL-Wu8"/>
+ <constraint firstItem="79H-PA-1m2" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="sPO-Xj-c1R"/>
+ <constraint firstAttribute="bottom" secondItem="79H-PA-1m2" secondAttribute="bottom" id="yMh-bh-mR7"/>
</constraints>
+ <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="favorite" destination="EaW-fI-EmD" id="dv5-Qo-tPx"/>
<outlet property="imageView" destination="79H-PA-1m2" id="t6m-wr-OQ5"/>
<outlet property="info" destination="bOQ-tC-40T" id="N7R-YH-Xek"/>
<outlet property="path" destination="n1G-pn-D8s" id="ckb-qc-lqb"/>
</connections>
- <point key="canvasLocation" x="38" y="253"/>
+ <point key="canvasLocation" x="-12.67605633802817" y="45"/>
</view>
</objects>
<designables>
@@ -74,6 +74,6 @@
</designable>
</designables>
<resources>
- <image name="favorite" width="300" height="300"/>
+ <image name="star.fill" width="512" height="512"/>
</resources>
</document>
diff --git a/iOSClient/Share/NCShareLinkCell.swift b/iOSClient/Share/NCShareLinkCell.swift
index 7468b78ba..fe0624e53 100644
--- a/iOSClient/Share/NCShareLinkCell.swift
+++ b/iOSClient/Share/NCShareLinkCell.swift
@@ -24,29 +24,65 @@ import UIKit
class NCShareLinkCell: UITableViewCell {
- @IBOutlet weak var imageItem: UIImageView!
- @IBOutlet weak var labelTitle: UILabel!
- @IBOutlet weak var buttonCopy: UIButton!
- @IBOutlet weak var buttonMenu: UIButton!
-
- private let iconShare: CGFloat = 200
+ @IBOutlet private weak var imageItem: UIImageView!
+ @IBOutlet private weak var labelTitle: UILabel!
+ @IBOutlet private weak var descriptionLabel: UILabel!
+ @IBOutlet private weak var menuButton: UIButton!
+ @IBOutlet private weak var copyButton: UIButton!
var tableShare: tableShare?
weak var delegate: NCShareLinkCellDelegate?
+ var isInternalLink = false
+
+ override func prepareForReuse() {
+ super.prepareForReuse()
+ isInternalLink = false
+ tableShare = nil
+ }
+
+ func setupCellUI() {
+ var imageName: String
+ var imageBGColor: UIColor
+ var menuImageName = "shareMenu"
+
+ menuButton.isHidden = isInternalLink
+ descriptionLabel.isHidden = !isInternalLink
+ copyButton.isHidden = !isInternalLink && tableShare == nil
+ copyButton.accessibilityLabel = NSLocalizedString("_copy_", comment: "")
+ menuButton.accessibilityLabel = NSLocalizedString("_more_", comment: "")
+
+ if isInternalLink {
+ imageName = "shareInternalLink"
+ imageBGColor = .gray
+ labelTitle.text = NSLocalizedString("_share_internal_link_", comment: "")
+ descriptionLabel.text = NSLocalizedString("_share_internal_link_des_", comment: "")
+ } else {
+ labelTitle.text = NSLocalizedString("_share_link_", comment: "")
+ if let tableShare = tableShare {
+ if !tableShare.label.isEmpty {
+ labelTitle.text? += " (\(tableShare.label))"
+ }
+ } else {
+ menuImageName = "shareAdd"
+ menuButton.accessibilityLabel = NSLocalizedString("_add_", comment: "")
+ }
+
+ imageName = "sharebylink"
+ imageBGColor = NCBrandColor.shared.brandElement
- override func awakeFromNib() {
- super.awakeFromNib()
+ menuButton.setImage(UIImage(named: menuImageName)?.image(color: .gray, size: 50), for: .normal)
+ }
- imageItem.image = NCShareCommon.shared.createLinkAvatar(imageName: "sharebylink", colorCircle: NCBrandColor.shared.brandElement)
- buttonCopy.setImage(UIImage(named: "shareCopy")!.image(color: .gray, size: 50), for: .normal)
- buttonMenu.setImage(UIImage(named: "shareMenu")!.image(color: .gray, size: 50), for: .normal)
+ labelTitle.textColor = NCBrandColor.shared.label
+ imageItem.image = NCShareCommon.shared.createLinkAvatar(imageName: imageName, colorCircle: imageBGColor)
+ copyButton.setImage(UIImage(named: "shareCopy")?.image(color: .gray, size: 50), for: .normal)
}
- @IBAction func touchUpInsideCopy(_ sender: Any) {
+ @IBAction func touchUpCopy(_ sender: Any) {
delegate?.tapCopy(with: tableShare, sender: sender)
}
- @IBAction func touchUpInsideMenu(_ sender: Any) {
+ @IBAction func touchUpMenu(_ sender: Any) {
delegate?.tapMenu(with: tableShare, sender: sender)
}
}
diff --git a/iOSClient/Share/NCShareLinkCell.xib b/iOSClient/Share/NCShareLinkCell.xib
index 81ba5aa18..b5172d16f 100755
--- a/iOSClient/Share/NCShareLinkCell.xib
+++ b/iOSClient/Share/NCShareLinkCell.xib
@@ -1,11 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14490.70" 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="19529" 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="14490.49"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
+ <capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@@ -15,7 +14,7 @@
<rect key="frame" x="0.0" y="0.0" width="600" height="90"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="qJF-Yc-gKE" id="3Oe-gU-3Nk">
- <rect key="frame" x="0.0" y="0.0" width="600" height="89.5"/>
+ <rect key="frame" x="0.0" y="0.0" width="600" height="90"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" image="circle" translatesAutoresizingMaskIntoConstraints="NO" id="qDs-UG-Mn7" userLabel="ImageItem">
@@ -25,63 +24,84 @@
<constraint firstAttribute="width" constant="40" id="GNY-Va-SIJ"/>
</constraints>
</imageView>
- <label opaque="NO" userInteractionEnabled="NO" tag="101" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Share link" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="otH-mT-7Z4" userLabel="labelTitle">
- <rect key="frame" x="55" y="36" width="150" height="18"/>
- <constraints>
- <constraint firstAttribute="width" constant="150" id="4Oa-yZ-HZK"/>
- <constraint firstAttribute="height" constant="18" id="iet-xr-SX6"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="15"/>
- <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
- <nil key="highlightedColor"/>
- </label>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xaz-vY-Jzu" userLabel="ButtonCopy">
- <rect key="frame" x="520" y="35" width="20" height="20"/>
- <constraints>
- <constraint firstAttribute="width" constant="20" id="0JR-eM-oir"/>
- <constraint firstAttribute="height" constant="20" id="HVo-ht-9m6"/>
- </constraints>
- <state key="normal" image="shareCopy"/>
- <connections>
- <action selector="touchUpInsideCopy:" destination="qJF-Yc-gKE" eventType="touchUpInside" id="hSV-RK-FAe"/>
- </connections>
- </button>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="J1z-RG-U4A" userLabel="ButtonMenu">
- <rect key="frame" x="570" y="35" width="20" height="20"/>
- <constraints>
- <constraint firstAttribute="height" constant="20" id="G48-LB-BsD"/>
- <constraint firstAttribute="width" constant="20" id="vLI-cJ-Jqx"/>
- </constraints>
- <state key="normal" image="shareMenu"/>
- <connections>
- <action selector="touchUpInsideMenu:" destination="qJF-Yc-gKE" eventType="touchUpInside" id="GT2-Ef-FfR"/>
- </connections>
- </button>
+ <stackView opaque="NO" contentMode="scaleToFill" spacing="30" translatesAutoresizingMaskIntoConstraints="NO" id="OQv-Vf-bvD">
+ <rect key="frame" x="520" y="35" width="70" height="20"/>
+ <subviews>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xaz-vY-Jzu" userLabel="ButtonCopy">
+ <rect key="frame" x="0.0" y="0.0" width="20" height="20"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="20" id="0JR-eM-oir"/>
+ <constraint firstAttribute="height" constant="20" id="HVo-ht-9m6"/>
+ </constraints>
+ <state key="normal" image="shareCopy"/>
+ <connections>
+ <action selector="touchUpCopy:" destination="qJF-Yc-gKE" eventType="touchUpInside" id="s3f-6n-cKF"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="J1z-RG-U4A" userLabel="ButtonMenu">
+ <rect key="frame" x="50" y="0.0" width="20" height="20"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="20" id="G48-LB-BsD"/>
+ <constraint firstAttribute="width" constant="20" id="vLI-cJ-Jqx"/>
+ </constraints>
+ <state key="normal" image="shareMenu"/>
+ <connections>
+ <action selector="touchUpMenu:" destination="qJF-Yc-gKE" eventType="touchUpInside" id="hFx-Ib-xay"/>
+ </connections>
+ </button>
+ </subviews>
+ </stackView>
+ <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="Wxr-1B-Czy">
+ <rect key="frame" x="53" y="12" width="452" height="66"/>
+ <subviews>
+ <label opaque="NO" userInteractionEnabled="NO" tag="101" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Share link" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="otH-mT-7Z4" userLabel="labelTitle">
+ <rect key="frame" x="0.0" y="0.0" width="452" height="22"/>
+ <fontDescription key="fontDescription" type="system" pointSize="15"/>
+ <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalCompressionResistancePriority="245" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WJj-9P-3bn">
+ <rect key="frame" x="0.0" y="26" width="452" height="40"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="40" id="Eo4-Rq-ETK"/>
+ </constraints>
+ <string key="text">Only works....
+.;...</string>
+ <fontDescription key="fontDescription" type="system" pointSize="13"/>
+ <color key="textColor" systemColor="secondaryLabelColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ </stackView>
</subviews>
<constraints>
- <constraint firstItem="otH-mT-7Z4" firstAttribute="leading" secondItem="qDs-UG-Mn7" secondAttribute="trailing" constant="10" id="7o5-Rj-6lV"/>
- <constraint firstItem="otH-mT-7Z4" firstAttribute="centerY" secondItem="3Oe-gU-3Nk" secondAttribute="centerY" id="JNE-HJ-E36"/>
+ <constraint firstItem="OQv-Vf-bvD" firstAttribute="leading" secondItem="Wxr-1B-Czy" secondAttribute="trailing" constant="15" id="8QW-n0-4lO"/>
<constraint firstItem="qDs-UG-Mn7" firstAttribute="leading" secondItem="3Oe-gU-3Nk" secondAttribute="leading" constant="5" id="KOm-wo-CBa"/>
- <constraint firstItem="J1z-RG-U4A" firstAttribute="centerY" secondItem="3Oe-gU-3Nk" secondAttribute="centerY" id="TvQ-yn-L5w"/>
+ <constraint firstAttribute="bottom" secondItem="Wxr-1B-Czy" secondAttribute="bottom" constant="12" id="MM0-9i-BpF"/>
+ <constraint firstAttribute="trailing" secondItem="OQv-Vf-bvD" secondAttribute="trailing" constant="10" id="W3b-ww-vbQ"/>
<constraint firstItem="qDs-UG-Mn7" firstAttribute="centerY" secondItem="3Oe-gU-3Nk" secondAttribute="centerY" id="ZrD-Aw-xkx"/>
- <constraint firstItem="J1z-RG-U4A" firstAttribute="leading" secondItem="xaz-vY-Jzu" secondAttribute="trailing" constant="30" id="gGI-DA-dwq"/>
- <constraint firstItem="xaz-vY-Jzu" firstAttribute="centerY" secondItem="3Oe-gU-3Nk" secondAttribute="centerY" id="o6o-Zj-1aU"/>
- <constraint firstAttribute="trailing" secondItem="J1z-RG-U4A" secondAttribute="trailing" constant="10" id="pQA-B9-MM5"/>
+ <constraint firstItem="OQv-Vf-bvD" firstAttribute="centerY" secondItem="3Oe-gU-3Nk" secondAttribute="centerY" id="eLc-gk-xAr"/>
+ <constraint firstItem="Wxr-1B-Czy" firstAttribute="leading" secondItem="qDs-UG-Mn7" secondAttribute="trailing" constant="8" id="nXI-b3-EJM"/>
+ <constraint firstItem="Wxr-1B-Czy" firstAttribute="top" secondItem="3Oe-gU-3Nk" secondAttribute="top" constant="12" id="vxe-9X-O1f"/>
</constraints>
</tableViewCellContentView>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<connections>
- <outlet property="buttonCopy" destination="xaz-vY-Jzu" id="WVv-oI-jD8"/>
- <outlet property="buttonMenu" destination="J1z-RG-U4A" id="L2V-Ev-Cx0"/>
+ <outlet property="copyButton" destination="xaz-vY-Jzu" id="pMt-Zu-ORX"/>
+ <outlet property="descriptionLabel" destination="WJj-9P-3bn" id="QC7-SX-O3M"/>
<outlet property="imageItem" destination="qDs-UG-Mn7" id="jxL-r7-BVs"/>
<outlet property="labelTitle" destination="otH-mT-7Z4" id="f9z-Oa-OiR"/>
+ <outlet property="menuButton" destination="J1z-RG-U4A" id="VCC-y1-LRK"/>
</connections>
<point key="canvasLocation" x="97.599999999999994" y="276.1619190404798"/>
</tableViewCell>
</objects>
<resources>
- <image name="circle" width="329" height="329"/>
+ <image name="circle" width="210" height="156"/>
<image name="shareCopy" width="329" height="329"/>
<image name="shareMenu" width="329" height="329"/>
+ <systemColor name="secondaryLabelColor">
+ <color red="0.23529411764705882" green="0.23529411764705882" blue="0.2627450980392157" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
+ </systemColor>
</resources>
</document>
diff --git a/iOSClient/Share/NCShareLinkFolderMenuView.xib b/iOSClient/Share/NCShareLinkFolderMenuView.xib
deleted file mode 100644
index 8fb3aed5c..000000000
--- a/iOSClient/Share/NCShareLinkFolderMenuView.xib
+++ /dev/null
@@ -1,318 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19455" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
- <device id="retina4_0" orientation="portrait" appearance="light"/>
- <dependencies>
- <deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19454"/>
- <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"/>
- <view opaque="NO" contentMode="scaleToFill" id="iN0-l3-epB" customClass="NCShareLinkMenuView" customModule="Nextcloud" customModuleProvider="target">
- <rect key="frame" x="0.0" y="0.0" width="250" height="600"/>
- <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
- <subviews>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="sjf-wF-y07" userLabel="SwitchAllowEditing">
- <rect key="frame" x="10" y="62" width="51" height="31"/>
- <connections>
- <action selector="switchReadOnlyWithSender:" destination="iN0-l3-epB" eventType="valueChanged" id="IZJ-Hz-NxB"/>
- </connections>
- </switch>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Read only" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="IHP-P8-rm2">
- <rect key="frame" x="70" y="70" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="lcS-7f-bEg"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="UIn-eq-hkP">
- <rect key="frame" x="10" y="215" width="51" height="31"/>
- <connections>
- <action selector="switchHideDownloadChangedWithSender:" destination="iN0-l3-epB" eventType="valueChanged" id="ZUj-2h-gQC"/>
- </connections>
- </switch>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Hide download" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="KXo-cP-gkc">
- <rect key="frame" x="70" y="223" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="IEP-cO-Um6"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="HDO-WC-RvJ">
- <rect key="frame" x="10" y="266" width="51" height="31"/>
- <connections>
- <action selector="switchPasswordProtectChangedWithSender:" destination="iN0-l3-epB" eventType="valueChanged" id="wGL-du-81Q"/>
- </connections>
- </switch>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Password protect" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HaY-OM-mQh">
- <rect key="frame" x="70" y="274" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="MeH-bs-tZK"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="e1F-PV-32s">
- <rect key="frame" x="70" y="299" width="170" height="30"/>
- <constraints>
- <constraint firstAttribute="height" constant="30" id="tTv-8w-kxm"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <textInputTraits key="textInputTraits" secureTextEntry="YES" textContentType="password"/>
- <connections>
- <action selector="fieldPasswordProtectDidEndOnExitWithTextField:" destination="iN0-l3-epB" eventType="editingDidEndOnExit" id="2PO-wf-bHs"/>
- </connections>
- </textField>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="dB8-1M-WZr">
- <rect key="frame" x="10" y="349" width="51" height="31"/>
- <connections>
- <action selector="switchSetExpirationDateWithSender:" destination="iN0-l3-epB" eventType="valueChanged" id="26x-ld-Jsj"/>
- </connections>
- </switch>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Set expiration date" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qll-9F-4DA">
- <rect key="frame" x="70" y="357" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="KyU-PL-PRI"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="ymk-0u-ddH">
- <rect key="frame" x="70" y="382" width="170" height="30"/>
- <constraints>
- <constraint firstAttribute="height" constant="30" id="G4f-LN-v7k"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <textInputTraits key="textInputTraits"/>
- <connections>
- <action selector="fieldSetExpirationDateWithSender:" destination="iN0-l3-epB" eventType="editingDidBegin" id="5Ou-k5-UM5"/>
- </connections>
- </textField>
- <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="file_txt" translatesAutoresizingMaskIntoConstraints="NO" id="F4T-wQ-tBU">
- <rect key="frame" x="13" y="432" width="25" height="25"/>
- <constraints>
- <constraint firstAttribute="height" constant="25" id="7uC-w2-XPl"/>
- <constraint firstAttribute="width" constant="25" id="YkI-0i-Hbj"/>
- </constraints>
- </imageView>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Note to recipient" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="grT-sd-j7q">
- <rect key="frame" x="70" y="437" width="175" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="gof-GU-toa"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="FyH-3p-EdC">
- <rect key="frame" x="70" y="462" width="170" height="30"/>
- <constraints>
- <constraint firstAttribute="height" constant="30" id="2CZ-EP-NrP"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <textInputTraits key="textInputTraits"/>
- <connections>
- <action selector="fieldNoteToRecipientDidEndOnExitWithTextField:" destination="iN0-l3-epB" eventType="editingDidEndOnExit" id="Z9v-qs-dp4"/>
- </connections>
- </textField>
- <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="trash" translatesAutoresizingMaskIntoConstraints="NO" id="hr8-Qe-xD0" userLabel="Image Delete Share Link">
- <rect key="frame" x="13" y="512" width="25" height="25"/>
- <constraints>
- <constraint firstAttribute="height" constant="25" id="Ktg-2f-87b"/>
- <constraint firstAttribute="width" constant="25" id="ZJu-Y5-U67"/>
- </constraints>
- </imageView>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Delete share link" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ff4-JE-zGU">
- <rect key="frame" x="70" y="517" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="gYi-S0-IOg"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CLA-UL-mYb">
- <rect key="frame" x="13" y="512" width="217" height="25"/>
- <constraints>
- <constraint firstAttribute="height" constant="25" id="fWP-XF-kQx"/>
- </constraints>
- <connections>
- <action selector="buttonDeleteShareLinkWithSender:" destination="iN0-l3-epB" eventType="touchUpInside" id="ANe-oV-NCX"/>
- </connections>
- </button>
- <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="add" translatesAutoresizingMaskIntoConstraints="NO" id="6SU-Ak-Q7m">
- <rect key="frame" x="13" y="557" width="25" height="25"/>
- <constraints>
- <constraint firstAttribute="width" constant="25" id="NLr-qc-w3G"/>
- <constraint firstAttribute="height" constant="25" id="wkp-ks-jJM"/>
- </constraints>
- </imageView>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Add another link" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cna-iK-PD7">
- <rect key="frame" x="70" y="562" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="p9o-oI-gWq"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0bK-Kl-hcs">
- <rect key="frame" x="13" y="557" width="217" height="25"/>
- <constraints>
- <constraint firstAttribute="height" constant="25" id="wQO-6d-vWV"/>
- </constraints>
- <connections>
- <action selector="buttonAddAnotherLinkWithSender:" destination="iN0-l3-epB" eventType="touchUpInside" id="1Ea-g9-pQ8"/>
- </connections>
- </button>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="0ON-8M-J6K" userLabel="SwitchAllowEditing">
- <rect key="frame" x="10" y="113" width="51" height="31"/>
- <connections>
- <action selector="switchAllowUploadAndEditingWithSender:" destination="iN0-l3-epB" eventType="valueChanged" id="HEh-km-e1I"/>
- </connections>
- </switch>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Allow upload and editing" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9rD-k5-hnW">
- <rect key="frame" x="70" y="121" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="zKi-d5-7DQ"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="jpY-MU-ecU" userLabel="SwitchAllowEditing">
- <rect key="frame" x="10" y="164" width="51" height="31"/>
- <connections>
- <action selector="switchFileDropWithSender:" destination="iN0-l3-epB" eventType="valueChanged" id="32M-Ks-mr6"/>
- </connections>
- </switch>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="File drop (upload only)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QJc-Cx-Fa3">
- <rect key="frame" x="70" y="172" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="GRe-k0-V9C"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Placeholder" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="JOx-l5-TUp">
- <rect key="frame" x="10" y="12" width="230" height="30"/>
- <constraints>
- <constraint firstAttribute="height" constant="30" id="eTg-X2-ih2"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <textInputTraits key="textInputTraits"/>
- <connections>
- <action selector="fielLabelDidEndOnExitWithTextField:" destination="iN0-l3-epB" eventType="editingDidEndOnExit" id="s4f-hL-eZ2"/>
- </connections>
- </textField>
- </subviews>
- <constraints>
- <constraint firstItem="Ff4-JE-zGU" firstAttribute="centerY" secondItem="hr8-Qe-xD0" secondAttribute="centerY" id="0WP-PE-HTp"/>
- <constraint firstItem="IHP-P8-rm2" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="2RV-rL-sYG"/>
- <constraint firstItem="HaY-OM-mQh" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="4CZ-Mo-lOP"/>
- <constraint firstItem="grT-sd-j7q" firstAttribute="centerY" secondItem="F4T-wQ-tBU" secondAttribute="centerY" id="4KH-Py-OgY"/>
- <constraint firstItem="qll-9F-4DA" firstAttribute="centerY" secondItem="dB8-1M-WZr" secondAttribute="centerY" id="5QL-7q-jdE"/>
- <constraint firstItem="FyH-3p-EdC" firstAttribute="top" secondItem="grT-sd-j7q" secondAttribute="bottom" constant="10" id="7al-MO-ezA"/>
- <constraint firstItem="CLA-UL-mYb" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="13" id="8lb-ki-xfh"/>
- <constraint firstItem="0ON-8M-J6K" firstAttribute="top" secondItem="sjf-wF-y07" secondAttribute="bottom" constant="20" id="AGy-qr-ahT"/>
- <constraint firstItem="0bK-Kl-hcs" firstAttribute="top" secondItem="CLA-UL-mYb" secondAttribute="bottom" constant="20" id="Bka-Hj-Arm"/>
- <constraint firstAttribute="trailing" secondItem="ymk-0u-ddH" secondAttribute="trailing" constant="10" id="Chd-iQ-EdR"/>
- <constraint firstItem="KXo-cP-gkc" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="CuB-lc-pHi"/>
- <constraint firstItem="UIn-eq-hkP" firstAttribute="top" secondItem="jpY-MU-ecU" secondAttribute="bottom" constant="20" id="EO5-Qr-Xxq"/>
- <constraint firstItem="UIn-eq-hkP" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="FwN-Rj-koX"/>
- <constraint firstItem="HDO-WC-RvJ" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="GTl-Tq-cLY"/>
- <constraint firstItem="IHP-P8-rm2" firstAttribute="centerY" secondItem="sjf-wF-y07" secondAttribute="centerY" id="HiA-pE-L6l"/>
- <constraint firstItem="6SU-Ak-Q7m" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="13" id="Hqf-wy-u3S"/>
- <constraint firstAttribute="trailing" secondItem="e1F-PV-32s" secondAttribute="trailing" constant="10" id="ImT-sr-UAr"/>
- <constraint firstAttribute="trailing" secondItem="QJc-Cx-Fa3" secondAttribute="trailing" constant="10" id="JJ4-N8-Sbc"/>
- <constraint firstItem="QJc-Cx-Fa3" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="Jnb-0A-4RI"/>
- <constraint firstAttribute="trailing" secondItem="0bK-Kl-hcs" secondAttribute="trailing" constant="20" id="Jy3-Qb-ucs"/>
- <constraint firstAttribute="trailing" secondItem="cna-iK-PD7" secondAttribute="trailing" constant="10" id="LEz-3F-g5Q"/>
- <constraint firstAttribute="trailing" secondItem="grT-sd-j7q" secondAttribute="trailing" constant="5" id="Nyn-RD-jTz"/>
- <constraint firstItem="6SU-Ak-Q7m" firstAttribute="top" secondItem="CLA-UL-mYb" secondAttribute="bottom" constant="20" id="OU0-vG-YTq"/>
- <constraint firstAttribute="trailing" secondItem="FyH-3p-EdC" secondAttribute="trailing" constant="10" id="RhU-wl-afT"/>
- <constraint firstItem="jpY-MU-ecU" firstAttribute="top" secondItem="0ON-8M-J6K" secondAttribute="bottom" constant="20" id="STB-7n-YyT"/>
- <constraint firstItem="KXo-cP-gkc" firstAttribute="centerY" secondItem="UIn-eq-hkP" secondAttribute="centerY" id="Snt-zf-mcs"/>
- <constraint firstItem="sjf-wF-y07" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="TFC-63-muN"/>
- <constraint firstItem="dB8-1M-WZr" firstAttribute="top" secondItem="e1F-PV-32s" secondAttribute="bottom" constant="20" id="TIV-5L-Cza"/>
- <constraint firstAttribute="trailing" secondItem="9rD-k5-hnW" secondAttribute="trailing" constant="10" id="TUb-mC-BhW"/>
- <constraint firstItem="FyH-3p-EdC" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="TXe-jF-DdS"/>
- <constraint firstItem="sjf-wF-y07" firstAttribute="top" secondItem="JOx-l5-TUp" secondAttribute="bottom" constant="20" id="UTk-iX-STG"/>
- <constraint firstItem="dB8-1M-WZr" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="Ua2-93-05m"/>
- <constraint firstItem="HaY-OM-mQh" firstAttribute="centerY" secondItem="HDO-WC-RvJ" secondAttribute="centerY" id="UcN-gf-Prv"/>
- <constraint firstItem="e1F-PV-32s" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="YCZ-Z6-1Ty"/>
- <constraint firstItem="9rD-k5-hnW" firstAttribute="centerY" secondItem="0ON-8M-J6K" secondAttribute="centerY" id="ZHV-C3-5rz"/>
- <constraint firstItem="CLA-UL-mYb" firstAttribute="centerY" secondItem="hr8-Qe-xD0" secondAttribute="centerY" id="Zoj-Ro-jFv"/>
- <constraint firstAttribute="trailing" secondItem="IHP-P8-rm2" secondAttribute="trailing" constant="10" id="Zsj-Ja-2wq"/>
- <constraint firstItem="cna-iK-PD7" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="aZc-3Q-liP"/>
- <constraint firstItem="F4T-wQ-tBU" firstAttribute="top" secondItem="ymk-0u-ddH" secondAttribute="bottom" constant="20" id="aj8-2w-ySe"/>
- <constraint firstItem="0bK-Kl-hcs" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="13" id="bSd-GG-kS3"/>
- <constraint firstItem="jpY-MU-ecU" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="bkE-q5-Vpr"/>
- <constraint firstItem="HDO-WC-RvJ" firstAttribute="top" secondItem="UIn-eq-hkP" secondAttribute="bottom" constant="20" id="dex-mb-oRg"/>
- <constraint firstItem="9rD-k5-hnW" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="eaN-ru-7yU"/>
- <constraint firstItem="hr8-Qe-xD0" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="13" id="elF-be-kqS"/>
- <constraint firstItem="cna-iK-PD7" firstAttribute="centerY" secondItem="0bK-Kl-hcs" secondAttribute="centerY" id="fDj-O7-Xdr"/>
- <constraint firstItem="hr8-Qe-xD0" firstAttribute="top" secondItem="FyH-3p-EdC" secondAttribute="bottom" constant="20" id="itX-To-Hbm"/>
- <constraint firstItem="ymk-0u-ddH" firstAttribute="top" secondItem="qll-9F-4DA" secondAttribute="bottom" constant="10" id="k4G-Yb-xBy"/>
- <constraint firstItem="grT-sd-j7q" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="lRX-gv-77N"/>
- <constraint firstAttribute="trailing" secondItem="Ff4-JE-zGU" secondAttribute="trailing" constant="10" id="ljN-WF-OVS"/>
- <constraint firstItem="e1F-PV-32s" firstAttribute="top" secondItem="HaY-OM-mQh" secondAttribute="bottom" constant="10" id="m5R-ms-HZh"/>
- <constraint firstItem="0ON-8M-J6K" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="mQf-ph-p16"/>
- <constraint firstAttribute="trailing" secondItem="JOx-l5-TUp" secondAttribute="trailing" constant="10" id="mq5-TO-THS"/>
- <constraint firstItem="JOx-l5-TUp" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="12" id="n0G-KB-JE2"/>
- <constraint firstAttribute="trailing" secondItem="CLA-UL-mYb" secondAttribute="trailing" constant="20" id="oEb-Su-Nu5"/>
- <constraint firstItem="qll-9F-4DA" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="qEq-8J-iTD"/>
- <constraint firstItem="ymk-0u-ddH" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="qrv-wQ-p6E"/>
- <constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="0bK-Kl-hcs" secondAttribute="bottom" constant="10" id="rgb-gX-oJd"/>
- <constraint firstAttribute="trailing" secondItem="KXo-cP-gkc" secondAttribute="trailing" constant="10" id="uDa-6r-K84"/>
- <constraint firstAttribute="trailing" secondItem="qll-9F-4DA" secondAttribute="trailing" constant="10" id="vaT-9Q-m84"/>
- <constraint firstItem="F4T-wQ-tBU" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="13" id="x4S-GE-lJ8"/>
- <constraint firstAttribute="trailing" secondItem="HaY-OM-mQh" secondAttribute="trailing" constant="10" id="yvI-xV-T7d"/>
- <constraint firstItem="QJc-Cx-Fa3" firstAttribute="centerY" secondItem="jpY-MU-ecU" secondAttribute="centerY" id="z3L-Nd-uWl"/>
- <constraint firstItem="Ff4-JE-zGU" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="zc7-db-OeN"/>
- <constraint firstItem="JOx-l5-TUp" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="zsp-AH-Dzr"/>
- </constraints>
- <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
- <connections>
- <outlet property="buttonAddAnotherLink" destination="0bK-Kl-hcs" id="XMo-Cp-y6f"/>
- <outlet property="buttonDeleteShareLink" destination="CLA-UL-mYb" id="LVP-Vh-RHb"/>
- <outlet property="fieldLabel" destination="JOx-l5-TUp" id="RTd-kU-zGz"/>
- <outlet property="fieldNoteToRecipient" destination="FyH-3p-EdC" id="EBz-iA-1tq"/>
- <outlet property="fieldPasswordProtect" destination="e1F-PV-32s" id="c1Y-0f-UYD"/>
- <outlet property="fieldSetExpirationDate" destination="ymk-0u-ddH" id="W6o-xf-Zj2"/>
- <outlet property="imageAddAnotherLink" destination="6SU-Ak-Q7m" id="Is7-q2-ZJu"/>
- <outlet property="imageDeleteShareLink" destination="hr8-Qe-xD0" id="hGE-fg-rnv"/>
- <outlet property="imageNoteToRecipient" destination="F4T-wQ-tBU" id="IHc-Q2-VxM"/>
- <outlet property="labelAddAnotherLink" destination="cna-iK-PD7" id="xax-ip-GpR"/>
- <outlet property="labelAllowUploadAndEditing" destination="9rD-k5-hnW" id="rqA-Me-ERg"/>
- <outlet property="labelDeleteShareLink" destination="Ff4-JE-zGU" id="7jH-iS-zf8"/>
- <outlet property="labelFileDrop" destination="QJc-Cx-Fa3" id="mN5-D6-JIs"/>
- <outlet property="labelHideDownload" destination="KXo-cP-gkc" id="vis-Zu-pga"/>
- <outlet property="labelNoteToRecipient" destination="grT-sd-j7q" id="yOv-Ke-EnF"/>
- <outlet property="labelPasswordProtect" destination="HaY-OM-mQh" id="nlG-u7-v1H"/>
- <outlet property="labelReadOnly" destination="IHP-P8-rm2" id="Rgw-5M-bf6"/>
- <outlet property="labelSetExpirationDate" destination="qll-9F-4DA" id="K8B-Ys-V8e"/>
- <outlet property="switchAllowUploadAndEditing" destination="0ON-8M-J6K" id="cY7-1g-kDC"/>
- <outlet property="switchFileDrop" destination="jpY-MU-ecU" id="gs6-3e-de6"/>
- <outlet property="switchHideDownload" destination="UIn-eq-hkP" id="25D-zI-MEj"/>
- <outlet property="switchPasswordProtect" destination="HDO-WC-RvJ" id="K7a-3i-8kx"/>
- <outlet property="switchReadOnly" destination="sjf-wF-y07" id="QSL-7L-cdn"/>
- <outlet property="switchSetExpirationDate" destination="dB8-1M-WZr" id="R5d-Hf-ga6"/>
- </connections>
- <point key="canvasLocation" x="-142.5" y="519.71830985915494"/>
- </view>
- </objects>
- <resources>
- <image name="add" width="25" height="25"/>
- <image name="file_txt" width="300" height="300"/>
- <image name="trash" width="512" height="512"/>
- </resources>
-</document>
diff --git a/iOSClient/Share/NCShareLinkMenuView.swift b/iOSClient/Share/NCShareLinkMenuView.swift
deleted file mode 100644
index 19993dc42..000000000
--- a/iOSClient/Share/NCShareLinkMenuView.swift
+++ /dev/null
@@ -1,484 +0,0 @@
-//
-// NCShareLinkMenuView.swift
-// Nextcloud
-//
-// Created by Marino Faggiana on 25/07/2019.
-// Copyright © 2019 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 FSCalendar
-import NCCommunication
-
-class NCShareLinkMenuView: UIView, UIGestureRecognizerDelegate, UITextFieldDelegate, NCShareNetworkingDelegate, FSCalendarDelegate, FSCalendarDelegateAppearance {
-
- @IBOutlet weak var fieldLabel: UITextField!
-
- @IBOutlet weak var switchAllowEditing: UISwitch!
- @IBOutlet weak var labelAllowEditing: UILabel!
-
- @IBOutlet weak var switchReadOnly: UISwitch!
- @IBOutlet weak var labelReadOnly: UILabel!
-
- @IBOutlet weak var switchAllowUploadAndEditing: UISwitch!
- @IBOutlet weak var labelAllowUploadAndEditing: UILabel!
-
- @IBOutlet weak var switchFileDrop: UISwitch!
- @IBOutlet weak var labelFileDrop: UILabel!
-
- @IBOutlet weak var switchHideDownload: UISwitch!
- @IBOutlet weak var labelHideDownload: UILabel!
-
- @IBOutlet weak var switchPasswordProtect: UISwitch!
- @IBOutlet weak var labelPasswordProtect: UILabel!
- @IBOutlet weak var fieldPasswordProtect: UITextField!
-
- @IBOutlet weak var switchSetExpirationDate: UISwitch!
- @IBOutlet weak var labelSetExpirationDate: UILabel!
- @IBOutlet weak var fieldSetExpirationDate: UITextField!
-
- @IBOutlet weak var imageNoteToRecipient: UIImageView!
- @IBOutlet weak var labelNoteToRecipient: UILabel!
- @IBOutlet weak var fieldNoteToRecipient: UITextField!
-
- @IBOutlet weak var buttonDeleteShareLink: UIButton!
- @IBOutlet weak var labelDeleteShareLink: UILabel!
- @IBOutlet weak var imageDeleteShareLink: UIImageView!
-
- @IBOutlet weak var buttonAddAnotherLink: UIButton!
- @IBOutlet weak var labelAddAnotherLink: UILabel!
- @IBOutlet weak var imageAddAnotherLink: UIImageView!
-
- private let appDelegate = UIApplication.shared.delegate as! AppDelegate
-
- var width: CGFloat = 0
- var height: CGFloat = 0
-
- private var tableShare: tableShare?
- var metadata: tableMetadata?
- var shareViewController: NCShare?
- private var networking: NCShareNetworking?
-
- var viewWindow: UIView?
- var viewWindowCalendar: UIView?
- private var calendar: FSCalendar?
- private var activeTextfieldDiff: CGFloat = 0
- private var activeTextField = UITextField()
-
- override func awakeFromNib() {
-
- layer.borderColor = UIColor.lightGray.cgColor
- layer.borderWidth = 0.5
- layer.cornerRadius = 5
- layer.masksToBounds = false
- layer.shadowOffset = CGSize(width: 2, height: 2)
- layer.shadowOpacity = 0.2
-
- fieldLabel?.placeholder = NSLocalizedString("_Link_name_", comment: "")
-
- switchAllowEditing?.transform = CGAffineTransform(scaleX: 0.75, y: 0.75)
- switchAllowEditing?.onTintColor = NCBrandColor.shared.brandElement
- switchReadOnly?.transform = CGAffineTransform(scaleX: 0.75, y: 0.75)
- switchReadOnly?.onTintColor = NCBrandColor.shared.brandElement
- switchAllowUploadAndEditing?.transform = CGAffineTransform(scaleX: 0.75, y: 0.75)
- switchAllowUploadAndEditing?.onTintColor = NCBrandColor.shared.brandElement
- switchFileDrop?.transform = CGAffineTransform(scaleX: 0.75, y: 0.75)
- switchFileDrop?.onTintColor = NCBrandColor.shared.brandElement
- switchHideDownload.transform = CGAffineTransform(scaleX: 0.75, y: 0.75)
- switchHideDownload.onTintColor = NCBrandColor.shared.brandElement
- switchPasswordProtect.transform = CGAffineTransform(scaleX: 0.75, y: 0.75)
- switchPasswordProtect.onTintColor = NCBrandColor.shared.brandElement
- switchSetExpirationDate.transform = CGAffineTransform(scaleX: 0.75, y: 0.75)
- switchSetExpirationDate.onTintColor = NCBrandColor.shared.brandElement
-
- labelAllowEditing?.text = NSLocalizedString("_share_allow_editing_", comment: "")
- labelAllowEditing?.textColor = NCBrandColor.shared.label
- labelReadOnly?.text = NSLocalizedString("_share_read_only_", comment: "")
- labelReadOnly?.textColor = NCBrandColor.shared.label
- labelAllowUploadAndEditing?.text = NSLocalizedString("_share_allow_upload_", comment: "")
- labelAllowUploadAndEditing?.textColor = NCBrandColor.shared.label
- labelFileDrop?.text = NSLocalizedString("_share_file_drop_", comment: "")
- labelFileDrop?.textColor = NCBrandColor.shared.label
- labelHideDownload?.text = NSLocalizedString("_share_hide_download_", comment: "")
- labelHideDownload?.textColor = NCBrandColor.shared.label
- labelPasswordProtect?.text = NSLocalizedString("_share_password_protect_", comment: "")
- labelPasswordProtect?.textColor = NCBrandColor.shared.label
- labelSetExpirationDate?.text = NSLocalizedString("_share_expiration_date_", comment: "")
- labelSetExpirationDate?.textColor = NCBrandColor.shared.label
- labelNoteToRecipient?.text = NSLocalizedString("_share_note_recipient_", comment: "")
- labelNoteToRecipient?.textColor = NCBrandColor.shared.label
- labelDeleteShareLink?.text = NSLocalizedString("_share_delete_sharelink_", comment: "")
- labelDeleteShareLink?.textColor = NCBrandColor.shared.label
- labelAddAnotherLink?.text = NSLocalizedString("_share_add_sharelink_", comment: "")
- labelAddAnotherLink?.textColor = NCBrandColor.shared.label
-
- fieldSetExpirationDate.inputView = UIView()
-
- fieldLabel.delegate = self
- fieldPasswordProtect.delegate = self
- fieldNoteToRecipient.delegate = self
-
- imageNoteToRecipient.image = UIImage(named: "file_txt")!.image(color: NCBrandColor.shared.gray, size: 50)
- imageDeleteShareLink.image = NCUtility.shared.loadImage(named: "trash", color: NCBrandColor.shared.gray, size: 50)
- imageAddAnotherLink.image = NCUtility.shared.loadImage(named: "plus", color: NCBrandColor.shared.gray, size: 50)
-
- NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
- NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
- }
-
- override func willMove(toWindow newWindow: UIWindow?) {
- super.willMove(toWindow: newWindow)
-
- if newWindow == nil {
- // UIView disappear
- shareViewController?.reloadData()
- } else {
- // UIView appear
- networking = NCShareNetworking(metadata: metadata!, urlBase: appDelegate.urlBase, view: self, delegate: self)
- }
- }
-
- func unLoad() {
- viewWindowCalendar?.removeFromSuperview()
- viewWindow?.removeFromSuperview()
-
- viewWindowCalendar = nil
- viewWindow = nil
- }
-
- func reloadData(idShare: Int) {
-
- guard let metadata = self.metadata else { return }
- tableShare = NCManageDatabase.shared.getTableShare(account: metadata.account, idShare: idShare)
- guard let tableShare = self.tableShare else { return }
-
- // Label
- fieldLabel.text = tableShare.label
-
- if metadata.directory {
- // File Drop
- if tableShare.permissions == NCGlobal.shared.permissionCreateShare {
- switchReadOnly.setOn(false, animated: false)
- switchAllowUploadAndEditing.setOn(false, animated: false)
- switchFileDrop.setOn(true, animated: false)
- } else {
- // Read Only
- if CCUtility.isAnyPermission(toEdit: tableShare.permissions) {
- switchReadOnly.setOn(false, animated: false)
- switchAllowUploadAndEditing.setOn(true, animated: false)
- } else {
- switchReadOnly.setOn(true, animated: false)
- switchAllowUploadAndEditing.setOn(false, animated: false)
- }
- switchFileDrop.setOn(false, animated: false)
- }
- } else {
- // Allow editing
- if CCUtility.isAnyPermission(toEdit: tableShare.permissions) {
- switchAllowEditing.setOn(true, animated: false)
- } else {
- switchAllowEditing.setOn(false, animated: false)
- }
- }
-
- // Hide download
- if tableShare.hideDownload {
- switchHideDownload.setOn(true, animated: false)
- } else {
- switchHideDownload.setOn(false, animated: false)
- }
-
- // Password protect
- if tableShare.shareWith.count > 0 {
- switchPasswordProtect.setOn(true, animated: false)
- fieldPasswordProtect.isEnabled = true
- fieldPasswordProtect.text = tableShare.shareWith
- } else {
- switchPasswordProtect.setOn(false, animated: false)
- fieldPasswordProtect.isEnabled = false
- fieldPasswordProtect.text = ""
- }
-
- // Set expiration date
- if tableShare.expirationDate != nil {
- switchSetExpirationDate.setOn(true, animated: false)
- fieldSetExpirationDate.isEnabled = true
-
- let dateFormatter = DateFormatter()
- dateFormatter.formatterBehavior = .behavior10_4
- dateFormatter.dateStyle = .medium
- fieldSetExpirationDate.text = dateFormatter.string(from: tableShare.expirationDate! as Date)
- } else {
- switchSetExpirationDate.setOn(false, animated: false)
- fieldSetExpirationDate.isEnabled = false
- fieldSetExpirationDate.text = ""
- }
-
- // Note to recipient
- fieldNoteToRecipient.text = tableShare.note
- }
-
- func textFieldDidBeginEditing(_ textField: UITextField) {
-
- self.activeTextField = textField
- }
-
- // MARK: - Keyboard notification
-
- @objc internal func keyboardWillShow(_ notification: Notification?) {
-
- activeTextfieldDiff = 0
-
- if let info = notification?.userInfo, let centerObject = self.activeTextField.superview?.convert(self.activeTextField.center, to: nil) {
-
- let frameEndUserInfoKey = UIResponder.keyboardFrameEndUserInfoKey
- if let keyboardFrame = info[frameEndUserInfoKey] as? CGRect {
- let diff = keyboardFrame.origin.y - centerObject.y - self.activeTextField.frame.height
- if diff < 0 {
- activeTextfieldDiff = diff
- self.frame.origin.y += diff
- }
- }
- }
- }
-
- @objc func keyboardWillHide(_ notification: Notification) {
- self.frame.origin.y -= activeTextfieldDiff
- }
-
- // MARK: - Tap viewWindowCalendar
-
- @objc func tapViewWindowCalendar(gesture: UITapGestureRecognizer) {
- calendar?.removeFromSuperview()
- viewWindowCalendar?.removeFromSuperview()
-
- calendar = nil
- viewWindowCalendar = nil
-
- reloadData(idShare: tableShare?.idShare ?? 0)
- }
-
- func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
- return gestureRecognizer.view == touch.view
- }
-
- // MARK: - IBAction
-
- // Allow editing (file)
- @IBAction func switchAllowEditingChanged(sender: UISwitch) {
-
- guard let tableShare = self.tableShare else { return }
- guard let metadata = self.metadata else { return }
-
- var permissions: Int = 0
-
- if sender.isOn {
- permissions = CCUtility.getPermissionsValue(byCanEdit: true, andCanCreate: true, andCanChange: true, andCanDelete: true, andCanShare: false, andIsFolder: metadata.directory)
- } else {
- permissions = CCUtility.getPermissionsValue(byCanEdit: false, andCanCreate: false, andCanChange: false, andCanDelete: false, andCanShare: false, andIsFolder: metadata.directory)
- }
-
- networking?.updateShare(idShare: tableShare.idShare, password: nil, permissions: permissions, note: nil, label: nil, expirationDate: nil, hideDownload: tableShare.hideDownload)
- }
-
- // Read Only (directory)
- @IBAction func switchReadOnly(sender: UISwitch) {
-
- guard let tableShare = self.tableShare else { return }
- guard let metadata = self.metadata else { return }
- let permissions = CCUtility.getPermissionsValue(byCanEdit: false, andCanCreate: false, andCanChange: false, andCanDelete: false, andCanShare: false, andIsFolder: metadata.directory)
-
- if sender.isOn && permissions != tableShare.permissions {
- switchAllowUploadAndEditing.setOn(false, animated: false)
- switchFileDrop.setOn(false, animated: false)
- networking?.updateShare(idShare: tableShare.idShare, password: nil, permissions: permissions, note: nil, label: nil, expirationDate: nil, hideDownload: tableShare.hideDownload)
- } else {
- sender.setOn(true, animated: false)
- }
- }
-
- // Allow Upload And Editing (directory)
- @IBAction func switchAllowUploadAndEditing(sender: UISwitch) {
-
- guard let tableShare = self.tableShare else { return }
- guard let metadata = self.metadata else { return }
- let permissions = CCUtility.getPermissionsValue(byCanEdit: true, andCanCreate: true, andCanChange: true, andCanDelete: true, andCanShare: false, andIsFolder: metadata.directory)
-
- if sender.isOn && permissions != tableShare.permissions {
- switchReadOnly.setOn(false, animated: false)
- switchFileDrop.setOn(false, animated: false)
- networking?.updateShare(idShare: tableShare.idShare, password: nil, permissions: permissions, note: nil, label: nil, expirationDate: nil, hideDownload: tableShare.hideDownload)
- } else {
- sender.setOn(true, animated: false)
- }
- }
-
- // File Drop (directory)
- @IBAction func switchFileDrop(sender: UISwitch) {
-
- guard let tableShare = self.tableShare else { return }
- let permissions = NCGlobal.shared.permissionCreateShare
-
- if sender.isOn && permissions != tableShare.permissions {
- switchReadOnly.setOn(false, animated: false)
- switchAllowUploadAndEditing.setOn(false, animated: false)
- networking?.updateShare(idShare: tableShare.idShare, password: nil, permissions: permissions, note: nil, label: nil, expirationDate: nil, hideDownload: tableShare.hideDownload)
- } else {
- sender.setOn(true, animated: false)
- }
- }
-
- // Hide download
- @IBAction func switchHideDownloadChanged(sender: UISwitch) {
-
- guard let tableShare = self.tableShare else { return }
-
- networking?.updateShare(idShare: tableShare.idShare, password: nil, permissions: tableShare.permissions, note: nil, label: nil, expirationDate: nil, hideDownload: sender.isOn)
- }
-
- // Password protect
- @IBAction func switchPasswordProtectChanged(sender: UISwitch) {
-
- guard let tableShare = self.tableShare else { return }
-
- if sender.isOn {
- fieldPasswordProtect.isEnabled = true
- fieldPasswordProtect.text = ""
- fieldPasswordProtect.becomeFirstResponder()
- } else {
- networking?.updateShare(idShare: tableShare.idShare, password: "", permissions: tableShare.permissions, note: nil, label: nil, expirationDate: nil, hideDownload: tableShare.hideDownload)
- }
- }
-
- @IBAction func fieldPasswordProtectDidEndOnExit(textField: UITextField) {
-
- guard let tableShare = self.tableShare else { return }
-
- networking?.updateShare(idShare: tableShare.idShare, password: fieldPasswordProtect.text, permissions: tableShare.permissions, note: nil, label: nil, expirationDate: nil, hideDownload: tableShare.hideDownload)
- }
-
- // Set expiration date
- @IBAction func switchSetExpirationDate(sender: UISwitch) {
-
- guard let tableShare = self.tableShare else { return }
-
- if sender.isOn {
- fieldSetExpirationDate.isEnabled = true
- fieldSetExpirationDate(sender: fieldSetExpirationDate)
- } else {
- networking?.updateShare(idShare: tableShare.idShare, password: nil, permissions: tableShare.permissions, note: nil, label: nil, expirationDate: "", hideDownload: tableShare.hideDownload)
- }
- }
-
- @IBAction func fieldSetExpirationDate(sender: UITextField) {
-
- let calendar = NCShareCommon.shared.openCalendar(view: self, width: width, height: height)
- calendar.calendarView.delegate = self
- self.calendar = calendar.calendarView
- viewWindowCalendar = calendar.viewWindow
-
- let tap = UITapGestureRecognizer(target: self, action: #selector(tapViewWindowCalendar))
- tap.delegate = self
- viewWindowCalendar?.addGestureRecognizer(tap)
- }
-
- // Note to recipient
- @IBAction func fieldNoteToRecipientDidEndOnExit(textField: UITextField) {
-
- guard let tableShare = self.tableShare else { return }
- if fieldNoteToRecipient.text == nil { return }
-
- networking?.updateShare(idShare: tableShare.idShare, password: nil, permissions: tableShare.permissions, note: fieldNoteToRecipient.text, label: nil, expirationDate: nil, hideDownload: tableShare.hideDownload)
- }
-
- // Label
- @IBAction func fielLabelDidEndOnExit(textField: UITextField) {
-
- guard let tableShare = self.tableShare else { return }
- if fieldLabel.text == nil { return }
-
- networking?.updateShare(idShare: tableShare.idShare, password: nil, permissions: tableShare.permissions, note: nil, label: fieldLabel.text, expirationDate: nil, hideDownload: tableShare.hideDownload)
- }
-
- // Delete share link
- @IBAction func buttonDeleteShareLink(sender: UIButton) {
-
- guard let tableShare = self.tableShare else { return }
-
- networking?.unShare(idShare: tableShare.idShare)
- }
-
- // Add another link
- @IBAction func buttonAddAnotherLink(sender: UIButton) {
-
- networking?.createShareLink(password: "")
- }
-
- // MARK: - Delegate networking
-
- func readShareCompleted() {
- reloadData(idShare: tableShare?.idShare ?? 0)
- }
-
- func shareCompleted() {
- unLoad()
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataNCShare)
- }
-
- func unShareCompleted() {
- unLoad()
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataNCShare)
- }
-
- func updateShareWithError(idShare: Int) {
- reloadData(idShare: idShare)
- }
-
- func getSharees(sharees: [NCCommunicationSharee]?) { }
-
- // MARK: - Delegate calendar
-
- func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
-
- if monthPosition == .previous || monthPosition == .next {
- calendar.setCurrentPage(date, animated: true)
- } else {
- let dateFormatter = DateFormatter()
- dateFormatter.formatterBehavior = .behavior10_4
- dateFormatter.dateStyle = .medium
- fieldSetExpirationDate.text = dateFormatter.string(from: date)
- fieldSetExpirationDate.endEditing(true)
-
- viewWindowCalendar?.removeFromSuperview()
-
- guard let tableShare = self.tableShare else { return }
-
- dateFormatter.dateFormat = "YYYY-MM-dd HH:mm:ss"
- let expirationDate = dateFormatter.string(from: date)
-
- networking?.updateShare(idShare: tableShare.idShare, password: nil, permissions: tableShare.permissions, note: nil, label: nil, expirationDate: expirationDate, hideDownload: tableShare.hideDownload)
- }
- }
-
- func calendar(_ calendar: FSCalendar, shouldSelect date: Date, at monthPosition: FSCalendarMonthPosition) -> Bool {
- return date > Date()
- }
-
- func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, titleDefaultColorFor date: Date) -> UIColor? {
- return date > Date() ? NCBrandColor.shared.label : NCBrandColor.shared.systemGray3
- }
-}
diff --git a/iOSClient/Share/NCShareLinkMenuView.xib b/iOSClient/Share/NCShareLinkMenuView.xib
deleted file mode 100644
index 35748f2e1..000000000
--- a/iOSClient/Share/NCShareLinkMenuView.xib
+++ /dev/null
@@ -1,274 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19455" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
- <device id="retina3_5" orientation="portrait" appearance="light"/>
- <dependencies>
- <deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19454"/>
- <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"/>
- <view opaque="NO" contentMode="scaleToFill" id="iN0-l3-epB" customClass="NCShareLinkMenuView" customModule="Nextcloud" customModuleProvider="target">
- <rect key="frame" x="0.0" y="0.0" width="250" height="500"/>
- <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
- <subviews>
- <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Placeholder" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="AjK-Ty-MRn">
- <rect key="frame" x="10" y="10" width="230" height="30"/>
- <constraints>
- <constraint firstAttribute="height" constant="30" id="sVl-pt-Qe5"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <textInputTraits key="textInputTraits"/>
- <connections>
- <action selector="fielLabelDidEndOnExitWithTextField:" destination="iN0-l3-epB" eventType="editingDidEndOnExit" id="WwX-ie-SRK"/>
- </connections>
- </textField>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="sjf-wF-y07" userLabel="SwitchAllowEditing">
- <rect key="frame" x="10" y="60" width="51" height="31"/>
- <connections>
- <action selector="switchAllowEditingChangedWithSender:" destination="iN0-l3-epB" eventType="valueChanged" id="22f-fh-Qc1"/>
- </connections>
- </switch>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Allow editing" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="IHP-P8-rm2">
- <rect key="frame" x="70" y="68" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="lcS-7f-bEg"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="UIn-eq-hkP">
- <rect key="frame" x="10" y="111" width="51" height="31"/>
- <connections>
- <action selector="switchHideDownloadChangedWithSender:" destination="iN0-l3-epB" eventType="valueChanged" id="ZUj-2h-gQC"/>
- </connections>
- </switch>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Hide download" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="KXo-cP-gkc">
- <rect key="frame" x="70" y="119" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="IEP-cO-Um6"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="HDO-WC-RvJ">
- <rect key="frame" x="10" y="162" width="51" height="31"/>
- <connections>
- <action selector="switchPasswordProtectChangedWithSender:" destination="iN0-l3-epB" eventType="valueChanged" id="wGL-du-81Q"/>
- </connections>
- </switch>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Password protect" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HaY-OM-mQh">
- <rect key="frame" x="70" y="170" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="MeH-bs-tZK"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="e1F-PV-32s">
- <rect key="frame" x="70" y="195" width="170" height="30"/>
- <constraints>
- <constraint firstAttribute="height" constant="30" id="tTv-8w-kxm"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <textInputTraits key="textInputTraits" secureTextEntry="YES" textContentType="password"/>
- <connections>
- <action selector="fieldPasswordProtectDidEndOnExitWithTextField:" destination="iN0-l3-epB" eventType="editingDidEndOnExit" id="2PO-wf-bHs"/>
- </connections>
- </textField>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="dB8-1M-WZr">
- <rect key="frame" x="10" y="245" width="51" height="31"/>
- <connections>
- <action selector="switchSetExpirationDateWithSender:" destination="iN0-l3-epB" eventType="valueChanged" id="26x-ld-Jsj"/>
- </connections>
- </switch>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Set expiration date" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qll-9F-4DA">
- <rect key="frame" x="70" y="253" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="KyU-PL-PRI"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="ymk-0u-ddH">
- <rect key="frame" x="70" y="278" width="170" height="30"/>
- <constraints>
- <constraint firstAttribute="height" constant="30" id="G4f-LN-v7k"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <textInputTraits key="textInputTraits"/>
- <connections>
- <action selector="fieldSetExpirationDateWithSender:" destination="iN0-l3-epB" eventType="editingDidBegin" id="5Ou-k5-UM5"/>
- </connections>
- </textField>
- <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="file_txt" translatesAutoresizingMaskIntoConstraints="NO" id="F4T-wQ-tBU">
- <rect key="frame" x="13" y="328" width="25" height="25"/>
- <constraints>
- <constraint firstAttribute="height" constant="25" id="7uC-w2-XPl"/>
- <constraint firstAttribute="width" constant="25" id="YkI-0i-Hbj"/>
- </constraints>
- </imageView>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Note to recipient" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="grT-sd-j7q">
- <rect key="frame" x="70" y="333" width="175" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="gof-GU-toa"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="FyH-3p-EdC">
- <rect key="frame" x="70" y="358" width="170" height="30"/>
- <constraints>
- <constraint firstAttribute="height" constant="30" id="hye-cf-nPD"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <textInputTraits key="textInputTraits"/>
- <connections>
- <action selector="fieldNoteToRecipientDidEndOnExitWithTextField:" destination="iN0-l3-epB" eventType="editingDidEndOnExit" id="Z9v-qs-dp4"/>
- </connections>
- </textField>
- <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="trash" translatesAutoresizingMaskIntoConstraints="NO" id="hr8-Qe-xD0" userLabel="Image Delete Share Link">
- <rect key="frame" x="13" y="408" width="25" height="25"/>
- <constraints>
- <constraint firstAttribute="height" constant="25" id="Ktg-2f-87b"/>
- <constraint firstAttribute="width" constant="25" id="ZJu-Y5-U67"/>
- </constraints>
- </imageView>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Delete share link" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ff4-JE-zGU">
- <rect key="frame" x="70" y="413" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="gYi-S0-IOg"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CLA-UL-mYb">
- <rect key="frame" x="13" y="408" width="217" height="25"/>
- <constraints>
- <constraint firstAttribute="height" constant="25" id="fWP-XF-kQx"/>
- </constraints>
- <connections>
- <action selector="buttonDeleteShareLinkWithSender:" destination="iN0-l3-epB" eventType="touchUpInside" id="ANe-oV-NCX"/>
- </connections>
- </button>
- <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="add" translatesAutoresizingMaskIntoConstraints="NO" id="6SU-Ak-Q7m">
- <rect key="frame" x="13" y="453" width="25" height="25"/>
- <constraints>
- <constraint firstAttribute="width" constant="25" id="NLr-qc-w3G"/>
- <constraint firstAttribute="height" constant="25" id="wkp-ks-jJM"/>
- </constraints>
- </imageView>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Add another link" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cna-iK-PD7">
- <rect key="frame" x="70" y="458" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="p9o-oI-gWq"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0bK-Kl-hcs">
- <rect key="frame" x="13" y="453" width="217" height="25"/>
- <constraints>
- <constraint firstAttribute="height" constant="25" id="wQO-6d-vWV"/>
- </constraints>
- <connections>
- <action selector="buttonAddAnotherLinkWithSender:" destination="iN0-l3-epB" eventType="touchUpInside" id="1Ea-g9-pQ8"/>
- </connections>
- </button>
- </subviews>
- <constraints>
- <constraint firstItem="Ff4-JE-zGU" firstAttribute="centerY" secondItem="hr8-Qe-xD0" secondAttribute="centerY" id="0WP-PE-HTp"/>
- <constraint firstItem="IHP-P8-rm2" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="2RV-rL-sYG"/>
- <constraint firstItem="HaY-OM-mQh" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="4CZ-Mo-lOP"/>
- <constraint firstItem="grT-sd-j7q" firstAttribute="centerY" secondItem="F4T-wQ-tBU" secondAttribute="centerY" id="4KH-Py-OgY"/>
- <constraint firstItem="qll-9F-4DA" firstAttribute="centerY" secondItem="dB8-1M-WZr" secondAttribute="centerY" id="5QL-7q-jdE"/>
- <constraint firstItem="FyH-3p-EdC" firstAttribute="top" secondItem="grT-sd-j7q" secondAttribute="bottom" constant="10" id="7al-MO-ezA"/>
- <constraint firstItem="CLA-UL-mYb" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="13" id="8lb-ki-xfh"/>
- <constraint firstItem="0bK-Kl-hcs" firstAttribute="top" secondItem="CLA-UL-mYb" secondAttribute="bottom" constant="20" id="Bka-Hj-Arm"/>
- <constraint firstAttribute="trailing" secondItem="ymk-0u-ddH" secondAttribute="trailing" constant="10" id="Chd-iQ-EdR"/>
- <constraint firstAttribute="trailing" secondItem="AjK-Ty-MRn" secondAttribute="trailing" constant="10" id="Cjo-Gm-Fqi"/>
- <constraint firstItem="KXo-cP-gkc" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="CuB-lc-pHi"/>
- <constraint firstItem="UIn-eq-hkP" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="FwN-Rj-koX"/>
- <constraint firstItem="HDO-WC-RvJ" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="GTl-Tq-cLY"/>
- <constraint firstItem="IHP-P8-rm2" firstAttribute="centerY" secondItem="sjf-wF-y07" secondAttribute="centerY" id="HiA-pE-L6l"/>
- <constraint firstItem="6SU-Ak-Q7m" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="13" id="Hqf-wy-u3S"/>
- <constraint firstAttribute="trailing" secondItem="e1F-PV-32s" secondAttribute="trailing" constant="10" id="ImT-sr-UAr"/>
- <constraint firstAttribute="trailing" secondItem="0bK-Kl-hcs" secondAttribute="trailing" constant="20" id="Jy3-Qb-ucs"/>
- <constraint firstAttribute="trailing" secondItem="cna-iK-PD7" secondAttribute="trailing" constant="10" id="LEz-3F-g5Q"/>
- <constraint firstAttribute="trailing" secondItem="grT-sd-j7q" secondAttribute="trailing" constant="5" id="Nyn-RD-jTz"/>
- <constraint firstItem="6SU-Ak-Q7m" firstAttribute="top" secondItem="CLA-UL-mYb" secondAttribute="bottom" constant="20" id="OU0-vG-YTq"/>
- <constraint firstAttribute="trailing" secondItem="FyH-3p-EdC" secondAttribute="trailing" constant="10" id="RhU-wl-afT"/>
- <constraint firstItem="KXo-cP-gkc" firstAttribute="centerY" secondItem="UIn-eq-hkP" secondAttribute="centerY" id="Snt-zf-mcs"/>
- <constraint firstItem="sjf-wF-y07" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="TFC-63-muN"/>
- <constraint firstItem="dB8-1M-WZr" firstAttribute="top" secondItem="e1F-PV-32s" secondAttribute="bottom" constant="20" id="TIV-5L-Cza"/>
- <constraint firstItem="FyH-3p-EdC" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="TXe-jF-DdS"/>
- <constraint firstItem="dB8-1M-WZr" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="Ua2-93-05m"/>
- <constraint firstItem="HaY-OM-mQh" firstAttribute="centerY" secondItem="HDO-WC-RvJ" secondAttribute="centerY" id="UcN-gf-Prv"/>
- <constraint firstItem="e1F-PV-32s" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="YCZ-Z6-1Ty"/>
- <constraint firstItem="CLA-UL-mYb" firstAttribute="centerY" secondItem="hr8-Qe-xD0" secondAttribute="centerY" id="Zoj-Ro-jFv"/>
- <constraint firstAttribute="trailing" secondItem="IHP-P8-rm2" secondAttribute="trailing" constant="10" id="Zsj-Ja-2wq"/>
- <constraint firstItem="cna-iK-PD7" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="aZc-3Q-liP"/>
- <constraint firstItem="F4T-wQ-tBU" firstAttribute="top" secondItem="ymk-0u-ddH" secondAttribute="bottom" constant="20" id="aj8-2w-ySe"/>
- <constraint firstItem="0bK-Kl-hcs" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="13" id="bSd-GG-kS3"/>
- <constraint firstItem="HDO-WC-RvJ" firstAttribute="top" secondItem="UIn-eq-hkP" secondAttribute="bottom" constant="20" id="dex-mb-oRg"/>
- <constraint firstItem="AjK-Ty-MRn" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="eT2-WG-2Db"/>
- <constraint firstItem="hr8-Qe-xD0" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="13" id="elF-be-kqS"/>
- <constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="0bK-Kl-hcs" secondAttribute="bottom" constant="10" id="eyC-io-Nk6"/>
- <constraint firstItem="cna-iK-PD7" firstAttribute="centerY" secondItem="0bK-Kl-hcs" secondAttribute="centerY" id="fDj-O7-Xdr"/>
- <constraint firstItem="hr8-Qe-xD0" firstAttribute="top" secondItem="FyH-3p-EdC" secondAttribute="bottom" constant="20" id="itX-To-Hbm"/>
- <constraint firstItem="ymk-0u-ddH" firstAttribute="top" secondItem="qll-9F-4DA" secondAttribute="bottom" constant="10" id="k4G-Yb-xBy"/>
- <constraint firstItem="grT-sd-j7q" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="lRX-gv-77N"/>
- <constraint firstAttribute="trailing" secondItem="Ff4-JE-zGU" secondAttribute="trailing" constant="10" id="ljN-WF-OVS"/>
- <constraint firstItem="e1F-PV-32s" firstAttribute="top" secondItem="HaY-OM-mQh" secondAttribute="bottom" constant="10" id="m5R-ms-HZh"/>
- <constraint firstAttribute="trailing" secondItem="CLA-UL-mYb" secondAttribute="trailing" constant="20" id="oEb-Su-Nu5"/>
- <constraint firstItem="qll-9F-4DA" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="qEq-8J-iTD"/>
- <constraint firstItem="ymk-0u-ddH" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="qrv-wQ-p6E"/>
- <constraint firstItem="sjf-wF-y07" firstAttribute="top" secondItem="AjK-Ty-MRn" secondAttribute="bottom" constant="20" id="suK-qu-fvy"/>
- <constraint firstAttribute="trailing" secondItem="KXo-cP-gkc" secondAttribute="trailing" constant="10" id="uDa-6r-K84"/>
- <constraint firstItem="AjK-Ty-MRn" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="10" id="vWx-aM-wFJ"/>
- <constraint firstAttribute="trailing" secondItem="qll-9F-4DA" secondAttribute="trailing" constant="10" id="vaT-9Q-m84"/>
- <constraint firstItem="F4T-wQ-tBU" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="13" id="x4S-GE-lJ8"/>
- <constraint firstAttribute="trailing" secondItem="HaY-OM-mQh" secondAttribute="trailing" constant="10" id="yvI-xV-T7d"/>
- <constraint firstItem="Ff4-JE-zGU" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="zc7-db-OeN"/>
- <constraint firstItem="UIn-eq-hkP" firstAttribute="top" secondItem="sjf-wF-y07" secondAttribute="bottom" constant="20" id="zex-fG-9ns"/>
- </constraints>
- <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
- <connections>
- <outlet property="buttonAddAnotherLink" destination="0bK-Kl-hcs" id="XMo-Cp-y6f"/>
- <outlet property="buttonDeleteShareLink" destination="CLA-UL-mYb" id="LVP-Vh-RHb"/>
- <outlet property="fieldLabel" destination="AjK-Ty-MRn" id="qar-eZ-ctz"/>
- <outlet property="fieldNoteToRecipient" destination="FyH-3p-EdC" id="EBz-iA-1tq"/>
- <outlet property="fieldPasswordProtect" destination="e1F-PV-32s" id="c1Y-0f-UYD"/>
- <outlet property="fieldSetExpirationDate" destination="ymk-0u-ddH" id="W6o-xf-Zj2"/>
- <outlet property="imageAddAnotherLink" destination="6SU-Ak-Q7m" id="Is7-q2-ZJu"/>
- <outlet property="imageDeleteShareLink" destination="hr8-Qe-xD0" id="hGE-fg-rnv"/>
- <outlet property="imageNoteToRecipient" destination="F4T-wQ-tBU" id="IHc-Q2-VxM"/>
- <outlet property="labelAddAnotherLink" destination="cna-iK-PD7" id="xax-ip-GpR"/>
- <outlet property="labelAllowEditing" destination="IHP-P8-rm2" id="bfP-WI-ryB"/>
- <outlet property="labelDeleteShareLink" destination="Ff4-JE-zGU" id="7jH-iS-zf8"/>
- <outlet property="labelHideDownload" destination="KXo-cP-gkc" id="vis-Zu-pga"/>
- <outlet property="labelNoteToRecipient" destination="grT-sd-j7q" id="yOv-Ke-EnF"/>
- <outlet property="labelPasswordProtect" destination="HaY-OM-mQh" id="nlG-u7-v1H"/>
- <outlet property="labelSetExpirationDate" destination="qll-9F-4DA" id="K8B-Ys-V8e"/>
- <outlet property="switchAllowEditing" destination="sjf-wF-y07" id="8J2-kj-Ugp"/>
- <outlet property="switchHideDownload" destination="UIn-eq-hkP" id="25D-zI-MEj"/>
- <outlet property="switchPasswordProtect" destination="HDO-WC-RvJ" id="K7a-3i-8kx"/>
- <outlet property="switchSetExpirationDate" destination="dB8-1M-WZr" id="R5d-Hf-ga6"/>
- </connections>
- <point key="canvasLocation" x="-60" y="350.625"/>
- </view>
- </objects>
- <resources>
- <image name="add" width="25" height="25"/>
- <image name="file_txt" width="300" height="300"/>
- <image name="trash" width="512" height="512"/>
- </resources>
-</document>
diff --git a/iOSClient/Share/NCShareNetworking.swift b/iOSClient/Share/NCShareNetworking.swift
index 04052ec9b..cb65673c2 100644
--- a/iOSClient/Share/NCShareNetworking.swift
+++ b/iOSClient/Share/NCShareNetworking.swift
@@ -53,8 +53,8 @@ class NCShareNetworking: NSObject {
NCUtility.shared.stopActivityIndicator()
}
- if errorCode == 0 && shares != nil {
- NCManageDatabase.shared.addShare(urlBase: self.urlBase, account: self.metadata.account, shares: shares!)
+ if errorCode == 0, let shares = shares {
+ NCManageDatabase.shared.addShare(urlBase: self.urlBase, account: self.metadata.account, shares: shares)
self.appDelegate.shares = NCManageDatabase.shared.getTableShares(account: self.metadata.account)
} else {
NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError)
@@ -62,35 +62,27 @@ class NCShareNetworking: NSObject {
self.delegate?.readShareCompleted()
}
}
-
- func createShareLink(password: String?) {
- NCUtility.shared.startActivityIndicator(backgroundView: view, blurEffect: false)
- let filenamePath = CCUtility.returnFileNamePath(fromFileName: metadata.fileName, serverUrl: metadata.serverUrl, urlBase: urlBase, account: metadata.account)!
- NCCommunication.shared.createShareLink(path: filenamePath, password: password) { account, share, errorCode, errorDescription in
- NCUtility.shared.stopActivityIndicator()
- if errorCode == 0 && share != nil {
- NCManageDatabase.shared.addShare(urlBase: self.urlBase, account: self.metadata.account, shares: [share!])
- self.appDelegate.shares = NCManageDatabase.shared.getTableShares(account: self.metadata.account)
- } else if errorCode != 0 {
- NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError)
- }
- self.delegate?.shareCompleted()
- }
- }
- func createShare(shareWith: String, shareType: Int, password: String?, metadata: tableMetadata) {
+ func createShare(option: NCTableShareable) {
+ // NOTE: Permissions don't work for creating with file drop!
+ // https://github.com/nextcloud/server/issues/17504
+
+ // NOTE: Can't save label, expirationDate, and note in same request.
+ // Library update needed:
+ // https://github.com/nextcloud/ios-communication-library/pull/104
+
NCUtility.shared.startActivityIndicator(backgroundView: view, blurEffect: false)
let filenamePath = CCUtility.returnFileNamePath(fromFileName: metadata.fileName, serverUrl: metadata.serverUrl, urlBase: urlBase, account: metadata.account)!
- var permission: Int = NCManageDatabase.shared.getCapabilitiesServerInt(account: metadata.account, elements: ["ocs", "data", "capabilities", "files_sharing", "default_permissions"])
- if permission <= 0 {
- permission = metadata.directory ? NCGlobal.shared.permissionMaxFolderShare : NCGlobal.shared.permissionMaxFileShare
- }
- NCCommunication.shared.createShare(path: filenamePath, shareType: shareType, shareWith: shareWith, password: password, permissions: permission) { (account, share, errorCode, errorDescription) in
+ 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()
- if errorCode == 0 && share != nil {
- NCManageDatabase.shared.addShare(urlBase: self.urlBase, account: self.metadata.account, shares: [share!])
+ if errorCode == 0, let share = share {
+ option.idShare = share.idShare
+ NCManageDatabase.shared.addShare(urlBase: self.urlBase, account: self.metadata.account, shares: [share])
self.appDelegate.shares = NCManageDatabase.shared.getTableShares(account: self.metadata.account)
+ if option.hasChanges(comparedTo: share) {
+ self.updateShare(option: option)
+ }
} else {
NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError)
}
@@ -111,17 +103,17 @@ class NCShareNetworking: NSObject {
}
}
- func updateShare(idShare: Int, password: String?, permissions: Int, note: String?, label: String?, expirationDate: String?, hideDownload: Bool) {
+ func updateShare(option: NCTableShareable) {
NCUtility.shared.startActivityIndicator(backgroundView: view, blurEffect: false)
- NCCommunication.shared.updateShare(idShare: idShare, password: password, expireDate: expirationDate, permissions: permissions, note: note, label: label, hideDownload: hideDownload) { account, share, errorCode, errorDescription in
+ 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()
- if errorCode == 0 && share != nil {
- NCManageDatabase.shared.addShare(urlBase: self.urlBase, account: self.metadata.account, shares: [share!])
+ 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)
self.delegate?.readShareCompleted()
} else {
NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorInternalError)
- self.delegate?.updateShareWithError(idShare: idShare)
+ self.delegate?.updateShareWithError(idShare: option.idShare)
}
}
}
diff --git a/iOSClient/Share/NCSharePaging.swift b/iOSClient/Share/NCSharePaging.swift
index fdf8d59d0..c86f79b4b 100644
--- a/iOSClient/Share/NCSharePaging.swift
+++ b/iOSClient/Share/NCSharePaging.swift
@@ -27,14 +27,19 @@ import Parchment
import NCCommunication
import MarqueeLabel
+protocol NCSharePagingContent {
+ var textField: UITextField? { get }
+}
+
class NCSharePaging: UIViewController {
private let pagingViewController = NCShareHeaderViewController()
- private let appDelegate = UIApplication.shared.delegate as! AppDelegate
+ private weak var appDelegate = UIApplication.shared.delegate as? AppDelegate
private var activityEnabled = true
private var commentsEnabled = true
private var sharingEnabled = true
+ private var currentVC: NCSharePagingContent?
@objc var metadata = tableMetadata()
var indexPage = NCGlobal.NCSharePagingIndex.activity
@@ -47,28 +52,9 @@ class NCSharePaging: UIViewController {
view.backgroundColor = NCBrandColor.shared.systemBackground
navigationItem.leftBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_close_", comment: ""), style: .done, target: self, action: #selector(exitTapped))
-
- // Verify Comments & Sharing enabled
- let serverVersionMajor = NCManageDatabase.shared.getCapabilitiesServerInt(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesVersionMajor)
- let comments = NCManageDatabase.shared.getCapabilitiesServerBool(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesFilesComments, exists: false)
- if serverVersionMajor >= NCGlobal.shared.nextcloudVersion20 && comments == false {
- commentsEnabled = false
- }
- let sharing = NCManageDatabase.shared.getCapabilitiesServerBool(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesFileSharingApiEnabled, exists: false)
- if sharing == false {
- sharingEnabled = false
- }
- let activity = NCManageDatabase.shared.getCapabilitiesServerArray(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesActivity)
- if activity == nil {
- activityEnabled = false
- }
- if indexPage == .sharing && !sharingEnabled {
- indexPage = .activity
- }
- if indexPage == .activity && !activityEnabled && sharingEnabled {
- indexPage = .sharing
- }
-
+ NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
+ NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
+ setupCapabilities()
// *** MUST BE THE FIRST ONE ***
pagingViewController.metadata = metadata
@@ -97,26 +83,53 @@ class NCSharePaging: UIViewController {
// Contrain the paging view to all edges.
pagingViewController.view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
- pagingViewController.view.topAnchor.constraint(equalTo: view.topAnchor),
- pagingViewController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
- pagingViewController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
- pagingViewController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor)
+ pagingViewController.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
+ pagingViewController.view.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
+ pagingViewController.view.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
+ pagingViewController.view.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor)
])
pagingViewController.dataSource = self
pagingViewController.delegate = self
pagingViewController.select(index: indexPage.rawValue)
- let pagingIndexItem = self.pagingViewController(pagingViewController, pagingItemAt: indexPage.rawValue) as! PagingIndexItem
- self.title = pagingIndexItem.title
+ 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()
}
+ func setupCapabilities() {
+ guard let appDelegate = appDelegate else { return }
+
+ // Verify Comments & Sharing enabled
+ let serverVersionMajor = NCManageDatabase.shared.getCapabilitiesServerInt(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesVersionMajor)
+ let comments = NCManageDatabase.shared.getCapabilitiesServerBool(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesFilesComments, exists: false)
+ if serverVersionMajor >= NCGlobal.shared.nextcloudVersion20 && comments == false {
+ commentsEnabled = false
+ }
+ let sharing = NCManageDatabase.shared.getCapabilitiesServerBool(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesFileSharingApiEnabled, exists: false)
+ sharingEnabled = sharing
+ let activity = NCManageDatabase.shared.getCapabilitiesServerArray(account: appDelegate.account, elements: NCElementsJSON.shared.capabilitiesActivity)
+ activityEnabled = activity != nil
+
+ if indexPage == .sharing && !sharingEnabled {
+ indexPage = .activity
+ }
+ if indexPage == .activity && !activityEnabled && sharingEnabled {
+ indexPage = .sharing
+ }
+ }
+
+ override func viewDidAppear(_ animated: Bool) {
+ super.viewDidAppear(animated)
+ currentVC = pagingViewController.pageViewController.selectedViewController as? NCSharePagingContent
+ }
+
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
-
- if appDelegate.disableSharesView {
+ if appDelegate?.disableSharesView == true {
self.dismiss(animated: false, completion: nil)
}
@@ -127,21 +140,53 @@ 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])
}
- @objc func exitTapped() {
- self.dismiss(animated: true, completion: nil)
+ deinit {
+ NotificationCenter.default.removeObserver(self, name: UIDevice.orientationDidChangeNotification, object: nil)
+ NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardDidShowNotification, object: nil)
+ NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}
// MARK: - NotificationCenter
+ @objc func orientationDidChange() {
+ pagingViewController.menuItemSize = .fixed(
+ width: self.view.bounds.width / CGFloat(NCGlobal.NCSharePagingIndex.allCases.count),
+ height: 40)
+ currentVC?.textField?.resignFirstResponder()
+ }
+
@objc func changeTheming() {
pagingViewController.indicatorColor = NCBrandColor.shared.brandElement
- (pagingViewController.view as! NCSharePagingView).setupConstraints()
+ (pagingViewController.view as? NCSharePagingView)?.setupConstraints()
pagingViewController.reloadMenu()
}
+
+ // MARK: - Keyboard & TextField
+ @objc func keyboardWillShow(notification: Notification) {
+ let frameEndUserInfoKey = UIResponder.keyboardFrameEndUserInfoKey
+
+ guard let info = notification.userInfo,
+ let textField = currentVC?.textField,
+ let centerObject = textField.superview?.convert(textField.center, to: nil),
+ let keyboardFrame = info[frameEndUserInfoKey] as? CGRect
+ else { return }
+
+ let diff = keyboardFrame.origin.y - centerObject.y - textField.frame.height
+ if diff < 0 {
+ view.frame.origin.y = diff
+ }
+ }
+
+ @objc func keyboardWillHide(notification: NSNotification) {
+ view.frame.origin.y = 0
+ }
+
+ @objc func exitTapped() {
+ self.dismiss(animated: true, completion: nil)
+ }
}
// MARK: - PagingViewController Delegate
@@ -155,13 +200,14 @@ extension NCSharePaging: PagingViewControllerDelegate {
let itemIndex = NCGlobal.NCSharePagingIndex(rawValue: item.index)
else { return }
- if itemIndex == .activity && !activityEnabled {
- pagingViewController.contentInteraction = .none
- } else if itemIndex == .sharing && !sharingEnabled {
+ if itemIndex == .activity && !activityEnabled || itemIndex == .sharing && !sharingEnabled {
pagingViewController.contentInteraction = .none
} else {
self.title = item.title
}
+
+ currentVC?.textField?.resignFirstResponder()
+ self.currentVC = destinationViewController as? NCSharePagingContent
}
}
@@ -171,11 +217,13 @@ extension NCSharePaging: PagingViewControllerDataSource {
func pagingViewController(_: PagingViewController, viewControllerAt index: Int) -> UIViewController {
- let height = pagingViewController.options.menuHeight + NCSharePagingView.HeaderHeight
+ let height = pagingViewController.options.menuHeight + NCSharePagingView.headerHeight
switch NCGlobal.NCSharePagingIndex(rawValue: index) {
case .activity:
- let viewController = UIStoryboard(name: "NCActivity", bundle: nil).instantiateInitialViewController() as! NCActivity
+ guard let viewController = UIStoryboard(name: "NCActivity", bundle: nil).instantiateInitialViewController() as? NCActivity else {
+ return UIViewController()
+ }
viewController.height = height
viewController.showComments = true
viewController.didSelectItemEnable = false
@@ -183,7 +231,9 @@ extension NCSharePaging: PagingViewControllerDataSource {
viewController.objectType = "files"
return viewController
case .sharing:
- let viewController = UIStoryboard(name: "NCShare", bundle: nil).instantiateViewController(withIdentifier: "sharing") as! NCShare
+ guard let viewController = UIStoryboard(name: "NCShare", bundle: nil).instantiateViewController(withIdentifier: "sharing") as? NCShare else {
+ return UIViewController()
+ }
viewController.sharingEnabled = sharingEnabled
viewController.metadata = metadata
viewController.height = height
@@ -231,18 +281,16 @@ class NCShareHeaderViewController: PagingViewController {
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
- if NCGlobal.NCSharePagingIndex(rawValue: indexPath.item) == .activity && !activityEnabled {
- return
- } else if NCGlobal.NCSharePagingIndex(rawValue: indexPath.item) == .sharing && !sharingEnabled {
- return
- }
+ guard NCGlobal.NCSharePagingIndex(rawValue: indexPath.item) != .activity || activityEnabled,
+ NCGlobal.NCSharePagingIndex(rawValue: indexPath.item) != .sharing || sharingEnabled
+ else { return }
super.collectionView(collectionView, didSelectItemAt: indexPath)
}
}
class NCSharePagingView: PagingView {
- static let HeaderHeight: CGFloat = 250
+ static let headerHeight: CGFloat = 100
var metadata = tableMetadata()
var headerHeightConstraint: NSLayoutConstraint?
@@ -261,7 +309,7 @@ class NCSharePagingView: PagingView {
override func setupConstraints() {
- let headerView = Bundle.main.loadNibNamed("NCShareHeaderView", owner: self, options: nil)?.first as! NCShareHeaderView
+ guard let headerView = Bundle.main.loadNibNamed("NCShareHeaderView", owner: self, options: nil)?.first as? NCShareHeaderView else { return }
headerView.backgroundColor = NCBrandColor.shared.systemBackground
headerView.ocId = metadata.ocId
@@ -269,9 +317,9 @@ class NCSharePagingView: PagingView {
headerView.imageView.image = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag))
} else {
if metadata.directory {
- let image = UIImage(named: "folder")!
- headerView.imageView.image = image.image(color: NCBrandColor.shared.brandElement, size: image.size.width)
- } else if metadata.iconName.count > 0 {
+ let image = UIImage(named: "folder")
+ headerView.imageView.image = image?.image(color: NCBrandColor.shared.brandElement, size: image?.size.width ?? 0)
+ } else if !metadata.iconName.isEmpty {
headerView.imageView.image = UIImage(named: metadata.iconName)
} else {
headerView.imageView.image = UIImage(named: "file")
@@ -292,9 +340,7 @@ class NCSharePagingView: PagingView {
collectionView.translatesAutoresizingMaskIntoConstraints = false
headerView.translatesAutoresizingMaskIntoConstraints = false
- headerHeightConstraint = headerView.heightAnchor.constraint(
- equalToConstant: NCSharePagingView.HeaderHeight
- )
+ headerHeightConstraint = headerView.heightAnchor.constraint(equalToConstant: NCSharePagingView.headerHeight)
headerHeightConstraint?.isActive = true
NSLayoutConstraint.activate([
@@ -325,32 +371,26 @@ class NCShareHeaderView: UIView {
override func awakeFromNib() {
super.awakeFromNib()
-
let longGesture = UILongPressGestureRecognizer(target: self, action: #selector(self.longTap))
path.addGestureRecognizer(longGesture)
}
@IBAction func touchUpInsideFavorite(_ sender: UIButton) {
- if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
- NCNetworking.shared.favoriteMetadata(metadata) { errorCode, errorDescription in
- if errorCode == 0 {
- if !metadata.favorite {
- self.favorite.setImage(NCUtility.shared.loadImage(named: "star.fill", color: NCBrandColor.shared.yellowFavorite, size: 20), for: .normal)
- } else {
- self.favorite.setImage(NCUtility.shared.loadImage(named: "star.fill", color: NCBrandColor.shared.systemGray, size: 20), for: .normal)
- }
- } else {
- NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
- }
+ guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return }
+ NCNetworking.shared.favoriteMetadata(metadata) { errorCode, errorDescription in
+ if errorCode == 0 {
+ self.favorite.setImage(NCUtility.shared.loadImage(
+ named: "star.fill",
+ color: metadata.favorite ? NCBrandColor.shared.yellowFavorite : NCBrandColor.shared.systemGray,
+ size: 20), for: .normal)
+ } else {
+ NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
}
}
}
@objc func longTap(sender: UIGestureRecognizer) {
-
- let board = UIPasteboard.general
- board.string = path.text
-
+ UIPasteboard.general.string = path.text
NCContentPresenter.shared.messageNotification("", description: "_copied_path_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorNoError)
}
}
diff --git a/iOSClient/Share/NCShareQuickStatusMenu.swift b/iOSClient/Share/NCShareQuickStatusMenu.swift
deleted file mode 100644
index 71d4a4be6..000000000
--- a/iOSClient/Share/NCShareQuickStatusMenu.swift
+++ /dev/null
@@ -1,66 +0,0 @@
-//
-// NCShareQuickStatusMenu.swift
-// Nextcloud
-//
-// Created by TSI-mc on 30/06/21.
-// Copyright © 2021 Marino Faggiana. All rights reserved.
-//
-
-import UIKit
-
-class NCShareQuickStatusMenu: NSObject {
-
- func toggleMenu(viewController: UIViewController, directory: Bool, tableShare: tableShare) {
-
- print(tableShare.permissions)
- let menuViewController = UIStoryboard(name: "NCMenu", bundle: nil).instantiateInitialViewController() as! NCMenu
- var actions = [NCMenuAction]()
-
- actions.append(
- NCMenuAction(
- title: NSLocalizedString("_share_read_only_", comment: ""),
- icon: UIImage(),
- selected: tableShare.permissions == (NCGlobal.shared.permissionReadShare + NCGlobal.shared.permissionShareShare) || tableShare.permissions == NCGlobal.shared.permissionReadShare,
- on: false,
- action: { _ in
- let canShare = CCUtility.isPermission(toCanShare: tableShare.permissions)
- let permissions = CCUtility.getPermissionsValue(byCanEdit: false, andCanCreate: false, andCanChange: false, andCanDelete: false, andCanShare: canShare, andIsFolder: directory)
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterShareChangePermissions, userInfo: ["idShare": tableShare.idShare, "permissions": permissions, "hideDownload": tableShare.hideDownload])
- }
- )
- )
-
- actions.append(
- NCMenuAction(
- title: directory ? NSLocalizedString("_share_allow_upload_", comment: "") : NSLocalizedString("_share_editing_", comment: ""),
- icon: UIImage(),
- selected: hasUploadPermission(tableShare: tableShare),
- on: false,
- action: { _ in
- let canShare = CCUtility.isPermission(toCanShare: tableShare.permissions)
- let permissions = CCUtility.getPermissionsValue(byCanEdit: true, andCanCreate: true, andCanChange: true, andCanDelete: true, andCanShare: canShare, andIsFolder: directory)
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterShareChangePermissions, userInfo: ["idShare": tableShare.idShare, "permissions": permissions, "hideDownload": tableShare.hideDownload])
- }
- )
- )
-
- menuViewController.actions = actions
-
- let menuPanelController = NCMenuPanelController()
- menuPanelController.parentPresenter = viewController
- menuPanelController.delegate = menuViewController
- menuPanelController.set(contentViewController: menuViewController)
- menuPanelController.track(scrollView: menuViewController.tableView)
-
- viewController.present(menuPanelController, animated: true, completion: nil)
- }
-
- fileprivate func hasUploadPermission(tableShare: tableShare) -> Bool {
- let uploadPermissions = [
- NCGlobal.shared.permissionMaxFileShare,
- NCGlobal.shared.permissionMaxFolderShare,
- NCGlobal.shared.permissionDefaultFileRemoteShareNoSupportShareOption,
- NCGlobal.shared.permissionDefaultFolderRemoteShareNoSupportShareOption]
- return uploadPermissions.contains(tableShare.permissions)
- }
-}
diff --git a/iOSClient/Share/NCShareUserCell.swift b/iOSClient/Share/NCShareUserCell.swift
index c20fe3dc0..97ef503b2 100644
--- a/iOSClient/Share/NCShareUserCell.swift
+++ b/iOSClient/Share/NCShareUserCell.swift
@@ -22,6 +22,7 @@
import UIKit
import DropDown
+import NCCommunication
class NCShareUserCell: UITableViewCell, NCCellProtocol {
@@ -37,24 +38,54 @@ class NCShareUserCell: UITableViewCell, NCCellProtocol {
var tableShare: tableShare?
weak var delegate: NCShareUserCellDelegate?
- var fileAvatarImageView: UIImageView? {
- get {
- return imageItem
- }
- }
- var fileObjectId: String? {
- get {
- return nil
+ var fileAvatarImageView: UIImageView? { return imageItem }
+ var fileObjectId: String? { return nil }
+ var filePreviewImageView: UIImageView? { return nil }
+ var fileUser: String? { return tableShare?.shareWith }
+
+ func setupCellUI(userId: String) {
+ guard let tableShare = tableShare else {
+ return
}
- }
- var filePreviewImageView: UIImageView? {
- get {
- return nil
+ self.accessibilityCustomActions = [UIAccessibilityCustomAction(
+ name: NSLocalizedString("_show_profile_", comment: ""),
+ target: self,
+ selector: #selector(tapAvatarImage))]
+
+ labelTitle.text = tableShare.shareWithDisplayname
+ labelTitle.textColor = NCBrandColor.shared.label
+ isUserInteractionEnabled = true
+ labelQuickStatus.isHidden = false
+ imageDownArrow.isHidden = false
+ buttonMenu.isHidden = false
+ buttonMenu.accessibilityLabel = NSLocalizedString("_more_", comment: "")
+ imageItem.image = NCShareCommon.shared.getImageShareType(shareType: tableShare.shareType)
+
+ let status = NCUtility.shared.getUserStatus(userIcon: tableShare.userIcon, userStatus: tableShare.userStatus, userMessage: tableShare.userMessage)
+ imageStatus.image = status.onlineStatus
+ self.status.text = status.statusMessage
+
+ // If the initiator or the recipient is not the current user, show the list of sharees without any options to edit it.
+ if tableShare.uidOwner != userId && tableShare.uidFileOwner != userId {
+ isUserInteractionEnabled = false
+ labelQuickStatus.isHidden = true
+ imageDownArrow.isHidden = true
+ buttonMenu.isHidden = true
}
- }
- var fileUser: String? {
- get {
- return tableShare?.shareWith
+
+ btnQuickStatus.accessibilityHint = NSLocalizedString("_user_sharee_footer_", comment: "")
+ btnQuickStatus.setTitle("", for: .normal)
+ btnQuickStatus.contentHorizontalAlignment = .left
+
+ if tableShare.permissions == NCGlobal.shared.permissionCreateShare {
+ labelQuickStatus.text = NSLocalizedString("_share_file_drop_", comment: "")
+ } else {
+ // Read Only
+ if CCUtility.isAnyPermission(toEdit: tableShare.permissions) {
+ labelQuickStatus.text = NSLocalizedString("_share_editing_", comment: "")
+ } else {
+ labelQuickStatus.text = NSLocalizedString("_share_read_only_", comment: "")
+ }
}
}
@@ -63,7 +94,7 @@ class NCShareUserCell: UITableViewCell, NCCellProtocol {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapAvatarImage))
imageItem?.addGestureRecognizer(tapGesture)
- buttonMenu.setImage(UIImage(named: "shareMenu")!.image(color: .gray, size: 50), for: .normal)
+ buttonMenu.setImage(UIImage(named: "shareMenu")?.image(color: .gray, size: 50), for: .normal)
labelQuickStatus.textColor = NCBrandColor.shared.customer
imageDownArrow.image = NCUtility.shared.loadImage(named: "arrowtriangle.down.fill", color: NCBrandColor.shared.customer)
}
@@ -87,9 +118,9 @@ protocol NCShareUserCellDelegate: AnyObject {
func quickStatus(with tableShare: tableShare?, sender: Any)
}
-// MARK: - NCShareUserDropDownCell
+// MARK: - NCSearchUserDropDownCell
-class NCShareUserDropDownCell: DropDownCell, NCCellProtocol {
+class NCSearchUserDropDownCell: DropDownCell, NCCellProtocol {
@IBOutlet weak var imageItem: UIImageView!
@IBOutlet weak var imageStatus: UIImageView!
@@ -99,21 +130,9 @@ class NCShareUserDropDownCell: DropDownCell, NCCellProtocol {
private var user: String = ""
- var fileAvatarImageView: UIImageView? {
- get {
- return imageItem
- }
- }
- var fileObjectId: String? {
- get {
- return nil
- }
- }
- var filePreviewImageView: UIImageView? {
- get {
- return nil
- }
- }
+ var fileAvatarImageView: UIImageView? { return imageItem }
+ var fileObjectId: String? { return nil }
+ var filePreviewImageView: UIImageView? { return nil }
var fileUser: String? {
get {
return user
@@ -122,4 +141,44 @@ class NCShareUserDropDownCell: DropDownCell, NCCellProtocol {
user = newValue ?? ""
}
}
+
+ func setupCell(sharee: NCCommunicationSharee, baseUrl: NCUserBaseUrl) {
+ imageItem.image = NCShareCommon.shared.getImageShareType(shareType: sharee.shareType)
+ imageShareeType.image = NCShareCommon.shared.getImageShareType(shareType: sharee.shareType)
+ let status = NCUtility.shared.getUserStatus(userIcon: sharee.userIcon, userStatus: sharee.userStatus, userMessage: sharee.userMessage)
+ imageStatus.image = status.onlineStatus
+ self.status.text = status.statusMessage
+ if self.status.text?.count ?? 0 > 0 {
+ centerTitle.constant = -5
+ } else {
+ centerTitle.constant = 0
+ }
+
+ imageItem.image = NCUtility.shared.loadUserImage(
+ for: sharee.shareWith,
+ displayName: nil,
+ userBaseUrl: baseUrl)
+
+ let fileName = baseUrl.userBaseUrl + "-" + sharee.shareWith + ".png"
+ if NCManageDatabase.shared.getImageAvatarLoaded(fileName: fileName) == nil {
+ let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName
+ let etag = NCManageDatabase.shared.getTableAvatar(fileName: fileName)?.etag
+
+ NCCommunication.shared.downloadAvatar(
+ user: sharee.shareWith,
+ fileNameLocalPath: fileNameLocalPath,
+ sizeImage: NCGlobal.shared.avatarSize,
+ avatarSizeRounded: NCGlobal.shared.avatarSizeRounded,
+ etag: etag) { _, imageAvatar, _, etag, errorCode, _ in
+
+ if errorCode == 0, let etag = etag, let imageAvatar = imageAvatar {
+ NCManageDatabase.shared.addAvatar(fileName: fileName, etag: etag)
+ self.imageItem.image = imageAvatar
+ } else if errorCode == NCGlobal.shared.errorNotModified, let imageAvatar = NCManageDatabase.shared.setAvatarLoaded(fileName: fileName) {
+ self.imageItem.image = imageAvatar
+ }
+ }
+ }
+
+ }
}
diff --git a/iOSClient/Share/NCShareUserFolderMenuView.xib b/iOSClient/Share/NCShareUserFolderMenuView.xib
deleted file mode 100644
index 2908ef2a1..000000000
--- a/iOSClient/Share/NCShareUserFolderMenuView.xib
+++ /dev/null
@@ -1,226 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19455" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
- <device id="retina3_5" orientation="portrait" appearance="light"/>
- <dependencies>
- <deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19454"/>
- <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"/>
- <view opaque="NO" contentMode="scaleToFill" id="iN0-l3-epB" customClass="NCShareUserMenuView" customModule="Nextcloud" customModuleProvider="target">
- <rect key="frame" x="0.0" y="0.0" width="250" height="420"/>
- <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
- <subviews>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="sjf-wF-y07">
- <rect key="frame" x="10" y="10" width="51" height="31"/>
- <connections>
- <action selector="switchCanReshareChangedWithSender:" destination="iN0-l3-epB" eventType="valueChanged" id="Ezn-AP-uEh"/>
- </connections>
- </switch>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Can reshare" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="IHP-P8-rm2">
- <rect key="frame" x="70" y="18" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="lcS-7f-bEg"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="dB8-1M-WZr">
- <rect key="frame" x="10" y="214" width="51" height="31"/>
- <connections>
- <action selector="switchSetExpirationDateWithSender:" destination="iN0-l3-epB" eventType="valueChanged" id="A9c-YF-bXd"/>
- </connections>
- </switch>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Set expiration date" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qll-9F-4DA">
- <rect key="frame" x="70" y="222" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="KyU-PL-PRI"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="ymk-0u-ddH">
- <rect key="frame" x="70" y="247" width="170" height="30"/>
- <constraints>
- <constraint firstAttribute="height" constant="30" id="G4f-LN-v7k"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <textInputTraits key="textInputTraits"/>
- <connections>
- <action selector="fieldSetExpirationDateWithSender:" destination="iN0-l3-epB" eventType="editingDidEndOnExit" id="WdF-Ie-Di0"/>
- </connections>
- </textField>
- <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="file_txt" translatesAutoresizingMaskIntoConstraints="NO" id="F4T-wQ-tBU">
- <rect key="frame" x="13" y="297" width="25" height="25"/>
- <constraints>
- <constraint firstAttribute="height" constant="25" id="7uC-w2-XPl"/>
- <constraint firstAttribute="width" constant="25" id="YkI-0i-Hbj"/>
- </constraints>
- </imageView>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Note to recipient" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="grT-sd-j7q">
- <rect key="frame" x="70" y="302" width="175" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="gof-GU-toa"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="FyH-3p-EdC">
- <rect key="frame" x="70" y="327" width="170" height="34"/>
- <fontDescription key="fontDescription" type="system" pointSize="14"/>
- <textInputTraits key="textInputTraits"/>
- <connections>
- <action selector="fieldNoteToRecipientDidEndOnExitWithTextField:" destination="iN0-l3-epB" eventType="editingDidEndOnExit" id="q1P-u7-EBw"/>
- </connections>
- </textField>
- <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="trash" translatesAutoresizingMaskIntoConstraints="NO" id="hr8-Qe-xD0" userLabel="Image Delete Share Link">
- <rect key="frame" x="13" y="381" width="25" height="25"/>
- <constraints>
- <constraint firstAttribute="height" constant="25" id="Ktg-2f-87b"/>
- <constraint firstAttribute="width" constant="25" id="ZJu-Y5-U67"/>
- </constraints>
- </imageView>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Unshare" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ff4-JE-zGU">
- <rect key="frame" x="70" y="386" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="gYi-S0-IOg"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CLA-UL-mYb">
- <rect key="frame" x="13" y="381" width="217" height="25"/>
- <constraints>
- <constraint firstAttribute="height" constant="25" id="fWP-XF-kQx"/>
- </constraints>
- <connections>
- <action selector="buttonUnshareWithSender:" destination="iN0-l3-epB" eventType="touchUpInside" id="Nky-nT-rCz"/>
- </connections>
- </button>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="1br-PL-gFf">
- <rect key="frame" x="10" y="61" width="51" height="31"/>
- <connections>
- <action selector="switchCanCreateWithSender:" destination="iN0-l3-epB" eventType="valueChanged" id="M2Z-bc-ZKU"/>
- </connections>
- </switch>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Can create" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="G13-DS-7uC">
- <rect key="frame" x="70" y="69" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="nK7-xW-fbq"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="0yc-df-C1f">
- <rect key="frame" x="10" y="112" width="51" height="31"/>
- <connections>
- <action selector="switchCanChangeWithSender:" destination="iN0-l3-epB" eventType="valueChanged" id="XIQ-GD-IU7"/>
- </connections>
- </switch>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Can change" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YWL-Ks-51c">
- <rect key="frame" x="70" y="120" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="NYy-3u-P1R"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="vja-ge-I6S">
- <rect key="frame" x="10" y="163" width="51" height="31"/>
- <connections>
- <action selector="switchCanDeleteWithSender:" destination="iN0-l3-epB" eventType="valueChanged" id="BRV-e3-C17"/>
- </connections>
- </switch>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Can delete" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dZP-fH-9sg">
- <rect key="frame" x="70" y="171" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="p6u-3B-cFa"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- </subviews>
- <constraints>
- <constraint firstItem="Ff4-JE-zGU" firstAttribute="centerY" secondItem="hr8-Qe-xD0" secondAttribute="centerY" id="0WP-PE-HTp"/>
- <constraint firstItem="YWL-Ks-51c" firstAttribute="leading" secondItem="0yc-df-C1f" secondAttribute="trailing" constant="11" id="18d-Lv-xE7"/>
- <constraint firstItem="dZP-fH-9sg" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="2N4-ol-qeH"/>
- <constraint firstItem="IHP-P8-rm2" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="2RV-rL-sYG"/>
- <constraint firstItem="grT-sd-j7q" firstAttribute="centerY" secondItem="F4T-wQ-tBU" secondAttribute="centerY" id="4KH-Py-OgY"/>
- <constraint firstItem="qll-9F-4DA" firstAttribute="centerY" secondItem="dB8-1M-WZr" secondAttribute="centerY" id="5QL-7q-jdE"/>
- <constraint firstItem="vja-ge-I6S" firstAttribute="top" secondItem="0yc-df-C1f" secondAttribute="bottom" constant="20" id="6jy-3A-HWD"/>
- <constraint firstItem="FyH-3p-EdC" firstAttribute="top" secondItem="grT-sd-j7q" secondAttribute="bottom" constant="10" id="7al-MO-ezA"/>
- <constraint firstItem="dZP-fH-9sg" firstAttribute="centerY" secondItem="vja-ge-I6S" secondAttribute="centerY" id="7ne-dy-Lt1"/>
- <constraint firstItem="CLA-UL-mYb" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="13" id="8lb-ki-xfh"/>
- <constraint firstAttribute="trailing" secondItem="ymk-0u-ddH" secondAttribute="trailing" constant="10" id="Chd-iQ-EdR"/>
- <constraint firstItem="sjf-wF-y07" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="10" id="EW6-D3-tml"/>
- <constraint firstItem="0yc-df-C1f" firstAttribute="top" secondItem="1br-PL-gFf" secondAttribute="bottom" constant="20" id="FGV-mm-Ko5"/>
- <constraint firstItem="G13-DS-7uC" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="GqL-Dy-FyM"/>
- <constraint firstItem="1br-PL-gFf" firstAttribute="top" secondItem="sjf-wF-y07" secondAttribute="bottom" constant="20" id="HCV-Fc-QqK"/>
- <constraint firstAttribute="trailing" secondItem="YWL-Ks-51c" secondAttribute="trailing" constant="10" id="HHo-s3-88y"/>
- <constraint firstItem="IHP-P8-rm2" firstAttribute="centerY" secondItem="sjf-wF-y07" secondAttribute="centerY" id="HiA-pE-L6l"/>
- <constraint firstItem="1br-PL-gFf" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="JKb-Jd-pOz"/>
- <constraint firstItem="0yc-df-C1f" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="JYX-ih-uiD"/>
- <constraint firstItem="dB8-1M-WZr" firstAttribute="top" secondItem="vja-ge-I6S" secondAttribute="bottom" constant="20" id="NSb-s1-gmD"/>
- <constraint firstAttribute="trailing" secondItem="grT-sd-j7q" secondAttribute="trailing" constant="5" id="Nyn-RD-jTz"/>
- <constraint firstAttribute="trailing" secondItem="FyH-3p-EdC" secondAttribute="trailing" constant="10" id="RhU-wl-afT"/>
- <constraint firstItem="sjf-wF-y07" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="TFC-63-muN"/>
- <constraint firstItem="FyH-3p-EdC" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="TXe-jF-DdS"/>
- <constraint firstItem="dB8-1M-WZr" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="Ua2-93-05m"/>
- <constraint firstAttribute="trailing" secondItem="dZP-fH-9sg" secondAttribute="trailing" constant="10" id="Y3X-Bg-zXC"/>
- <constraint firstItem="CLA-UL-mYb" firstAttribute="centerY" secondItem="hr8-Qe-xD0" secondAttribute="centerY" id="Zoj-Ro-jFv"/>
- <constraint firstAttribute="trailing" secondItem="IHP-P8-rm2" secondAttribute="trailing" constant="10" id="Zsj-Ja-2wq"/>
- <constraint firstItem="F4T-wQ-tBU" firstAttribute="top" secondItem="ymk-0u-ddH" secondAttribute="bottom" constant="20" id="aj8-2w-ySe"/>
- <constraint firstItem="G13-DS-7uC" firstAttribute="centerY" secondItem="1br-PL-gFf" secondAttribute="centerY" id="cbx-hu-mhg"/>
- <constraint firstItem="hr8-Qe-xD0" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="13" id="elF-be-kqS"/>
- <constraint firstAttribute="trailing" secondItem="G13-DS-7uC" secondAttribute="trailing" constant="10" id="gKS-GP-xkX"/>
- <constraint firstItem="hr8-Qe-xD0" firstAttribute="top" secondItem="FyH-3p-EdC" secondAttribute="bottom" constant="20" id="itX-To-Hbm"/>
- <constraint firstItem="ymk-0u-ddH" firstAttribute="top" secondItem="qll-9F-4DA" secondAttribute="bottom" constant="10" id="k4G-Yb-xBy"/>
- <constraint firstItem="grT-sd-j7q" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="lRX-gv-77N"/>
- <constraint firstAttribute="trailing" secondItem="Ff4-JE-zGU" secondAttribute="trailing" constant="10" id="ljN-WF-OVS"/>
- <constraint firstAttribute="trailing" secondItem="CLA-UL-mYb" secondAttribute="trailing" constant="20" id="oEb-Su-Nu5"/>
- <constraint firstItem="YWL-Ks-51c" firstAttribute="centerY" secondItem="0yc-df-C1f" secondAttribute="centerY" id="p2G-NK-Qcr"/>
- <constraint firstItem="qll-9F-4DA" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="qEq-8J-iTD"/>
- <constraint firstItem="ymk-0u-ddH" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="qrv-wQ-p6E"/>
- <constraint firstItem="vja-ge-I6S" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="ukl-JN-XFD"/>
- <constraint firstAttribute="trailing" secondItem="qll-9F-4DA" secondAttribute="trailing" constant="10" id="vaT-9Q-m84"/>
- <constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="CLA-UL-mYb" secondAttribute="bottom" constant="10" id="w6T-Q9-OKA"/>
- <constraint firstItem="F4T-wQ-tBU" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="13" id="x4S-GE-lJ8"/>
- <constraint firstItem="Ff4-JE-zGU" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="zc7-db-OeN"/>
- </constraints>
- <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
- <connections>
- <outlet property="buttonUnshare" destination="CLA-UL-mYb" id="fwq-pr-JO0"/>
- <outlet property="fieldNoteToRecipient" destination="FyH-3p-EdC" id="389-TM-dhC"/>
- <outlet property="fieldSetExpirationDate" destination="ymk-0u-ddH" id="erm-BP-BWD"/>
- <outlet property="imageNoteToRecipient" destination="F4T-wQ-tBU" id="hv7-Ln-aYs"/>
- <outlet property="imageUnshare" destination="hr8-Qe-xD0" id="kfC-D4-Ak0"/>
- <outlet property="labelCanChange" destination="YWL-Ks-51c" id="3lh-TV-rKt"/>
- <outlet property="labelCanCreate" destination="G13-DS-7uC" id="BOR-I2-EVX"/>
- <outlet property="labelCanDelete" destination="dZP-fH-9sg" id="iCn-VY-P3p"/>
- <outlet property="labelCanReshare" destination="IHP-P8-rm2" id="dkZ-O3-1cB"/>
- <outlet property="labelNoteToRecipient" destination="grT-sd-j7q" id="0Rj-H1-Bqv"/>
- <outlet property="labelSetExpirationDate" destination="qll-9F-4DA" id="SsD-jd-FX1"/>
- <outlet property="labelUnshare" destination="Ff4-JE-zGU" id="Ubq-EL-yOd"/>
- <outlet property="switchCanChange" destination="0yc-df-C1f" id="JcH-18-ZRX"/>
- <outlet property="switchCanCreate" destination="1br-PL-gFf" id="3En-bH-Wzm"/>
- <outlet property="switchCanDelete" destination="vja-ge-I6S" id="NN7-2l-NSz"/>
- <outlet property="switchCanReshare" destination="sjf-wF-y07" id="3jS-Gr-YMT"/>
- <outlet property="switchSetExpirationDate" destination="dB8-1M-WZr" id="0Ki-ah-3FE"/>
- </connections>
- <point key="canvasLocation" x="1.875" y="195"/>
- </view>
- </objects>
- <resources>
- <image name="file_txt" width="300" height="300"/>
- <image name="trash" width="512" height="512"/>
- </resources>
-</document>
diff --git a/iOSClient/Share/NCShareUserMenuView.swift b/iOSClient/Share/NCShareUserMenuView.swift
deleted file mode 100644
index 9dd2c2be2..000000000
--- a/iOSClient/Share/NCShareUserMenuView.swift
+++ /dev/null
@@ -1,398 +0,0 @@
-//
-// NCShareUserMenuView.swift
-// Nextcloud
-//
-// Created by Marino Faggiana on 25/07/2019.
-// Copyright © 2019 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 FSCalendar
-import NCCommunication
-
-class NCShareUserMenuView: UIView, UIGestureRecognizerDelegate, UITextFieldDelegate, NCShareNetworkingDelegate, FSCalendarDelegate, FSCalendarDelegateAppearance {
-
- @IBOutlet weak var switchCanReshare: UISwitch!
- @IBOutlet weak var labelCanReshare: UILabel!
-
- @IBOutlet weak var switchCanCreate: UISwitch!
- @IBOutlet weak var labelCanCreate: UILabel!
-
- @IBOutlet weak var switchCanChange: UISwitch!
- @IBOutlet weak var labelCanChange: UILabel!
-
- @IBOutlet weak var switchCanDelete: UISwitch!
- @IBOutlet weak var labelCanDelete: UILabel!
-
- @IBOutlet weak var switchSetExpirationDate: UISwitch!
- @IBOutlet weak var labelSetExpirationDate: UILabel!
- @IBOutlet weak var fieldSetExpirationDate: UITextField!
-
- @IBOutlet weak var imageNoteToRecipient: UIImageView!
- @IBOutlet weak var labelNoteToRecipient: UILabel!
- @IBOutlet weak var fieldNoteToRecipient: UITextField!
-
- @IBOutlet weak var buttonUnshare: UIButton!
- @IBOutlet weak var labelUnshare: UILabel!
- @IBOutlet weak var imageUnshare: UIImageView!
-
- private let appDelegate = UIApplication.shared.delegate as! AppDelegate
-
- var width: CGFloat = 0
- var height: CGFloat = 0
-
- private var tableShare: tableShare?
- var metadata: tableMetadata?
- var shareViewController: NCShare?
- private var networking: NCShareNetworking?
-
- var viewWindow: UIView?
- var viewWindowCalendar: UIView?
- private var calendar: FSCalendar?
- private var activeTextfieldDiff: CGFloat = 0
- private var activeTextField = UITextField()
-
- override func awakeFromNib() {
-
- layer.borderColor = UIColor.lightGray.cgColor
- layer.borderWidth = 0.5
- layer.cornerRadius = 5
- layer.masksToBounds = false
- layer.shadowOffset = CGSize(width: 2, height: 2)
- layer.shadowOpacity = 0.2
-
- switchCanReshare.transform = CGAffineTransform(scaleX: 0.75, y: 0.75)
- switchCanReshare.onTintColor = NCBrandColor.shared.brandElement
- switchCanCreate?.transform = CGAffineTransform(scaleX: 0.75, y: 0.75)
- switchCanCreate?.onTintColor = NCBrandColor.shared.brandElement
- switchCanChange?.transform = CGAffineTransform(scaleX: 0.75, y: 0.75)
- switchCanChange?.onTintColor = NCBrandColor.shared.brandElement
- switchCanDelete?.transform = CGAffineTransform(scaleX: 0.75, y: 0.75)
- switchCanDelete?.onTintColor = NCBrandColor.shared.brandElement
- switchSetExpirationDate.transform = CGAffineTransform(scaleX: 0.75, y: 0.75)
- switchSetExpirationDate.onTintColor = NCBrandColor.shared.brandElement
-
- labelCanReshare?.text = NSLocalizedString("_share_can_reshare_", comment: "")
- labelCanReshare?.textColor = NCBrandColor.shared.label
- labelCanCreate?.text = NSLocalizedString("_share_can_create_", comment: "")
- labelCanCreate?.textColor = NCBrandColor.shared.label
- labelCanChange?.text = NSLocalizedString("_share_can_change_", comment: "")
- labelCanChange?.textColor = NCBrandColor.shared.label
- labelCanDelete?.text = NSLocalizedString("_share_can_delete_", comment: "")
- labelCanDelete?.textColor = NCBrandColor.shared.label
- labelSetExpirationDate?.text = NSLocalizedString("_share_expiration_date_", comment: "")
- labelSetExpirationDate?.textColor = NCBrandColor.shared.label
- labelNoteToRecipient?.text = NSLocalizedString("_share_note_recipient_", comment: "")
- labelNoteToRecipient?.textColor = NCBrandColor.shared.label
- labelUnshare?.text = NSLocalizedString("_share_unshare_", comment: "")
- labelUnshare?.textColor = NCBrandColor.shared.label
-
- fieldSetExpirationDate.inputView = UIView()
-
- fieldNoteToRecipient.delegate = self
-
- imageNoteToRecipient.image = UIImage(named: "file_txt")!.image(color: NCBrandColor.shared.gray, size: 50)
- imageUnshare.image = NCUtility.shared.loadImage(named: "trash", color: NCBrandColor.shared.gray, size: 50)
-
- NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
- NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
- }
-
- override func willMove(toWindow newWindow: UIWindow?) {
- super.willMove(toWindow: newWindow)
-
- if newWindow == nil {
- // UIView disappear
- shareViewController?.reloadData()
- } else {
- // UIView appear
- networking = NCShareNetworking(metadata: metadata!, urlBase: appDelegate.urlBase, view: self, delegate: self)
- }
- }
-
- func unLoad() {
- viewWindowCalendar?.removeFromSuperview()
- viewWindow?.removeFromSuperview()
-
- viewWindowCalendar = nil
- viewWindow = nil
- }
-
- func reloadData(idShare: Int) {
-
- guard let metadata = self.metadata else { return }
- tableShare = NCManageDatabase.shared.getTableShare(account: metadata.account, idShare: idShare)
- guard let tableShare = self.tableShare else { return }
-
- // Can reshare (file)
- let canReshare = CCUtility.isPermission(toCanShare: tableShare.permissions)
- switchCanReshare.setOn(canReshare, animated: false)
-
- if metadata.directory {
- // Can create (folder)
- let canCreate = CCUtility.isPermission(toCanCreate: tableShare.permissions)
- switchCanCreate.setOn(canCreate, animated: false)
-
- // Can change (folder)
- let canChange = CCUtility.isPermission(toCanChange: tableShare.permissions)
- switchCanChange.setOn(canChange, animated: false)
-
- // Can delete (folder)
- let canDelete = CCUtility.isPermission(toCanDelete: tableShare.permissions)
- switchCanDelete.setOn(canDelete, animated: false)
- }
-
- // Set expiration date
- if tableShare.expirationDate != nil {
- switchSetExpirationDate.setOn(true, animated: false)
- fieldSetExpirationDate.isEnabled = true
-
- let dateFormatter = DateFormatter()
- dateFormatter.formatterBehavior = .behavior10_4
- dateFormatter.dateStyle = .medium
- fieldSetExpirationDate.text = dateFormatter.string(from: tableShare.expirationDate! as Date)
- } else {
- switchSetExpirationDate.setOn(false, animated: false)
- fieldSetExpirationDate.isEnabled = false
- fieldSetExpirationDate.text = ""
- }
-
- // Note to recipient
- fieldNoteToRecipient.text = tableShare.note
- }
-
- func textFieldDidBeginEditing(_ textField: UITextField) {
-
- self.activeTextField = textField
- }
-
- // MARK: - Keyboard notification
-
- @objc internal func keyboardWillShow(_ notification: Notification?) {
-
- activeTextfieldDiff = 0
-
- if let info = notification?.userInfo, let centerObject = self.activeTextField.superview?.convert(self.activeTextField.center, to: nil) {
-
- let frameEndUserInfoKey = UIResponder.keyboardFrameEndUserInfoKey
- if let keyboardFrame = info[frameEndUserInfoKey] as? CGRect {
- let diff = keyboardFrame.origin.y - centerObject.y - self.activeTextField.frame.height
- if diff < 0 {
- activeTextfieldDiff = diff
- self.frame.origin.y += diff
- }
- }
- }
- }
-
- @objc func keyboardWillHide(_ notification: Notification) {
- self.frame.origin.y -= activeTextfieldDiff
- }
-
- // MARK: - Tap viewWindowCalendar
-
- @objc func tapViewWindowCalendar(gesture: UITapGestureRecognizer) {
- calendar?.removeFromSuperview()
- viewWindowCalendar?.removeFromSuperview()
-
- calendar = nil
- viewWindowCalendar = nil
-
- reloadData(idShare: tableShare?.idShare ?? 0)
- }
-
- func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
- return gestureRecognizer.view == touch.view
- }
-
- // MARK: - IBAction
-
- // Can reshare
- @IBAction func switchCanReshareChanged(sender: UISwitch) {
-
- guard let tableShare = self.tableShare else { return }
- guard let metadata = self.metadata else { return }
-
- let canEdit = CCUtility.isAnyPermission(toEdit: tableShare.permissions)
- let canCreate = CCUtility.isPermission(toCanCreate: tableShare.permissions)
- let canChange = CCUtility.isPermission(toCanChange: tableShare.permissions)
- let canDelete = CCUtility.isPermission(toCanDelete: tableShare.permissions)
-
- var permissions: Int = 0
-
- if metadata.directory {
- permissions = CCUtility.getPermissionsValue(byCanEdit: canEdit, andCanCreate: canCreate, andCanChange: canChange, andCanDelete: canDelete, andCanShare: sender.isOn, andIsFolder: metadata.directory)
- } else {
- if sender.isOn {
- if canEdit {
- permissions = CCUtility.getPermissionsValue(byCanEdit: true, andCanCreate: true, andCanChange: true, andCanDelete: true, andCanShare: sender.isOn, andIsFolder: metadata.directory)
- } else {
- permissions = CCUtility.getPermissionsValue(byCanEdit: false, andCanCreate: false, andCanChange: false, andCanDelete: false, andCanShare: sender.isOn, andIsFolder: metadata.directory)
- }
- } else {
- if canEdit {
- permissions = CCUtility.getPermissionsValue(byCanEdit: true, andCanCreate: true, andCanChange: true, andCanDelete: true, andCanShare: sender.isOn, andIsFolder: metadata.directory)
- } else {
- permissions = CCUtility.getPermissionsValue(byCanEdit: false, andCanCreate: false, andCanChange: false, andCanDelete: false, andCanShare: sender.isOn, andIsFolder: metadata.directory)
- }
- }
- }
-
- networking?.updateShare(idShare: tableShare.idShare, password: nil, permissions: permissions, note: nil, label: nil, expirationDate: nil, hideDownload: tableShare.hideDownload)
- }
-
- @IBAction func switchCanCreate(sender: UISwitch) {
-
- guard let tableShare = self.tableShare else { return }
- guard let metadata = self.metadata else { return }
-
- let canEdit = CCUtility.isAnyPermission(toEdit: tableShare.permissions)
- let canChange = CCUtility.isPermission(toCanChange: tableShare.permissions)
- let canDelete = CCUtility.isPermission(toCanDelete: tableShare.permissions)
- let canShare = CCUtility.isPermission(toCanShare: tableShare.permissions)
-
- let permissions = CCUtility.getPermissionsValue(byCanEdit: canEdit, andCanCreate: sender.isOn, andCanChange: canChange, andCanDelete: canDelete, andCanShare: canShare, andIsFolder: metadata.directory)
-
- networking?.updateShare(idShare: tableShare.idShare, password: nil, permissions: permissions, note: nil, label: nil, expirationDate: nil, hideDownload: tableShare.hideDownload)
- }
-
- @IBAction func switchCanChange(sender: UISwitch) {
-
- guard let tableShare = self.tableShare else { return }
- guard let metadata = self.metadata else { return }
-
- let canEdit = CCUtility.isAnyPermission(toEdit: tableShare.permissions)
- let canCreate = CCUtility.isPermission(toCanCreate: tableShare.permissions)
- let canDelete = CCUtility.isPermission(toCanDelete: tableShare.permissions)
- let canShare = CCUtility.isPermission(toCanShare: tableShare.permissions)
-
- let permissions = CCUtility.getPermissionsValue(byCanEdit: canEdit, andCanCreate: canCreate, andCanChange: sender.isOn, andCanDelete: canDelete, andCanShare: canShare, andIsFolder: metadata.directory)
-
- networking?.updateShare(idShare: tableShare.idShare, password: nil, permissions: permissions, note: nil, label: nil, expirationDate: nil, hideDownload: tableShare.hideDownload)
- }
-
- @IBAction func switchCanDelete(sender: UISwitch) {
-
- guard let tableShare = self.tableShare else { return }
- guard let metadata = self.metadata else { return }
-
- let canEdit = CCUtility.isAnyPermission(toEdit: tableShare.permissions)
- let canCreate = CCUtility.isPermission(toCanCreate: tableShare.permissions)
- let canChange = CCUtility.isPermission(toCanChange: tableShare.permissions)
- let canShare = CCUtility.isPermission(toCanShare: tableShare.permissions)
-
- let permissions = CCUtility.getPermissionsValue(byCanEdit: canEdit, andCanCreate: canCreate, andCanChange: canChange, andCanDelete: sender.isOn, andCanShare: canShare, andIsFolder: metadata.directory)
-
- networking?.updateShare(idShare: tableShare.idShare, password: nil, permissions: permissions, note: nil, label: nil, expirationDate: nil, hideDownload: tableShare.hideDownload)
- }
-
- // Set expiration date
- @IBAction func switchSetExpirationDate(sender: UISwitch) {
-
- guard let tableShare = self.tableShare else { return }
-
- if sender.isOn {
- fieldSetExpirationDate.isEnabled = true
- fieldSetExpirationDate(sender: fieldSetExpirationDate)
- } else {
- networking?.updateShare(idShare: tableShare.idShare, password: nil, permissions: tableShare.permissions, note: nil, label: nil, expirationDate: "", hideDownload: tableShare.hideDownload)
- }
- }
-
- @IBAction func fieldSetExpirationDate(sender: UITextField) {
-
- let calendar = NCShareCommon.shared.openCalendar(view: self, width: width, height: height)
- calendar.calendarView.delegate = self
- self.calendar = calendar.calendarView
- viewWindowCalendar = calendar.viewWindow
-
- let tap = UITapGestureRecognizer(target: self, action: #selector(tapViewWindowCalendar))
- tap.delegate = self
- viewWindowCalendar?.addGestureRecognizer(tap)
- }
-
- // Note to recipient
- @IBAction func fieldNoteToRecipientDidEndOnExit(textField: UITextField) {
-
- guard let tableShare = self.tableShare else { return }
- if fieldNoteToRecipient.text == nil { return }
-
- networking?.updateShare(idShare: tableShare.idShare, password: nil, permissions: tableShare.permissions, note: fieldNoteToRecipient.text, label: nil, expirationDate: nil, hideDownload: tableShare.hideDownload)
- }
-
- // Unshare
- @IBAction func buttonUnshare(sender: UIButton) {
-
- guard let tableShare = self.tableShare else { return }
-
- networking?.unShare(idShare: tableShare.idShare)
- }
-
- // MARK: - Delegate networking
-
- func readShareCompleted() {
- reloadData(idShare: tableShare?.idShare ?? 0)
- }
-
- func shareCompleted() {
- unLoad()
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataNCShare)
- }
-
- func unShareCompleted() {
- unLoad()
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataNCShare)
- }
-
- func updateShareWithError(idShare: Int) {
- reloadData(idShare: idShare)
- }
-
- func getSharees(sharees: [NCCommunicationSharee]?) { }
-
- // MARK: - Delegate calendar
-
- func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
-
- if monthPosition == .previous || monthPosition == .next {
- calendar.setCurrentPage(date, animated: true)
- } else {
- let dateFormatter = DateFormatter()
- dateFormatter.formatterBehavior = .behavior10_4
- dateFormatter.dateStyle = .medium
- fieldSetExpirationDate.text = dateFormatter.string(from: date)
- fieldSetExpirationDate.endEditing(true)
-
- viewWindowCalendar?.removeFromSuperview()
-
- guard let tableShare = self.tableShare else { return }
-
- dateFormatter.dateFormat = "YYYY-MM-dd HH:mm:ss"
- let expirationDate = dateFormatter.string(from: date)
-
- networking?.updateShare(idShare: tableShare.idShare, password: nil, permissions: tableShare.permissions, note: nil, label: nil, expirationDate: expirationDate, hideDownload: tableShare.hideDownload)
- }
- }
-
- func calendar(_ calendar: FSCalendar, shouldSelect date: Date, at monthPosition: FSCalendarMonthPosition) -> Bool {
- return date > Date()
- }
-
- func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, titleDefaultColorFor date: Date) -> UIColor? {
- return date > Date() ? NCBrandColor.shared.label : NCBrandColor.shared.systemGray3
- }
-}
diff --git a/iOSClient/Share/NCShareUserMenuView.xib b/iOSClient/Share/NCShareUserMenuView.xib
deleted file mode 100644
index 38a4304ad..000000000
--- a/iOSClient/Share/NCShareUserMenuView.xib
+++ /dev/null
@@ -1,160 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19455" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
- <device id="retina3_5" orientation="portrait" appearance="light"/>
- <dependencies>
- <deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19454"/>
- <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"/>
- <view opaque="NO" contentMode="scaleToFill" id="iN0-l3-epB" customClass="NCShareUserMenuView" customModule="Nextcloud" customModuleProvider="target">
- <rect key="frame" x="0.0" y="0.0" width="250" height="270"/>
- <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
- <subviews>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="sjf-wF-y07">
- <rect key="frame" x="10" y="10" width="51" height="31"/>
- <connections>
- <action selector="switchCanReshareChangedWithSender:" destination="iN0-l3-epB" eventType="valueChanged" id="Ezn-AP-uEh"/>
- </connections>
- </switch>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Can reshare" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="IHP-P8-rm2">
- <rect key="frame" x="70" y="18" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="lcS-7f-bEg"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="dB8-1M-WZr">
- <rect key="frame" x="10" y="61" width="51" height="31"/>
- <connections>
- <action selector="switchSetExpirationDateWithSender:" destination="iN0-l3-epB" eventType="valueChanged" id="A9c-YF-bXd"/>
- </connections>
- </switch>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Set expiration date" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qll-9F-4DA">
- <rect key="frame" x="70" y="69" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="KyU-PL-PRI"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="ymk-0u-ddH">
- <rect key="frame" x="70" y="94" width="170" height="30"/>
- <constraints>
- <constraint firstAttribute="height" constant="30" id="G4f-LN-v7k"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <textInputTraits key="textInputTraits"/>
- <connections>
- <action selector="fieldSetExpirationDateWithSender:" destination="iN0-l3-epB" eventType="editingDidEndOnExit" id="WdF-Ie-Di0"/>
- </connections>
- </textField>
- <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="file_txt" translatesAutoresizingMaskIntoConstraints="NO" id="F4T-wQ-tBU">
- <rect key="frame" x="13" y="144" width="25" height="25"/>
- <constraints>
- <constraint firstAttribute="height" constant="25" id="7uC-w2-XPl"/>
- <constraint firstAttribute="width" constant="25" id="YkI-0i-Hbj"/>
- </constraints>
- </imageView>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Note to recipient" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="grT-sd-j7q">
- <rect key="frame" x="70" y="149" width="175" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="gof-GU-toa"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="FyH-3p-EdC">
- <rect key="frame" x="70" y="174" width="170" height="34"/>
- <fontDescription key="fontDescription" type="system" pointSize="14"/>
- <textInputTraits key="textInputTraits"/>
- <connections>
- <action selector="fieldNoteToRecipientDidEndOnExitWithTextField:" destination="iN0-l3-epB" eventType="editingDidEndOnExit" id="q1P-u7-EBw"/>
- </connections>
- </textField>
- <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="trash" translatesAutoresizingMaskIntoConstraints="NO" id="hr8-Qe-xD0" userLabel="Image Delete Share Link">
- <rect key="frame" x="13" y="228" width="25" height="25"/>
- <constraints>
- <constraint firstAttribute="height" constant="25" id="Ktg-2f-87b"/>
- <constraint firstAttribute="width" constant="25" id="ZJu-Y5-U67"/>
- </constraints>
- </imageView>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Unshare" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ff4-JE-zGU">
- <rect key="frame" x="70" y="233" width="170" height="15"/>
- <constraints>
- <constraint firstAttribute="height" constant="15" id="gYi-S0-IOg"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="13"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CLA-UL-mYb">
- <rect key="frame" x="13" y="228" width="217" height="25"/>
- <constraints>
- <constraint firstAttribute="height" constant="25" id="fWP-XF-kQx"/>
- </constraints>
- <connections>
- <action selector="buttonUnshareWithSender:" destination="iN0-l3-epB" eventType="touchUpInside" id="Nky-nT-rCz"/>
- </connections>
- </button>
- </subviews>
- <constraints>
- <constraint firstItem="Ff4-JE-zGU" firstAttribute="centerY" secondItem="hr8-Qe-xD0" secondAttribute="centerY" id="0WP-PE-HTp"/>
- <constraint firstItem="IHP-P8-rm2" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="2RV-rL-sYG"/>
- <constraint firstItem="grT-sd-j7q" firstAttribute="centerY" secondItem="F4T-wQ-tBU" secondAttribute="centerY" id="4KH-Py-OgY"/>
- <constraint firstItem="qll-9F-4DA" firstAttribute="centerY" secondItem="dB8-1M-WZr" secondAttribute="centerY" id="5QL-7q-jdE"/>
- <constraint firstItem="FyH-3p-EdC" firstAttribute="top" secondItem="grT-sd-j7q" secondAttribute="bottom" constant="10" id="7al-MO-ezA"/>
- <constraint firstItem="CLA-UL-mYb" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="13" id="8lb-ki-xfh"/>
- <constraint firstAttribute="trailing" secondItem="ymk-0u-ddH" secondAttribute="trailing" constant="10" id="Chd-iQ-EdR"/>
- <constraint firstItem="sjf-wF-y07" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="10" id="EW6-D3-tml"/>
- <constraint firstItem="IHP-P8-rm2" firstAttribute="centerY" secondItem="sjf-wF-y07" secondAttribute="centerY" id="HiA-pE-L6l"/>
- <constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="CLA-UL-mYb" secondAttribute="bottom" constant="10" id="MQ9-xT-wSR"/>
- <constraint firstAttribute="trailing" secondItem="grT-sd-j7q" secondAttribute="trailing" constant="5" id="Nyn-RD-jTz"/>
- <constraint firstItem="dB8-1M-WZr" firstAttribute="top" secondItem="sjf-wF-y07" secondAttribute="bottom" constant="20" id="P2C-Pq-hSl"/>
- <constraint firstAttribute="trailing" secondItem="FyH-3p-EdC" secondAttribute="trailing" constant="10" id="RhU-wl-afT"/>
- <constraint firstItem="sjf-wF-y07" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="TFC-63-muN"/>
- <constraint firstItem="FyH-3p-EdC" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="TXe-jF-DdS"/>
- <constraint firstItem="dB8-1M-WZr" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="Ua2-93-05m"/>
- <constraint firstItem="CLA-UL-mYb" firstAttribute="centerY" secondItem="hr8-Qe-xD0" secondAttribute="centerY" id="Zoj-Ro-jFv"/>
- <constraint firstAttribute="trailing" secondItem="IHP-P8-rm2" secondAttribute="trailing" constant="10" id="Zsj-Ja-2wq"/>
- <constraint firstItem="F4T-wQ-tBU" firstAttribute="top" secondItem="ymk-0u-ddH" secondAttribute="bottom" constant="20" id="aj8-2w-ySe"/>
- <constraint firstItem="hr8-Qe-xD0" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="13" id="elF-be-kqS"/>
- <constraint firstItem="hr8-Qe-xD0" firstAttribute="top" secondItem="FyH-3p-EdC" secondAttribute="bottom" constant="20" id="itX-To-Hbm"/>
- <constraint firstItem="ymk-0u-ddH" firstAttribute="top" secondItem="qll-9F-4DA" secondAttribute="bottom" constant="10" id="k4G-Yb-xBy"/>
- <constraint firstItem="grT-sd-j7q" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="lRX-gv-77N"/>
- <constraint firstAttribute="trailing" secondItem="Ff4-JE-zGU" secondAttribute="trailing" constant="10" id="ljN-WF-OVS"/>
- <constraint firstAttribute="trailing" secondItem="CLA-UL-mYb" secondAttribute="trailing" constant="20" id="oEb-Su-Nu5"/>
- <constraint firstItem="qll-9F-4DA" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="qEq-8J-iTD"/>
- <constraint firstItem="ymk-0u-ddH" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="qrv-wQ-p6E"/>
- <constraint firstAttribute="trailing" secondItem="qll-9F-4DA" secondAttribute="trailing" constant="10" id="vaT-9Q-m84"/>
- <constraint firstItem="F4T-wQ-tBU" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="13" id="x4S-GE-lJ8"/>
- <constraint firstItem="Ff4-JE-zGU" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="70" id="zc7-db-OeN"/>
- </constraints>
- <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
- <connections>
- <outlet property="buttonUnshare" destination="CLA-UL-mYb" id="fwq-pr-JO0"/>
- <outlet property="fieldNoteToRecipient" destination="FyH-3p-EdC" id="389-TM-dhC"/>
- <outlet property="fieldSetExpirationDate" destination="ymk-0u-ddH" id="erm-BP-BWD"/>
- <outlet property="imageNoteToRecipient" destination="F4T-wQ-tBU" id="hv7-Ln-aYs"/>
- <outlet property="imageUnshare" destination="hr8-Qe-xD0" id="kfC-D4-Ak0"/>
- <outlet property="labelCanReshare" destination="IHP-P8-rm2" id="dkZ-O3-1cB"/>
- <outlet property="labelNoteToRecipient" destination="grT-sd-j7q" id="0Rj-H1-Bqv"/>
- <outlet property="labelSetExpirationDate" destination="qll-9F-4DA" id="SsD-jd-FX1"/>
- <outlet property="labelUnshare" destination="Ff4-JE-zGU" id="Ubq-EL-yOd"/>
- <outlet property="switchCanReshare" destination="sjf-wF-y07" id="3jS-Gr-YMT"/>
- <outlet property="switchSetExpirationDate" destination="dB8-1M-WZr" id="0Ki-ah-3FE"/>
- </connections>
- <point key="canvasLocation" x="2" y="196"/>
- </view>
- </objects>
- <resources>
- <image name="file_txt" width="300" height="300"/>
- <image name="trash" width="512" height="512"/>
- </resources>
-</document>
diff --git a/iOSClient/Supporting Files/af.lproj/InfoPlist.strings b/iOSClient/Supporting Files/af.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/af.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/af.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/af.lproj/Localizable.strings b/iOSClient/Supporting Files/af.lproj/Localizable.strings
index 8af22bc37..38666ba61 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/ar.lproj/InfoPlist.strings b/iOSClient/Supporting Files/ar.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/ar.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/ar.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ar.lproj/Localizable.strings b/iOSClient/Supporting Files/ar.lproj/Localizable.strings
index f1ac2903e..70d6407c0 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/InfoPlist.strings b/iOSClient/Supporting Files/ast.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/ast.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/ast.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ast.lproj/Localizable.strings b/iOSClient/Supporting Files/ast.lproj/Localizable.strings
index 09a842f36..96059f72a 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/InfoPlist.strings b/iOSClient/Supporting Files/az.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/az.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/az.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/az.lproj/Localizable.strings b/iOSClient/Supporting Files/az.lproj/Localizable.strings
index d7647967f..dd3846eeb 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/InfoPlist.strings b/iOSClient/Supporting Files/be.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/be.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/be.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/be.lproj/Localizable.strings b/iOSClient/Supporting Files/be.lproj/Localizable.strings
index 61aa73400..0c89fcb1e 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/InfoPlist.strings b/iOSClient/Supporting Files/bg_BG.lproj/InfoPlist.strings
index b907f6e78..e93a4a9cd 100644
--- a/iOSClient/Supporting Files/bg_BG.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/bg_BG.lproj/InfoPlist.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 ea077df63..c1f1efe32 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/InfoPlist.strings b/iOSClient/Supporting Files/bn_BD.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/bn_BD.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/bn_BD.lproj/InfoPlist.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 25c719311..58546a3cc 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/InfoPlist.strings b/iOSClient/Supporting Files/br.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/br.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/br.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/br.lproj/Localizable.strings b/iOSClient/Supporting Files/br.lproj/Localizable.strings
index 236b4c10a..ed158d553 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/InfoPlist.strings b/iOSClient/Supporting Files/bs.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/bs.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/bs.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/bs.lproj/Localizable.strings b/iOSClient/Supporting Files/bs.lproj/Localizable.strings
index afdb00d49..09e98ca41 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/InfoPlist.strings b/iOSClient/Supporting Files/ca.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/ca.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/ca.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ca.lproj/Localizable.strings b/iOSClient/Supporting Files/ca.lproj/Localizable.strings
index 5bd2b1379..4678b2456 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 93032bd6a..a345c34e5 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/InfoPlist.strings b/iOSClient/Supporting Files/cy_GB.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/cy_GB.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/cy_GB.lproj/InfoPlist.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 c38de2e6a..479794262 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/InfoPlist.strings b/iOSClient/Supporting Files/da.lproj/InfoPlist.strings
index 466a99c4a..9fe347b0d 100644
--- a/iOSClient/Supporting Files/da.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/da.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/da.lproj/Localizable.strings b/iOSClient/Supporting Files/da.lproj/Localizable.strings
index ddce71e31..4715b9ce4 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 ea3634aa7..849fecc6b 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/InfoPlist.strings b/iOSClient/Supporting Files/el.lproj/InfoPlist.strings
index b907f6e78..7c5a3231f 100644
--- a/iOSClient/Supporting Files/el.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/el.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/el.lproj/Localizable.strings b/iOSClient/Supporting Files/el.lproj/Localizable.strings
index 5b845b08c..3d34ca6c3 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/InfoPlist.strings b/iOSClient/Supporting Files/en-GB.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/en-GB.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/en-GB.lproj/InfoPlist.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 33332d7aa..e8e417484 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/InfoPlist.strings b/iOSClient/Supporting Files/en.lproj/InfoPlist.strings
index e163dea69..353940953 100644
--- a/iOSClient/Supporting Files/en.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/en.lproj/InfoPlist.strings
@@ -1,7 +1,7 @@
NSCameraUsageDescription = "Camera access is required to scan documents and make photo and video.";
NSFaceIDUsageDescription = "Face ID is required to authenticate using face recognition.";
-NSLocationAlwaysUsageDescription = "GPS is used to detect new photos from camera roll, continued use of GPS running in the background can dramatically decrease battery life.";
+NSLocationAlwaysUsageDescription = "GPS is used to detect new photos from camera roll. Continued use of GPS running in the background can dramatically decrease battery life.";
NSPhotoLibraryUsageDescription = "Photo library access is required to upload your photos and videos to your cloud.";
NSPhotoLibraryAddUsageDescription = "Photo library access is required to upload your photos and videos to your cloud.";
NSMicrophoneUsageDescription = "Microphone access is required to create voice notes.";
-NSLocationWhenInUseUsageDescription = "GPS is used to detect new photos from camera roll on background, the use of GPS only when the App is in use is useless.";
+NSLocationWhenInUseUsageDescription = "GPS is used to detect new photos from camera roll on background. It is useless to use GPS only while using the app.";
diff --git a/iOSClient/Supporting Files/en.lproj/Localizable.strings b/iOSClient/Supporting Files/en.lproj/Localizable.strings
index 49952614a..cb7ccaeae 100644
--- a/iOSClient/Supporting Files/en.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/en.lproj/Localizable.strings
@@ -22,8 +22,8 @@
"_cancel_" = "Cancel";
"_tap_to_cancel_" = "Tap to cancel";
+"_cancel_request_" = "Do you want to cancel?";
"_upload_file_" = "Upload file";
-"_accessibility_add_upload_" = "Add and upload";
"_download_file_" = "Download file";
"_loading_" = "Loading";
"_loading_with_points_" = "Loading …";
@@ -62,6 +62,7 @@
"_beta_version_" = "Beta version";
"_function_in_testing_" = "Function in testing, please send information about any problems you run into.";
"_done_" = "Done";
+"_clear_" = "Clear";
"_passcode_too_short_" = "Passcode too short, at least 4 characters required";
"_selected_" = "Selected";
"_scan_fingerprint_" = "Scan fingerprint to authenticate";
@@ -81,6 +82,7 @@
"_remove_" = "Remove";
"_file_not_found_" = "File not found";
"_continue_" = "Continue";
+"_continue_editing_" = "Continue editing";
"_continue_request_" = "Do you want to continue?";
"_auto_upload_folder_" = "Auto upload";
"_gallery_" = "Gallery";
@@ -92,7 +94,7 @@
"_initialization_" = "Initialization";
"_experimental_" = "Experimental";
"_select_dir_media_tab_" = "Select as folder \"Media\"";
-"_error_creation_file_" = "Ops! Could not create the file";
+"_error_creation_file_" = "Oops! Could not create the file";
"_save_path_" = "Save path";
"_save_settings_" = "Save settings";
"_mode_filename_" = "Filename mode";
@@ -145,6 +147,15 @@
"_view_in_folder_" = "View in folder";
"_leave_share_" = "Leave this share";
+/* MARK: Files lock */
+
+"_lock_file_" = "Lock file";
+"_unlock_file_" = "Unlock file";
+"_lock_selected_files_" = "Lock files";
+"_unlock_selected_files_" = "Unlock files";
+"_locked_by_" = "Locked by %@";
+"_file_locked_no_override_" = "This file is locked. It cannot be overridden.";
+
/* Remove a file from a list, don't delete it entirely */
"_remove_file_" = "Remove file";
@@ -204,6 +215,8 @@
"_default_color_" = "Use the default color";
"_as_default_color_" = "Use as default color";
+// MARK: User Status
+
/* User status */
"_online_" = "Online";
@@ -254,6 +267,7 @@
"_file_already_exists_" = "Unable to complete the operation, a file with the same name exists";
"_read_file_error_" = "Could not read the file";
"_write_file_error_" = "Could not write the file";
+"_files_lock_error_" = "There was an error changing the lock of this file";
"_more_" = "More";
"_notifications_" = "Notifications";
"_logout_" = "Log out";
@@ -336,10 +350,12 @@
"_user_editprofile_" = "Edit profile";
"_select_offline_warning_" = "Making multiple files and folders available offline may take a while and use a lot of memory while doing so.";
"_advanced_" = "Advanced";
+"_permissions_" = "Permissions";
"_disable_files_app_" = "Disable Files App integration";
"_disable_files_app_footer_" = "Do not permit the access of files via the iOS Files application";
"_trial_" = "Trial";
"_trial_expired_day_" = "Days remaining";
+"_time_remaining_" = "%@ remaining";
"_disableLocalCacheAfterUpload_footer_" = "After uploading the file, do not keep it in the local cache";
"_disableLocalCacheAfterUpload_" = "Disable local cache";
"_autoupload_" = "Auto upload photos/videos";
@@ -426,7 +442,7 @@
"_error_createsubfolders_upload_" = "Error creating subfolders";
"_activate_autoupload_" = "Enable auto upload";
"_remove_photo_CameraRoll_" = "Remove from camera roll";
-"_remove_photo_CameraRoll_desc_" = "After successful automatic uploads, a confirmation message will be displayed to delete the uploaded photos or videos from the camera roll. The deleted photos or videos will still be available in the iOS Photos Trash for 30 days.";
+"_remove_photo_CameraRoll_desc_" = "\"Remove from camera roll\" after uploads, a confirmation message will be displayed to delete the uploaded photos or videos from the camera roll. The deleted photos or videos will still be available in the iOS Photos Trash for 30 days.";
"_never_" = "never";
"_less_a_minute_" = "less than a minute ago";
"_a_minute_ago_" = "a minute ago";
@@ -562,9 +578,12 @@
"_insert_password_pfd_" = "Secured PDF. Enter password";
"_password_pdf_error_" = "Wrong password";
"_error_download_photobrowser_" = "Error: Unable to download photo";
+
+// MARK: Share
+
"_share_link_" = "Share link";
"_share_link_button_" = "Send link to …";
-"_Link_name_" = "Link name";
+"_share_link_name_" = "Link name";
"_password_" = "Password";
"_share_password_" = "Password protected link";
"_share_expirationdate_" = "Set expiration date for link";
@@ -609,6 +628,9 @@
"_share_unshare_" = "Unshare";
"_share_internal_link_" = "Internal link";
"_share_internal_link_des_" = "Only works for users with access to this folder";
+"_share_reshare_disabled_" = "You are not allowed to reshare this file/folder";
+"_share_reshare_restricted_" = "Note: You only have limited permission to reshare this file/folder";
+
"_no_transfer_" = "No transfers yet";
"_no_transfer_sub_" = "Uploads and downloads from this device will show up here";
"_no_activity_" = "No activity yet";
@@ -722,8 +744,8 @@
"_go_online_" = "Go online to see the document";
"_intro_1_title_" = "Keep your data secure and under your control";
"_intro_2_title_" = "Secure collaboration & file exchange";
-"_intro_3_title_" = "Easy-to-use web mail, calendering & contacts";
-"_intro_4_title_" = "Screensharing, online meetings & web conferences";
+"_intro_3_title_" = "Easy-to-use web mail, calendaring & contacts";
+"_intro_4_title_" = "Screen sharing, online meetings & web conferences";
"_log_in_" = "Log in";
"_sign_up_" = "Sign up with provider";
"_host_your_own_server" = "Host your own server";
@@ -803,7 +825,8 @@
"_overwrite_original_" = "Overwrite original";
"_save_as_copy_" = "Save as copy";
"_discard_changes_" = "Close and discard changes";
-"_message_disable_overwrite_livephoto_" = "This image it's a Live Photo, the overwrite will not possible";
+"_message_disable_overwrite_livephoto_" = "This image is a Live Photo, overwrite will not be possible";
+"_discard_changes_info_" = "Your changes will be discarded.";
"_delete_files_desc_" = "Delete files to free up space";
"_delete_old_files_" = "Delete all files older than";
"_never_" = "Never";
@@ -830,7 +853,9 @@
"_certificates_" = "Certificates";
"_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?";
// Video
+"_select_trace_" = "Select the trace";
"_video_processing_" = "Video processing";
"_video_being_processed_" = "Video being processed …";
"_downloading_" = "Downloading";
@@ -841,4 +866,26 @@
"_stay_app_foreground_" = "Keep the app in the foreground …";
"_conversion_available_" = "The conversion is always available on menu";
"_video_format_not_recognized_" = "This video needs to be processed to be played, do you want to do it now?";
+"_video_must_download_" = "This video needs to be downloaded and processed to be played, do you want to do it now?";
"_conversion_max_compatibility_" = "Max compatibility, the conversion can take much longer";
+"_video_tap_for_close_" = "A slight pressure to close the processing";
+"_subtitle_not_found_" = "Subtitle not found";
+"_disable_" = "Disable";
+"_subtitle_not_dowloaded_" = "There are subtitles not downloaded locally";
+
+// Tip
+"_tip_pdf_thumbnails_" = "Swipe left from the right edge of the screen to show the thumbnails.";
+
+// MARK: Accessibility
+
+// Accessibility, floating panel top element
+"_cart_controller_" = "Card controller";
+"_accessibility_add_upload_" = "Add and upload";
+"_dismiss_menu_" = "Dismiss the menu";
+"_show_profile_" = "Show profile";
+// a11y: On/Off
+"_on_" = "On";
+// a11y: On/Off
+"_off_" = "Off";
+"_grid_view_" = "Show grid view";
+"_list_view_" = "Show list view";
diff --git a/iOSClient/Supporting Files/eo.lproj/InfoPlist.strings b/iOSClient/Supporting Files/eo.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/eo.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/eo.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/eo.lproj/Localizable.strings b/iOSClient/Supporting Files/eo.lproj/Localizable.strings
index e752850f3..0999863cc 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/InfoPlist.strings b/iOSClient/Supporting Files/es-419.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/es-419.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/es-419.lproj/InfoPlist.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 08e4b7142..f0d8dd7af 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/InfoPlist.strings b/iOSClient/Supporting Files/es-AR.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/es-AR.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/es-AR.lproj/InfoPlist.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 4d2b401be..e9222dd44 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/InfoPlist.strings b/iOSClient/Supporting Files/es-CL.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/es-CL.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/es-CL.lproj/InfoPlist.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 1df3a142a..7a52551e5 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/InfoPlist.strings b/iOSClient/Supporting Files/es-CO.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/es-CO.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/es-CO.lproj/InfoPlist.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 1df3a142a..fd097fa4f 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/InfoPlist.strings b/iOSClient/Supporting Files/es-CR.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/es-CR.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/es-CR.lproj/InfoPlist.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 1df3a142a..1f9cfde75 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/InfoPlist.strings b/iOSClient/Supporting Files/es-DO.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/es-DO.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/es-DO.lproj/InfoPlist.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 1df3a142a..fcff56a2c 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/InfoPlist.strings b/iOSClient/Supporting Files/es-EC.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/es-EC.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/es-EC.lproj/InfoPlist.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 999010d18..6e787565a 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/InfoPlist.strings b/iOSClient/Supporting Files/es-GT.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/es-GT.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/es-GT.lproj/InfoPlist.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 1df3a142a..1f9cfde75 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/InfoPlist.strings b/iOSClient/Supporting Files/es-HN.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/es-HN.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/es-HN.lproj/InfoPlist.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 682a10fc4..34a8f1c0d 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/InfoPlist.strings b/iOSClient/Supporting Files/es-MX.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/es-MX.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/es-MX.lproj/InfoPlist.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 06042e9b1..29ff32f9d 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/InfoPlist.strings b/iOSClient/Supporting Files/es-NI.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/es-NI.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/es-NI.lproj/InfoPlist.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 682a10fc4..aa61e2455 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/InfoPlist.strings b/iOSClient/Supporting Files/es-PA.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/es-PA.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/es-PA.lproj/InfoPlist.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 682a10fc4..aa61e2455 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/InfoPlist.strings b/iOSClient/Supporting Files/es-PE.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/es-PE.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/es-PE.lproj/InfoPlist.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 682a10fc4..aa61e2455 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/InfoPlist.strings b/iOSClient/Supporting Files/es-PR.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/es-PR.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/es-PR.lproj/InfoPlist.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 682a10fc4..aa61e2455 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/InfoPlist.strings b/iOSClient/Supporting Files/es-PY.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/es-PY.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/es-PY.lproj/InfoPlist.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 69c760b42..484370411 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/InfoPlist.strings b/iOSClient/Supporting Files/es-SV.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/es-SV.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/es-SV.lproj/InfoPlist.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 1df3a142a..1f9cfde75 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/InfoPlist.strings b/iOSClient/Supporting Files/es-UY.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/es-UY.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/es-UY.lproj/InfoPlist.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 682a10fc4..ba9fc8776 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/InfoPlist.strings b/iOSClient/Supporting Files/es.lproj/InfoPlist.strings
index 7b744e241..0be5276e3 100644
--- a/iOSClient/Supporting Files/es.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/es.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/es.lproj/Localizable.strings b/iOSClient/Supporting Files/es.lproj/Localizable.strings
index d4811b624..5ba66b02e 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/InfoPlist.strings b/iOSClient/Supporting Files/et_EE.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/et_EE.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/et_EE.lproj/InfoPlist.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 39381572f..618b9fd1a 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/InfoPlist.strings b/iOSClient/Supporting Files/eu.lproj/InfoPlist.strings
index b907f6e78..6db2ffca3 100644
--- a/iOSClient/Supporting Files/eu.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/eu.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/eu.lproj/Localizable.strings b/iOSClient/Supporting Files/eu.lproj/Localizable.strings
index e5c3566c8..ed6b156bd 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/InfoPlist.strings b/iOSClient/Supporting Files/fa.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/fa.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/fa.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/fa.lproj/Localizable.strings b/iOSClient/Supporting Files/fa.lproj/Localizable.strings
index f6f6b67b9..020b7b6bc 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/InfoPlist.strings b/iOSClient/Supporting Files/fi-FI.lproj/InfoPlist.strings
index b907f6e78..17ad11ec9 100644
--- a/iOSClient/Supporting Files/fi-FI.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/fi-FI.lproj/InfoPlist.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 4f3846b4c..b0fa858c0 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/InfoPlist.strings b/iOSClient/Supporting Files/fo.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/fo.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/fo.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/fo.lproj/Localizable.strings b/iOSClient/Supporting Files/fo.lproj/Localizable.strings
index cad2830f0..aa76ef0b0 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 dabb43b5e..ad8c81d8e 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 adb4b7364..f847542a1 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/InfoPlist.strings b/iOSClient/Supporting Files/gd.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/gd.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/gd.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/gd.lproj/Localizable.strings b/iOSClient/Supporting Files/gd.lproj/Localizable.strings
index 29465f2a1..2e758e91c 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/InfoPlist.strings b/iOSClient/Supporting Files/gl.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/gl.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/gl.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/gl.lproj/Localizable.strings b/iOSClient/Supporting Files/gl.lproj/Localizable.strings
index 860cfba88..53b4ba168 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/InfoPlist.strings b/iOSClient/Supporting Files/he.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/he.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/he.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/he.lproj/Localizable.strings b/iOSClient/Supporting Files/he.lproj/Localizable.strings
index bca57ad9e..a09013332 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/InfoPlist.strings b/iOSClient/Supporting Files/hi_IN.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/hi_IN.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/hi_IN.lproj/InfoPlist.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 29465f2a1..d6feb161f 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/InfoPlist.strings b/iOSClient/Supporting Files/hr.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/hr.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/hr.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/hr.lproj/Localizable.strings b/iOSClient/Supporting Files/hr.lproj/Localizable.strings
index f9b8306b3..0e5ef62ad 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/InfoPlist.strings b/iOSClient/Supporting Files/hsb.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/hsb.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/hsb.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/hsb.lproj/Localizable.strings b/iOSClient/Supporting Files/hsb.lproj/Localizable.strings
index 1ce567a41..6f11a3e51 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/InfoPlist.strings b/iOSClient/Supporting Files/hu.lproj/InfoPlist.strings
index 1a9745288..1add04cfe 100644
--- a/iOSClient/Supporting Files/hu.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/hu.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/hu.lproj/Localizable.strings b/iOSClient/Supporting Files/hu.lproj/Localizable.strings
index b32adfb13..d78522d67 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/InfoPlist.strings b/iOSClient/Supporting Files/hy.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/hy.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/hy.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/hy.lproj/Localizable.strings b/iOSClient/Supporting Files/hy.lproj/Localizable.strings
index 688f0e548..a56cf377e 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/InfoPlist.strings b/iOSClient/Supporting Files/ia.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/ia.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/ia.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ia.lproj/Localizable.strings b/iOSClient/Supporting Files/ia.lproj/Localizable.strings
index 50a2d5f91..4447846b0 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/InfoPlist.strings b/iOSClient/Supporting Files/id.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/id.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/id.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/id.lproj/Localizable.strings b/iOSClient/Supporting Files/id.lproj/Localizable.strings
index abffe4686..2b5c81e56 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/InfoPlist.strings b/iOSClient/Supporting Files/ig.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/ig.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/ig.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ig.lproj/Localizable.strings b/iOSClient/Supporting Files/ig.lproj/Localizable.strings
index 29465f2a1..b1e6f9f2f 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/InfoPlist.strings b/iOSClient/Supporting Files/is.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/is.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/is.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/is.lproj/Localizable.strings b/iOSClient/Supporting Files/is.lproj/Localizable.strings
index 1f42be7e8..e99e2bb2d 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/InfoPlist.strings b/iOSClient/Supporting Files/it.lproj/InfoPlist.strings
index 9f957bc21..acd43ce85 100644
--- a/iOSClient/Supporting Files/it.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/it.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/it.lproj/Localizable.strings b/iOSClient/Supporting Files/it.lproj/Localizable.strings
index a35b9bf43..8e113f338 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/InfoPlist.strings b/iOSClient/Supporting Files/ja-JP.lproj/InfoPlist.strings
index b907f6e78..ebd63f78d 100644
--- a/iOSClient/Supporting Files/ja-JP.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/ja-JP.lproj/InfoPlist.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 785646f12..4c5ef5480 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/InfoPlist.strings b/iOSClient/Supporting Files/ka-GE.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/ka-GE.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/ka-GE.lproj/InfoPlist.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 8711f456d..384abecfc 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/InfoPlist.strings b/iOSClient/Supporting Files/ka.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/ka.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/ka.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ka.lproj/Localizable.strings b/iOSClient/Supporting Files/ka.lproj/Localizable.strings
index d31ff4616..800fbe66e 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/InfoPlist.strings b/iOSClient/Supporting Files/kab.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/kab.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/kab.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/kab.lproj/Localizable.strings b/iOSClient/Supporting Files/kab.lproj/Localizable.strings
index 7b125ea57..83f45f735 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/kk.lproj/InfoPlist.strings b/iOSClient/Supporting Files/kk.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/kk.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/kk.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/kk.lproj/Localizable.strings b/iOSClient/Supporting Files/kk.lproj/Localizable.strings
index 29465f2a1..d6feb161f 100644
--- a/iOSClient/Supporting Files/kk.lproj/Localizable.strings
+++ b/iOSClient/Supporting Files/kk.lproj/Localizable.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/km.lproj/InfoPlist.strings b/iOSClient/Supporting Files/km.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/km.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/km.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/km.lproj/Localizable.strings b/iOSClient/Supporting Files/km.lproj/Localizable.strings
index a48abd3c0..e2343fd71 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/InfoPlist.strings b/iOSClient/Supporting Files/kn.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/kn.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/kn.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/kn.lproj/Localizable.strings b/iOSClient/Supporting Files/kn.lproj/Localizable.strings
index a848f6d5e..105d64240 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/InfoPlist.strings b/iOSClient/Supporting Files/ko.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/ko.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/ko.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ko.lproj/Localizable.strings b/iOSClient/Supporting Files/ko.lproj/Localizable.strings
index ac7a42d2c..6c9f2609d 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/InfoPlist.strings b/iOSClient/Supporting Files/la.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/la.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/la.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/la.lproj/Localizable.strings b/iOSClient/Supporting Files/la.lproj/Localizable.strings
index 91c1683d2..2baa2f06e 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/InfoPlist.strings b/iOSClient/Supporting Files/lb.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/lb.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/lb.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/lb.lproj/Localizable.strings b/iOSClient/Supporting Files/lb.lproj/Localizable.strings
index b27bbd24b..4990dc5c8 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/InfoPlist.strings b/iOSClient/Supporting Files/lo.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/lo.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/lo.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/lo.lproj/Localizable.strings b/iOSClient/Supporting Files/lo.lproj/Localizable.strings
index 8432bea32..150df0194 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/InfoPlist.strings b/iOSClient/Supporting Files/lt_LT.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/lt_LT.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/lt_LT.lproj/InfoPlist.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 a347fc39b..cba973880 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/InfoPlist.strings b/iOSClient/Supporting Files/lv.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/lv.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/lv.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/lv.lproj/Localizable.strings b/iOSClient/Supporting Files/lv.lproj/Localizable.strings
index 3e525055c..80d3d3063 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/InfoPlist.strings b/iOSClient/Supporting Files/mk.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/mk.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/mk.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/mk.lproj/Localizable.strings b/iOSClient/Supporting Files/mk.lproj/Localizable.strings
index 6937fb8db..79abd4af6 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/InfoPlist.strings b/iOSClient/Supporting Files/mn.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/mn.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/mn.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/mn.lproj/Localizable.strings b/iOSClient/Supporting Files/mn.lproj/Localizable.strings
index b389828d7..2106f082d 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/InfoPlist.strings b/iOSClient/Supporting Files/mr.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/mr.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/mr.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/mr.lproj/Localizable.strings b/iOSClient/Supporting Files/mr.lproj/Localizable.strings
index 29465f2a1..9a4c98b34 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/InfoPlist.strings b/iOSClient/Supporting Files/ms_MY.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/ms_MY.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/ms_MY.lproj/InfoPlist.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 602303db4..a68b50a6b 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/InfoPlist.strings b/iOSClient/Supporting Files/my.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/my.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/my.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/my.lproj/Localizable.strings b/iOSClient/Supporting Files/my.lproj/Localizable.strings
index cb25a9ecc..29dec98a8 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/InfoPlist.strings b/iOSClient/Supporting Files/nb-NO.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/nb-NO.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/nb-NO.lproj/InfoPlist.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 a616388f0..95fcaa666 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/InfoPlist.strings b/iOSClient/Supporting Files/ne.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/ne.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/ne.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ne.lproj/Localizable.strings b/iOSClient/Supporting Files/ne.lproj/Localizable.strings
index 0837b531d..e882cb781 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/InfoPlist.strings b/iOSClient/Supporting Files/nl.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/nl.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/nl.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/nl.lproj/Localizable.strings b/iOSClient/Supporting Files/nl.lproj/Localizable.strings
index 6587eaffb..9b6b823d5 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/InfoPlist.strings b/iOSClient/Supporting Files/nn_NO.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/nn_NO.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/nn_NO.lproj/InfoPlist.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 e8654611a..1f04dcda5 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/InfoPlist.strings b/iOSClient/Supporting Files/oc.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/oc.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/oc.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/oc.lproj/Localizable.strings b/iOSClient/Supporting Files/oc.lproj/Localizable.strings
index ec06d8816..e04570e48 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/InfoPlist.strings b/iOSClient/Supporting Files/pl.lproj/InfoPlist.strings
index b055470d7..d630826b2 100644
--- a/iOSClient/Supporting Files/pl.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/pl.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/pl.lproj/Localizable.strings b/iOSClient/Supporting Files/pl.lproj/Localizable.strings
index 500e7296d..e1065e025 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/InfoPlist.strings b/iOSClient/Supporting Files/ps.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/ps.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/ps.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ps.lproj/Localizable.strings b/iOSClient/Supporting Files/ps.lproj/Localizable.strings
index 6ed383774..9031888a4 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/InfoPlist.strings b/iOSClient/Supporting Files/pt-BR.lproj/InfoPlist.strings
index d73155d57..b0013897e 100644
--- a/iOSClient/Supporting Files/pt-BR.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/pt-BR.lproj/InfoPlist.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 74336c384..464d3f855 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 b907f6e78..b58e1cf05 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 26c2f511d..0e826616a 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/InfoPlist.strings b/iOSClient/Supporting Files/ro.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/ro.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/ro.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ro.lproj/Localizable.strings b/iOSClient/Supporting Files/ro.lproj/Localizable.strings
index 41de44c52..fe1d77757 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 b907f6e78..b58e1cf05 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 2b40acab0..c87d9f964 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/InfoPlist.strings b/iOSClient/Supporting Files/sc.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/sc.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/sc.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/sc.lproj/Localizable.strings b/iOSClient/Supporting Files/sc.lproj/Localizable.strings
index 04f9753f0..43da9b89e 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/InfoPlist.strings b/iOSClient/Supporting Files/si.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/si.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/si.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/si.lproj/Localizable.strings b/iOSClient/Supporting Files/si.lproj/Localizable.strings
index e3ef30803..ca90225b0 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 4afaa09dc..d0a95dc1c 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 b26ecfca3..389d16f42 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 b907f6e78..b58e1cf05 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 561ab7d2f..e93456fc3 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/InfoPlist.strings b/iOSClient/Supporting Files/sq.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/sq.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/sq.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/sq.lproj/Localizable.strings b/iOSClient/Supporting Files/sq.lproj/Localizable.strings
index 4db0730ea..8e1194c04 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/InfoPlist.strings b/iOSClient/Supporting Files/sr.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/sr.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/sr.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/sr.lproj/Localizable.strings b/iOSClient/Supporting Files/sr.lproj/Localizable.strings
index ce3c29b44..63b2a1bea 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/InfoPlist.strings b/iOSClient/Supporting Files/sr@latin.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/sr@latin.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/sr@latin.lproj/InfoPlist.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 551b3d8e9..e18103b5c 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/InfoPlist.strings b/iOSClient/Supporting Files/sv.lproj/InfoPlist.strings
index 1edb2895e..94cb1cc84 100644
--- a/iOSClient/Supporting Files/sv.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/sv.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/sv.lproj/Localizable.strings b/iOSClient/Supporting Files/sv.lproj/Localizable.strings
index 2e693b521..be2b8a132 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/InfoPlist.strings b/iOSClient/Supporting Files/sw.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/sw.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/sw.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/sw.lproj/Localizable.strings b/iOSClient/Supporting Files/sw.lproj/Localizable.strings
index 29465f2a1..d6feb161f 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/InfoPlist.strings b/iOSClient/Supporting Files/ta.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/ta.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/ta.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ta.lproj/Localizable.strings b/iOSClient/Supporting Files/ta.lproj/Localizable.strings
index 77655b07c..bfb871e98 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/InfoPlist.strings b/iOSClient/Supporting Files/th_TH.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/th_TH.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/th_TH.lproj/InfoPlist.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 43b01cf13..16615f2b1 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/InfoPlist.strings b/iOSClient/Supporting Files/tk.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/tk.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/tk.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/tk.lproj/Localizable.strings b/iOSClient/Supporting Files/tk.lproj/Localizable.strings
index 5b1131787..be672326e 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/InfoPlist.strings b/iOSClient/Supporting Files/tr.lproj/InfoPlist.strings
index a4424f682..3d6e79102 100644
--- a/iOSClient/Supporting Files/tr.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/tr.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/tr.lproj/Localizable.strings b/iOSClient/Supporting Files/tr.lproj/Localizable.strings
index 9abfe1c5d..fdff9602b 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/InfoPlist.strings b/iOSClient/Supporting Files/ug.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/ug.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/ug.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/ug.lproj/Localizable.strings b/iOSClient/Supporting Files/ug.lproj/Localizable.strings
index ad7e9d073..4fd0b3de0 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/InfoPlist.strings b/iOSClient/Supporting Files/uk.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/uk.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/uk.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/uk.lproj/Localizable.strings b/iOSClient/Supporting Files/uk.lproj/Localizable.strings
index d5c5277f1..c0ecb041e 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/InfoPlist.strings b/iOSClient/Supporting Files/ur_PK.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/ur_PK.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/ur_PK.lproj/InfoPlist.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 3912758b2..2be0c7a1a 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/InfoPlist.strings b/iOSClient/Supporting Files/uz.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/uz.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/uz.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/uz.lproj/Localizable.strings b/iOSClient/Supporting Files/uz.lproj/Localizable.strings
index 6c9045dc1..6a10a5bae 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/InfoPlist.strings b/iOSClient/Supporting Files/vi.lproj/InfoPlist.strings
index b907f6e78..b58e1cf05 100644
--- a/iOSClient/Supporting Files/vi.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/vi.lproj/InfoPlist.strings
Binary files differ
diff --git a/iOSClient/Supporting Files/vi.lproj/Localizable.strings b/iOSClient/Supporting Files/vi.lproj/Localizable.strings
index 308165814..175916657 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/InfoPlist.strings b/iOSClient/Supporting Files/zh-Hans.lproj/InfoPlist.strings
index 349e58003..a732957e9 100644
--- a/iOSClient/Supporting Files/zh-Hans.lproj/InfoPlist.strings
+++ b/iOSClient/Supporting Files/zh-Hans.lproj/InfoPlist.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 a71f2177c..945bdd621 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 b907f6e78..b58e1cf05 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 859f5f7a9..ab783619a 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 95c7b93b2..946102aad 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 614e4f002..2df137685 100755
--- a/iOSClient/Transfers/NCTransferCell.swift
+++ b/iOSClient/Transfers/NCTransferCell.swift
@@ -73,6 +73,8 @@ class NCTransferCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellP
override func awakeFromNib() {
super.awakeFromNib()
+ isAccessibilityElement = true
+
imageItem.layer.cornerRadius = 6
imageItem.layer.masksToBounds = true
@@ -120,6 +122,13 @@ class NCTransferCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellP
func setButtonMore(named: String, image: UIImage) {
namedButtonMore = named
imageMore.image = image
+ self.accessibilityCustomActions = [
+ UIAccessibilityCustomAction(
+ name: NSLocalizedString("_cancel_", comment: ""),
+ target: self,
+ selector: #selector(touchUpInsideMore))
+ ]
+
}
}
diff --git a/iOSClient/Transfers/NCTransfers.swift b/iOSClient/Transfers/NCTransfers.swift
index bc5d022b0..30827eb70 100644
--- a/iOSClient/Transfers/NCTransfers.swift
+++ b/iOSClient/Transfers/NCTransfers.swift
@@ -252,6 +252,7 @@ class NCTransfers: NCCollectionViewCommon, NCTransferCellDelegate {
cell.labelInfo.text = ""
break
}
+ cell.accessibilityLabel = metadata.fileNameView + ", " + (cell.labelInfo.text ?? "")
// Remove last separator
if collectionView.numberOfItems(inSection: indexPath.section) == indexPath.row + 1 {
diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift
index 5c953a6b8..28b2fa8b6 100644
--- a/iOSClient/Trash/Cell/NCTrashListCell.swift
+++ b/iOSClient/Trash/Cell/NCTrashListCell.swift
@@ -50,6 +50,20 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCell {
override func awakeFromNib() {
super.awakeFromNib()
+ isAccessibilityElement = true
+
+ self.accessibilityCustomActions = [
+ UIAccessibilityCustomAction(
+ name: NSLocalizedString("_restore_", comment: ""),
+ target: self,
+ selector: #selector(touchUpInsideRestore)),
+ UIAccessibilityCustomAction(
+ name: NSLocalizedString("_delete_", comment: ""),
+ target: self,
+ selector: #selector(touchUpInsideMore))
+
+ ]
+
imageRestore.image = NCBrandColor.cacheImages.buttonRestore
imageMore.image = NCUtility.shared.loadImage(named: "trash")
@@ -119,18 +133,21 @@ protocol NCTrashCell {
func selectMode(_ status: Bool)
func selected(_ status: Bool)
}
-extension NCTrashCell {
+
+extension NCTrashCell 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 tableTrash.directory {
self.imageItem.image = NCBrandColor.cacheImages.folder
- self.labelInfo?.text = CCUtility.dateDiff(tableTrash.date as Date)
+ infoText = CCUtility.dateDiff(tableTrash.date as Date)
} else {
self.imageItem.image = image
- self.labelInfo?.text = CCUtility.dateDiff(tableTrash.date as Date) + ", " + CCUtility.transformedSize(tableTrash.size)
+ infoText = CCUtility.dateDiff(tableTrash.date as Date) + ", " + CCUtility.transformedSize(tableTrash.size)
}
+ self.labelInfo?.text = infoText
+ self.accessibilityLabel = tableTrash.trashbinFileName + ", " + infoText
}
}
diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift
index 66c4fde96..8261bfc9b 100644
--- a/iOSClient/Trash/NCTrash+CollectionView.swift
+++ b/iOSClient/Trash/NCTrash+CollectionView.swift
@@ -62,8 +62,10 @@ extension NCTrash: UICollectionViewDataSource {
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
diff --git a/iOSClient/Utility/CCUtility.h b/iOSClient/Utility/CCUtility.h
index e2aee0e86..2d50ba80d 100644
--- a/iOSClient/Utility/CCUtility.h
+++ b/iOSClient/Utility/CCUtility.h
@@ -180,12 +180,12 @@
+ (NSInteger)getCleanUpDay;
+ (void)setCleanUpDay:(NSInteger)days;
-+ (PDFDisplayDirection)getPDFDisplayDirection;
-+ (void)setPDFDisplayDirection:(PDFDisplayDirection)direction;
-
+ (BOOL)getPrivacyScreenEnabled;
+ (void)setPrivacyScreenEnabled:(BOOL)set;
++ (BOOL)getRemovePhotoCameraRoll;
++ (void)setRemovePhotoCameraRoll:(BOOL)set;
+
// ===== Varius =====
+ (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL;
@@ -243,7 +243,7 @@
+ (NSString *)getMimeType:(NSString *)fileNameView;
-+ (void)extractImageVideoFromAssetLocalIdentifierForUpload:(tableMetadata *)metadataForUpload notification:(BOOL)notification completion:(void(^)(tableMetadata *newMetadata, NSString* fileNamePath))completion;
++ (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 =====
diff --git a/iOSClient/Utility/CCUtility.m b/iOSClient/Utility/CCUtility.m
index 0013c4b68..edc4b55b7 100644
--- a/iOSClient/Utility/CCUtility.m
+++ b/iOSClient/Utility/CCUtility.m
@@ -715,23 +715,6 @@
[UICKeyChainStore setString:daysString forKey:@"cleanUpDay" service:NCGlobal.shared.serviceShareKeyChain];
}
-+ (PDFDisplayDirection)getPDFDisplayDirection
-{
- NSString *direction = [UICKeyChainStore stringForKey:@"PDFDisplayDirection" service:NCGlobal.shared.serviceShareKeyChain];
-
- if (direction == nil) {
- return kPDFDisplayDirectionVertical;
- } else {
- return [direction integerValue];
- }
-}
-
-+ (void)setPDFDisplayDirection:(PDFDisplayDirection)direction
-{
- NSString *directionString = [@(direction) stringValue];
- [UICKeyChainStore setString:directionString forKey:@"PDFDisplayDirection" service:NCGlobal.shared.serviceShareKeyChain];
-}
-
+ (BOOL)getPrivacyScreenEnabled
{
NSString *valueString = [UICKeyChainStore stringForKey:@"privacyScreen" service:NCGlobal.shared.serviceShareKeyChain];
@@ -751,6 +734,17 @@
[UICKeyChainStore setString:sSet forKey:@"privacyScreen" service:NCGlobal.shared.serviceShareKeyChain];
}
++ (BOOL)getRemovePhotoCameraRoll
+{
+ return [[UICKeyChainStore stringForKey:@"removePhotoCameraRoll" service:NCGlobal.shared.serviceShareKeyChain] boolValue];
+}
+
++ (void)setRemovePhotoCameraRoll:(BOOL)set
+{
+ NSString *sSet = (set) ? @"true" : @"false";
+ [UICKeyChainStore setString:sSet forKey:@"removePhotoCameraRoll" service:NCGlobal.shared.serviceShareKeyChain];
+}
+
#pragma --------------------------------------------------------------------------------------------
#pragma mark ===== Various =====
#pragma --------------------------------------------------------------------------------------------
@@ -1350,7 +1344,7 @@
return path;
}
-+ (void)extractImageVideoFromAssetLocalIdentifierForUpload:(tableMetadata *)metadataForUpload notification:(BOOL)notification completion:(void(^)(tableMetadata *metadata, NSString* fileNamePath))completion
++ (void)extractImageVideoFromAssetLocalIdentifierForUpload:(tableMetadata *)metadataForUpload completion:(void(^)(tableMetadata *metadata, NSString* fileNamePath))completion
{
if (metadataForUpload == nil) {
return completion(nil, nil);
@@ -1360,10 +1354,6 @@
PHFetchResult *result = [PHAsset fetchAssetsWithLocalIdentifiers:@[metadata.assetLocalIdentifier] options:nil];
if (!result.count) {
- if (notification) {
- [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:NCGlobal.shared.notificationCenterUploadedFile object:nil userInfo:@{@"ocId": metadata.ocId, @"errorCode": @(NCGlobal.shared.errorInternalError), @"errorDescription": @"_err_file_not_found_"}];
- }
-
return completion(nil, nil);
}
@@ -1385,21 +1375,24 @@
NSLog(@"cacheAsset: %f", progress);
if (error) {
- if (notification) {
- [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:NCGlobal.shared.notificationCenterUploadedFile object:nil userInfo:@{@"ocId": metadata.ocId, @"errorCode": @(error.code), @"errorDescription": [NSString stringWithFormat:@"Image request iCloud failed [%@]", error.description]}];
- }
-
+ [[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 *extensionAsset = [[[asset valueForKey:@"filename"] pathExtension] uppercaseString];
NSString *fileName = metadata.fileNameView;
- if ([extensionAsset isEqualToString:@"HEIC"] && [CCUtility getFormatCompatibility]) {
+ if (([extensionAsset isEqualToString:@"HEIC"] || [extensionAsset isEqualToString:@"DNG"]) && [CCUtility getFormatCompatibility]) {
CIImage *ciImage = [CIImage imageWithData:imageData];
CIContext *context = [CIContext context];
@@ -1444,10 +1437,7 @@
NSLog(@"cacheAsset: %f", progress);
if (error) {
- if (notification) {
- [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:NCGlobal.shared.notificationCenterUploadedFile object:nil userInfo:@{@"ocId": metadata.ocId, @"errorCode": @(error.code), @"errorDescription": [NSString stringWithFormat:@"Video request iCloud failed [%@]", error.description]}];
- }
-
+ [[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);
}
};
@@ -1468,19 +1458,12 @@
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
-
- if (notification) {
- [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:NCGlobal.shared.notificationCenterUploadedFile object:nil userInfo:@{@"ocId": metadata.ocId, @"errorCode": @(error.code), @"errorDescription": [NSString stringWithFormat:@"Video request iCloud failed [%@]", error.description]}];
- }
-
+ [[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);
}
});
@@ -1728,6 +1711,7 @@
stringLatitude = [NSString stringWithFormat:@"+%.4f", latitude];
} else {
stringLatitude = [NSString stringWithFormat:@"-%.4f", latitude];
+ latitude *= -1;
}
// conversion 4 decimal +E -W
@@ -1737,10 +1721,10 @@
stringLongitude = [NSString stringWithFormat:@"+%.4f", longitude];
} else {
stringLongitude = [NSString stringWithFormat:@"-%.4f", longitude];
+ longitude *= -1;
}
if (latitude == 0 || longitude == 0) {
-
stringLatitude = @"0";
stringLongitude = @"0";
}
diff --git a/iOSClient/Utility/NCAskAuthorization.swift b/iOSClient/Utility/NCAskAuthorization.swift
index 28ce6e902..1d02f9d1e 100644
--- a/iOSClient/Utility/NCAskAuthorization.swift
+++ b/iOSClient/Utility/NCAskAuthorization.swift
@@ -29,6 +29,8 @@ class NCAskAuthorization: NSObject {
return instance
}()
+ private(set) var isRequesting = false
+
func askAuthorizationAudioRecord(viewController: UIViewController?, completion: @escaping (_ hasPermission: Bool) -> Void) {
switch AVAudioSession.sharedInstance().recordPermission {
@@ -65,7 +67,7 @@ class NCAskAuthorization: NSObject {
}
}
- func askAuthorizationPhotoLibrary(viewController: UIViewController?, completion: @escaping (_ hasPermission: Bool) -> Void) {
+ @objc func askAuthorizationPhotoLibrary(viewController: UIViewController?, completion: @escaping (_ hasPermission: Bool) -> Void) {
switch PHPhotoLibrary.authorizationStatus() {
case PHAuthorizationStatus.authorized:
@@ -85,7 +87,12 @@ class NCAskAuthorization: NSObject {
}
break
case PHAuthorizationStatus.notDetermined:
+ isRequesting = true
PHPhotoLibrary.requestAuthorization { allowed in
+ self.isRequesting = false
+ DispatchQueue.main.async {
+ (UIApplication.shared.delegate as? AppDelegate)?.hidePrivacyProtectionWindow()
+ }
DispatchQueue.main.async {
if allowed == PHAuthorizationStatus.authorized {
completion(true)
@@ -100,33 +107,4 @@ class NCAskAuthorization: NSObject {
break
}
}
-
- @objc func askAuthorizationLocationManager(completion: @escaping (_ hasFullPermissions: Bool) -> Void) {
-
- switch CLLocationManager.authorizationStatus() {
- case CLAuthorizationStatus.authorizedAlways:
- completion(true)
- break
- /*
- case CLAuthorizationStatus.authorizedWhenInUse, CLAuthorizationStatus.denied, CLAuthorizationStatus.restricted:
- DispatchQueue.main.async {
- NCAutoUpload.shared.startSignificantChangeUpdates()
- }
- completion(false)
- break
- case CLAuthorizationStatus.notDetermined:
- DispatchQueue.main.async {
- NCAutoUpload.shared.startSignificantChangeUpdates()
- }
- completion(false)
- break
- */
- default:
- DispatchQueue.main.async {
- NCAutoUpload.shared.startSignificantChangeUpdates()
- }
- completion(false)
- break
- }
- }
}
diff --git a/iOSClient/Utility/NCUserBaseUrl.swift b/iOSClient/Utility/NCUserBaseUrl.swift
index c8eee917b..8bb5e6576 100644
--- a/iOSClient/Utility/NCUserBaseUrl.swift
+++ b/iOSClient/Utility/NCUserBaseUrl.swift
@@ -26,6 +26,7 @@ import Foundation
@objc public protocol NCUserBaseUrl {
var user: String { get }
var urlBase: String { get }
+ var account: String { get }
}
public extension NCUserBaseUrl {
diff --git a/iOSClient/Utility/NCUtility+Image.swift b/iOSClient/Utility/NCUtility+Image.swift
new file mode 100644
index 000000000..a56f96e91
--- /dev/null
+++ b/iOSClient/Utility/NCUtility+Image.swift
@@ -0,0 +1,91 @@
+//
+// NCUtility+Image.swift
+// Nextcloud
+//
+// Created by Henrik Storch on 17.03.22.
+// Copyright © 2022 Henrik Storch. All rights reserved.
+//
+// Author Henrik Storch <henrik.storch@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 SVGKit
+import NCCommunication
+
+extension NCUtility {
+ func getImageMetadata(_ metadata: tableMetadata, for size: CGFloat) -> UIImage? {
+
+ if let image = getImage(metadata: metadata) {
+ return image
+ }
+
+ if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue && !metadata.hasPreview {
+ NCUtility.shared.createImageFrom(fileName: metadata.fileNameView, ocId: metadata.ocId, etag: metadata.etag, classFile: metadata.classFile)
+ }
+
+ if CCUtility.fileProviderStoragePreviewIconExists(metadata.ocId, etag: metadata.etag) {
+ if let imagePreviewPath = CCUtility.getDirectoryProviderStoragePreviewOcId(metadata.ocId, etag: metadata.etag) {
+ return UIImage(contentsOfFile: imagePreviewPath)
+ }
+ }
+
+ if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue {
+ return UIImage(named: "noPreviewVideo")?.image(color: .gray, size: size)
+ } else if metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
+ return UIImage(named: "noPreviewAudio")?.image(color: .gray, size: size)
+ } else {
+ return UIImage(named: "noPreview")?.image(color: .gray, size: size)
+ }
+ }
+
+ func getImage(metadata: tableMetadata) -> UIImage? {
+ let ext = CCUtility.getExtension(metadata.fileNameView)
+ var image: UIImage?
+
+ if CCUtility.fileProviderStorageExists(metadata) && metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue {
+
+ let previewPath = CCUtility.getDirectoryProviderStoragePreviewOcId(metadata.ocId, etag: metadata.etag)!
+ let imagePath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
+
+ if ext == "GIF" {
+ if !FileManager().fileExists(atPath: previewPath) {
+ NCUtility.shared.createImageFrom(fileName: metadata.fileNameView, ocId: metadata.ocId, etag: metadata.etag, classFile: metadata.classFile)
+ }
+ image = UIImage.animatedImage(withAnimatedGIFURL: URL(fileURLWithPath: imagePath))
+ } else if ext == "SVG" {
+ if let svgImage = SVGKImage(contentsOfFile: imagePath) {
+ svgImage.size = CGSize(width: NCGlobal.shared.sizePreview, height: NCGlobal.shared.sizePreview)
+ if let image = svgImage.uiImage {
+ if !FileManager().fileExists(atPath: previewPath) {
+ do {
+ try image.pngData()?.write(to: URL(fileURLWithPath: previewPath), options: .atomic)
+ } catch { }
+ }
+ return image
+ } else {
+ return nil
+ }
+ } else {
+ return nil
+ }
+ } else {
+ NCUtility.shared.createImageFrom(fileName: metadata.fileNameView, ocId: metadata.ocId, etag: metadata.etag, classFile: metadata.classFile)
+ image = UIImage(contentsOfFile: imagePath)
+ }
+ }
+ return image
+ }
+}
diff --git a/iOSClient/Utility/NCUtility.swift b/iOSClient/Utility/NCUtility.swift
index a29f0cdea..191615981 100644
--- a/iOSClient/Utility/NCUtility.swift
+++ b/iOSClient/Utility/NCUtility.swift
@@ -305,6 +305,19 @@ class NCUtility: NSObject {
return true
}
+ @objc func getCustomUserAgentNCText() -> String {
+ let userAgent: String = CCUtility.getUserAgent()
+ if UIDevice.current.userInterfaceIdiom == .phone {
+ // NOTE: Hardcoded (May 2022)
+ // Tested for iPhone SE (1st), iOS 12; iPhone Pro Max, iOS 15.4
+ // 605.1.15 = WebKit build version
+ // 15E148 = frozen iOS build number according to: https://chromestatus.com/feature/4558585463832576
+ return userAgent + " " + "AppleWebKit/605.1.15 Mobile/15E148"
+ } else {
+ return userAgent
+ }
+ }
+
@objc func getCustomUserAgentOnlyOffice() -> String {
let appVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString")!
@@ -353,7 +366,7 @@ class NCUtility: NSObject {
var messageUserDefined: String = ""
if userStatus?.lowercased() == "online" {
- onlineStatus = UIImage(named: "userStatusOnline")!.image(color: UIColor(red: 103.0/255.0, green: 176.0/255.0, blue: 134.0/255.0, alpha: 1.0), size: 50)
+ onlineStatus = UIImage(named: "circle_fill")!.image(color: UIColor(red: 103.0/255.0, green: 176.0/255.0, blue: 134.0/255.0, alpha: 1.0), size: 50)
messageUserDefined = NSLocalizedString("_online_", comment: "")
}
if userStatus?.lowercased() == "away" {
@@ -474,25 +487,27 @@ class NCUtility: NSObject {
return ""
}
- func loadImage(named: String, color: UIColor = NCBrandColor.shared.gray, size: CGFloat = 50, symbolConfiguration: Any? = nil) -> UIImage {
+ func loadImage(named imageName: String, color: UIColor = NCBrandColor.shared.gray, size: CGFloat = 50, symbolConfiguration: Any? = nil) -> UIImage {
var image: UIImage?
if #available(iOS 13.0, *) {
+ // see https://stackoverflow.com/questions/71764255
+ let sfSymbolName = imageName.replacingOccurrences(of: "_", with: ".")
if let symbolConfiguration = symbolConfiguration {
- image = UIImage(systemName: named, withConfiguration: symbolConfiguration as? UIImage.Configuration)?.imageColor(color)
+ image = UIImage(systemName: sfSymbolName, withConfiguration: symbolConfiguration as? UIImage.Configuration)?.imageColor(color)
} else {
- image = UIImage(systemName: named)?.imageColor(color)
+ image = UIImage(systemName: sfSymbolName)?.imageColor(color)
}
if image == nil {
- image = UIImage(named: named)?.image(color: color, size: size)
+ image = UIImage(named: imageName)?.image(color: color, size: size)
}
} else {
- image = UIImage(named: named)?.image(color: color, size: size)
+ image = UIImage(named: imageName)?.image(color: color, size: size)
}
- if image != nil {
- return image!
+ if let image = image {
+ return image
}
return UIImage(named: "file")!.image(color: color, size: size)
@@ -799,6 +814,81 @@ class NCUtility: NSObject {
}
}
}
+
+ func getEncondingDataType(data: Data) -> String.Encoding? {
+ if let _ = String(data: data, encoding: .utf8) {
+ return .utf8
+ }
+ if let _ = String(data: data, encoding: .ascii) {
+ return .ascii
+ }
+ if let _ = String(data: data, encoding: .isoLatin1) {
+ return .isoLatin1
+ }
+ if let _ = String(data: data, encoding: .isoLatin2) {
+ return .isoLatin2
+ }
+ if let _ = String(data: data, encoding: .windowsCP1250) {
+ return .windowsCP1250
+ }
+ if let _ = String(data: data, encoding: .windowsCP1251) {
+ return .windowsCP1251
+ }
+ if let _ = String(data: data, encoding: .windowsCP1252) {
+ return .windowsCP1252
+ }
+ if let _ = String(data: data, encoding: .windowsCP1253) {
+ return .windowsCP1253
+ }
+ if let _ = String(data: data, encoding: .windowsCP1254) {
+ return .windowsCP1254
+ }
+ if let _ = String(data: data, encoding: .macOSRoman) {
+ return .macOSRoman
+ }
+ if let _ = String(data: data, encoding: .japaneseEUC) {
+ return .japaneseEUC
+ }
+ if let _ = String(data: data, encoding: .nextstep) {
+ return .nextstep
+ }
+ if let _ = String(data: data, encoding: .nonLossyASCII) {
+ return .nonLossyASCII
+ }
+ if let _ = String(data: data, encoding: .shiftJIS) {
+ return .shiftJIS
+ }
+ if let _ = String(data: data, encoding: .symbol) {
+ return .symbol
+ }
+ if let _ = String(data: data, encoding: .unicode) {
+ return .unicode
+ }
+ if let _ = String(data: data, encoding: .utf16) {
+ return .utf16
+ }
+ if let _ = String(data: data, encoding: .utf16BigEndian) {
+ return .utf16BigEndian
+ }
+ if let _ = String(data: data, encoding: .utf16LittleEndian) {
+ return .utf16LittleEndian
+ }
+ if let _ = String(data: data, encoding: .utf32) {
+ return .utf32
+ }
+ if let _ = String(data: data, encoding: .utf32BigEndian) {
+ return .utf32BigEndian
+ }
+ if let _ = String(data: data, encoding: .utf32LittleEndian) {
+ return .utf32LittleEndian
+ }
+ return nil
+ }
+
+ func SYSTEM_VERSION_LESS_THAN(version: String) -> Bool {
+ return UIDevice.current.systemVersion.compare(version,
+ options: NSString.CompareOptions.numeric) == ComparisonResult.orderedAscending
+ }
}
// MARK: -
diff --git a/iOSClient/Utility/NCUtilityFileSystem.swift b/iOSClient/Utility/NCUtilityFileSystem.swift
index e64148a37..94ad7ff48 100644
--- a/iOSClient/Utility/NCUtilityFileSystem.swift
+++ b/iOSClient/Utility/NCUtilityFileSystem.swift
@@ -32,20 +32,6 @@ class NCUtilityFileSystem: NSObject {
let fileManager = FileManager.default
- @objc func getFileSize(asset: PHAsset) -> Int64 {
-
- let resources = PHAssetResource.assetResources(for: asset)
-
- if let resource = resources.first {
- if resource.responds(to: #selector(NSDictionary.fileSize)) {
- let unsignedInt64 = resource.value(forKey: "fileSize") as! CLong
- return Int64(bitPattern: UInt64(unsignedInt64))
- }
- }
-
- return 0
- }
-
@objc func getFileSize(filePath: String) -> Int64 {
do {
diff --git a/iOSClient/Viewer/NCViewer.swift b/iOSClient/Viewer/NCViewer.swift
index e34784f38..1e36d2490 100644
--- a/iOSClient/Viewer/NCViewer.swift
+++ b/iOSClient/Viewer/NCViewer.swift
@@ -152,6 +152,8 @@ class NCViewer: NSObject {
if editor == NCGlobal.shared.editorOnlyoffice {
customUserAgent = NCUtility.shared.getCustomUserAgentOnlyOffice()
+ } else {
+ customUserAgent = NCUtility.shared.getCustomUserAgentNCText()
}
NCUtility.shared.startActivityIndicator(backgroundView: viewController.view, blurEffect: true)
@@ -208,11 +210,8 @@ class NCViewer: NSObject {
CCUtility.copyFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView), toPath: fileNamePath)
- let viewerQuickLook = NCViewerQuickLook(with: URL(fileURLWithPath: fileNamePath), editingMode: false, metadata: metadata)
- let navigationController = UINavigationController(rootViewController: viewerQuickLook)
- navigationController.modalPresentationStyle = .overFullScreen
-
- viewController.present(navigationController, animated: true)
+ let viewerQuickLook = NCViewerQuickLook(with: URL(fileURLWithPath: fileNamePath), isEditingEnabled: false, metadata: metadata)
+ viewController.present(viewerQuickLook, animated: true)
}
}
diff --git a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCKTVHTTPCache.swift b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCKTVHTTPCache.swift
index 067bf0946..27ca0708e 100644
--- a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCKTVHTTPCache.swift
+++ b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCKTVHTTPCache.swift
@@ -31,17 +31,17 @@ class NCKTVHTTPCache: NSObject {
return instance
}()
- func getVideoURL(metadata: tableMetadata) -> URL? {
+ func getVideoURL(metadata: tableMetadata) -> (url: URL?, isProxy: Bool) {
if CCUtility.fileProviderStorageExists(metadata) {
- return URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView))
+ return (URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)), false)
} else {
- guard let stringURL = (metadata.serverUrl + "/" + metadata.fileName).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { return nil }
+ guard let stringURL = (metadata.serverUrl + "/" + metadata.fileName).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { return (nil, false) }
- return NCKTVHTTPCache.shared.getProxyURL(stringURL: stringURL)
+ return (NCKTVHTTPCache.shared.getProxyURL(stringURL: stringURL), true)
}
}
@@ -92,6 +92,11 @@ class NCKTVHTTPCache: NSObject {
KTVHTTPCache.cacheDelete(with: videoURL)
}
+ @objc func deleteAllCache() {
+
+ KTVHTTPCache.cacheDeleteAllCaches()
+ }
+
func saveCache(metadata: tableMetadata) {
if !CCUtility.fileProviderStorageExists(metadata) {
@@ -109,6 +114,13 @@ class NCKTVHTTPCache: NSObject {
}
}
+ func getDownloadStatusCode(metadata: tableMetadata) -> Int {
+
+ guard let stringURL = (metadata.serverUrl + "/" + metadata.fileName).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { return 0 }
+ let url = URL(string: stringURL)
+ return KTVHTTPCache.downloadStatusCode(url)
+ }
+
private func setupHTTPCache() {
KTVHTTPCache.cacheSetMaxCacheLength(NCGlobal.shared.maxHTTPCache)
diff --git a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift
index 9c796b421..60032e9ec 100644
--- a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift
+++ b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift
@@ -26,29 +26,42 @@ import NCCommunication
import UIKit
import AVFoundation
import MediaPlayer
+import JGProgressHUD
+import Alamofire
class NCPlayer: NSObject {
-
+
internal let appDelegate = UIApplication.shared.delegate as! AppDelegate
internal var url: URL
- internal var playerToolBar: NCPlayerToolBar?
- internal var viewController: UIViewController
-
- private var imageVideoContainer: imageVideoContainerView
- private var detailView: NCViewerMediaDetailView?
+ internal weak var playerToolBar: NCPlayerToolBar?
+ internal weak var viewController: UIViewController?
+ internal var autoPlay: Bool
+ internal var isProxy: Bool
+ internal var isStartPlayer: Bool
+ internal var isStartObserver: Bool
+ internal var subtitleUrls: [URL] = []
+ internal var currentSubtitle: URL?
+
+ private weak var imageVideoContainer: imageVideoContainerView?
+ private weak var detailView: NCViewerMediaDetailView?
private var observerAVPlayerItemDidPlayToEndTime: Any?
private var observerAVPlayertTime: Any?
- public var player: AVPlayer?
- public var durationTime: CMTime = .zero
- public var metadata: tableMetadata
- public var videoLayer: AVPlayerLayer?
+ var kvoPlayerObserver: NSKeyValueObservation?
+ var player: AVPlayer?
+ var durationTime: CMTime = .zero
+ var metadata: tableMetadata
+ var videoLayer: AVPlayerLayer?
// MARK: - View Life Cycle
- init(url: URL, autoPlay: Bool, imageVideoContainer: imageVideoContainerView, playerToolBar: NCPlayerToolBar?, metadata: tableMetadata, detailView: NCViewerMediaDetailView?, viewController: UIViewController) {
-
+ init(url: URL, autoPlay: Bool, isProxy: Bool, imageVideoContainer: imageVideoContainerView, playerToolBar: NCPlayerToolBar?, metadata: tableMetadata, detailView: NCViewerMediaDetailView?, viewController: UIViewController) {
+
self.url = url
+ self.autoPlay = autoPlay
+ self.isProxy = isProxy
+ self.isStartPlayer = false
+ self.isStartObserver = false
self.imageVideoContainer = imageVideoContainer
self.playerToolBar = playerToolBar
self.metadata = metadata
@@ -56,7 +69,7 @@ class NCPlayer: NSObject {
self.viewController = viewController
super.init()
-
+
do {
try AVAudioSession.sharedInstance().setCategory(.playback)
try AVAudioSession.sharedInstance().overrideOutputAudioPort(AVAudioSession.PortOverride.none)
@@ -64,51 +77,48 @@ class NCPlayer: NSObject {
} catch {
print(error)
}
-
- #if MFFFLIB
+ }
+
+ deinit {
+
+ print("deinit NCPlayer with ocId \(metadata.ocId)")
+ deactivateObserver()
+ }
+
+ func openAVPlayer() {
+
+#if MFFFLIB
+ MFFF.shared.setDelegate = self
+ MFFF.shared.dismissMessage()
+ NotificationCenter.default.addObserver(self, selector: #selector(convertVideoDidFinish(_:)), name: NSNotification.Name(rawValue: self.metadata.ocId), object: nil)
+
if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: NCGlobal.shared.fileNameVideoEncoded) {
self.url = URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: NCGlobal.shared.fileNameVideoEncoded))
+ self.isProxy = false
}
if MFFF.shared.existsMFFFSession(url: URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView))) {
return
- } else {
- MFFF.shared.dismissMessage()
}
- #endif
-
- openAVPlayer() { status, error in
-
- switch status {
- case .loaded:
- if autoPlay {
- self.player?.play()
- }
- break
- case .failed:
- #if MFFFLIB
- self.convertVideo(error: error)
- #else
- if let title = error?.localizedDescription, let description = error?.localizedFailureReason {
- NCContentPresenter.shared.messageNotification(title, description: description, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorGeneric, priority: .max)
- } else {
- NCContentPresenter.shared.messageNotification("_error_", description: "_error_something_wrong_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorGeneric, priority: .max)
- }
- #endif
- break
- case .cancelled:
- break
- default:
- break
+#endif
+
+ // Check already started
+ if isStartPlayer {
+ if !isStartObserver {
+ print("Play already started - URL: \(self.url)")
+ activateObserver()
+ playerToolBar?.show()
}
+ return
}
- }
-
- internal func openAVPlayer(completion: @escaping (_ status: AVKeyValueStatus, _ error: NSError?)->()) {
-
+
print("Play URL: \(self.url)")
player = AVPlayer(url: self.url)
+ playerToolBar?.show()
playerToolBar?.setMetadata(self.metadata)
-
+#if MFFFLIB
+ setUpForSubtitle()
+#endif
+
if metadata.livePhoto {
player?.isMuted = false
} else if metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
@@ -120,70 +130,133 @@ class NCPlayer: NSObject {
}
}
+ let observerAVPlayertStatus = self.player?.currentItem?.observe(\.status, options: [.new,.initial]) { player, change in
+
+ if let player = self.player,
+ let playerItem = player.currentItem,
+ let object = player.currentItem,
+ playerItem === object {
+
+ if self.isStartPlayer {
+ return
+ }
+ if (playerItem.status == .readyToPlay || playerItem.status == .failed) {
+ print("Player ready")
+ self.startPlayer()
+ } else {
+ print("Player not ready")
+ }
+ }
+ }
+
+ if let observerAVPlayertStatus = observerAVPlayertStatus{
+ kvoPlayerObserver = observerAVPlayertStatus
+ }
+ }
+
+ func startPlayer() {
+
player?.currentItem?.asset.loadValuesAsynchronously(forKeys: ["playable"], completionHandler: {
-
+
var error: NSError? = nil
let status = self.player?.currentItem?.asset.statusOfValue(forKey: "playable", error: &error) ?? .unknown
-
+
DispatchQueue.main.async {
- if status == .loaded {
+
+ switch status {
+ case .loaded:
+
self.durationTime = self.player?.currentItem?.asset.duration ?? .zero
NCManageDatabase.shared.addVideoTime(metadata: self.metadata, time: nil, durationTime: self.durationTime)
- self.activateObserver(playerToolBar: self.playerToolBar)
-
self.videoLayer = AVPlayerLayer(player: self.player)
- self.videoLayer!.frame = self.imageVideoContainer.bounds
+ self.videoLayer!.frame = self.imageVideoContainer?.bounds ?? .zero
self.videoLayer!.videoGravity = .resizeAspect
-
+
if self.metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue {
-
- self.imageVideoContainer.layer.addSublayer(self.videoLayer!)
- self.imageVideoContainer.playerLayer = self.videoLayer
- self.imageVideoContainer.metadata = self.metadata
- self.imageVideoContainer.image = self.imageVideoContainer.image?.image(alpha: 0)
+ self.imageVideoContainer?.layer.addSublayer(self.videoLayer!)
+ self.imageVideoContainer?.playerLayer = self.videoLayer
+ self.imageVideoContainer?.metadata = self.metadata
+ self.imageVideoContainer?.image = self.imageVideoContainer?.image?.image(alpha: 0)
}
-
+
self.playerToolBar?.setBarPlayer(ncplayer: self)
self.generatorImagePreview()
if !(self.detailView?.isShow() ?? false) {
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterShowPlayerToolBar, userInfo: ["ocId":self.metadata.ocId, "enableTimerAutoHide": false])
}
+ self.activateObserver()
+ if self.autoPlay {
+ self.player?.play()
+ }
+ self.isStartPlayer = true
+ break
+
+ case .failed:
+
+ self.playerToolBar?.hide()
+ if self.isProxy && NCKTVHTTPCache.shared.getDownloadStatusCode(metadata: self.metadata) == 200 {
+ let alertController = UIAlertController(title: NSLocalizedString("_error_", value: "Error", comment: ""), message: NSLocalizedString("_video_not_streamed_", comment: ""), preferredStyle: .alert)
+ alertController.addAction(UIAlertAction(title: NSLocalizedString("_yes_", value: "Yes", comment: ""), style: .default, handler: { _ in
+ self.downloadVideo()
+ }))
+ alertController.addAction(UIAlertAction(title: NSLocalizedString("_no_", value: "No", comment: ""), style: .default, handler: { _ in }))
+ self.viewController?.present(alertController, animated: true)
+ } else {
+#if MFFFLIB
+ if error?.code == AVError.Code.fileFormatNotRecognized.rawValue {
+ self.convertVideo(withAlert: true)
+ break
+ }
+#endif
+ if let title = error?.localizedDescription, let description = error?.localizedFailureReason {
+ NCContentPresenter.shared.messageNotification(title, description: description, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorGeneric, priority: .max)
+ } else {
+ NCContentPresenter.shared.messageNotification("_error_", description: "_error_something_wrong_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: NCGlobal.shared.errorGeneric, priority: .max)
+ }
+ }
+ break
+
+ case .cancelled:
+ break
+
+ default:
+ break
}
-
- completion(status, error)
}
})
}
- deinit {
- print("deinit NCPlayer")
-
- deactivateObserver()
- }
+ func activateObserver() {
+ print("activating Observer ocId \(metadata.ocId)")
- func activateObserver(playerToolBar: NCPlayerToolBar?) {
+ observerAVPlayerItemDidPlayToEndTime = NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: player?.currentItem, queue: .main) { [weak self] notification in
- self.playerToolBar = playerToolBar
+ guard let self = self else {
+ return
+ }
- // At end go back to start & show toolbar
- observerAVPlayerItemDidPlayToEndTime = NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: player?.currentItem, queue: .main) { notification in
if let item = notification.object as? AVPlayerItem, let currentItem = self.player?.currentItem, item == currentItem {
-
+
NCKTVHTTPCache.shared.saveCache(metadata: self.metadata)
-
+
self.videoSeek(time: .zero)
-
+
if !(self.detailView?.isShow() ?? false) {
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterShowPlayerToolBar, userInfo: ["ocId": self.metadata.ocId, "enableTimerAutoHide": false])
}
-
+
self.playerToolBar?.updateToolBar()
}
}
// Evey 1 second update toolbar
- observerAVPlayertTime = player?.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, preferredTimescale: 1), queue: .main, using: { _ in
+ observerAVPlayertTime = player?.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, preferredTimescale: 1), queue: .main, using: { [weak self] _ in
+
+ guard let self = self else {
+ return
+ }
+
if self.player?.currentItem?.status == .readyToPlay {
self.playerToolBar?.updateToolBar()
}
@@ -192,41 +265,55 @@ class NCPlayer: NSObject {
NotificationCenter.default.addObserver(self, selector: #selector(generatorImagePreview), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationWillResignActive), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(applicationDidEnterBackground(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidEnterBackground), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(applicationDidBecomeActive(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidBecomeActive), object: nil)
-
+
NotificationCenter.default.addObserver(self, selector: #selector(playerPause), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterPauseMedia), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(playerPlay), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterPlayMedia), object: nil)
+
+ if let player = self.player {
+ NotificationCenter.default.addObserver(self, selector: #selector(playerStalled), name: NSNotification.Name.AVPlayerItemPlaybackStalled, object: player.currentItem)
+ }
+
+ isStartObserver = true
}
func deactivateObserver() {
+ print("deactivating Observer ocId \(metadata.ocId)")
+
if isPlay() {
playerPause()
}
-
- self.playerToolBar = nil
+
+ self.kvoPlayerObserver?.invalidate()
+ self.kvoPlayerObserver = nil
if let observerAVPlayerItemDidPlayToEndTime = self.observerAVPlayerItemDidPlayToEndTime {
NotificationCenter.default.removeObserver(observerAVPlayerItemDidPlayToEndTime)
}
- self.observerAVPlayerItemDidPlayToEndTime = nil
+ observerAVPlayerItemDidPlayToEndTime = nil
- if let observerAVPlayertTime = self.observerAVPlayertTime {
- player?.removeTimeObserver(observerAVPlayertTime)
+ if let observerAVPlayertTime = self.observerAVPlayertTime,
+ let player = player {
+ player.removeTimeObserver(observerAVPlayertTime)
}
- self.observerAVPlayertTime = nil
+ observerAVPlayertTime = nil
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationWillResignActive), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidEnterBackground), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidBecomeActive), object: nil)
-
+
+ NotificationCenter.default.removeObserver(self, name: NSNotification.Name.AVPlayerItemPlaybackStalled, object: nil)
+
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterPauseMedia), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterPlayMedia), object: nil)
+
+ isStartObserver = false
}
// MARK: - NotificationCenter
@objc func applicationDidEnterBackground(_ notification: NSNotification) {
-
+
if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue, let playerToolBar = self.playerToolBar {
if !playerToolBar.isPictureInPictureActive() {
playerPause()
@@ -238,24 +325,30 @@ class NCPlayer: NSObject {
playerToolBar?.updateToolBar()
}
-
+
// MARK: -
func isPlay() -> Bool {
if player?.rate == 1 { return true } else { return false }
}
-
+
+ @objc func playerStalled() {
+
+ print("current player \(String(describing: player)) stalled.\nCalling playerPlay()")
+ playerPlay()
+ }
+
@objc func playerPlay() {
-
+
player?.play()
- self.playerToolBar?.updateToolBar()
+ playerToolBar?.updateToolBar()
}
-
+
@objc func playerPause() {
-
+
player?.pause()
- self.playerToolBar?.updateToolBar()
+ playerToolBar?.updateToolBar()
if let playerToolBar = self.playerToolBar, playerToolBar.isPictureInPictureActive() {
playerToolBar.pictureInPictureController?.stopPictureInPicture()
@@ -265,7 +358,7 @@ class NCPlayer: NSObject {
func videoSeek(time: CMTime) {
player?.seek(to: time)
- self.saveTime(time)
+ saveTime(time)
}
func saveTime(_ time: CMTime) {
@@ -314,9 +407,54 @@ class NCPlayer: NSObject {
try data.write(to: URL(fileURLWithPath: fileNameIconLocalPath), options: .atomic)
}
} catch let error as NSError {
+ print("GeneratorImagePreview localized error:")
print(error.localizedDescription)
}
}
}
-}
+ internal func downloadVideo(requiredConvert: Bool = false) {
+
+ guard let view = appDelegate.window?.rootViewController?.view else { return }
+ let serverUrlFileName = metadata.serverUrl + "/" + metadata.fileName
+ let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
+ let hud = JGProgressHUD()
+ var downloadRequest: DownloadRequest?
+
+ hud.indicatorView = JGProgressHUDRingIndicatorView()
+ if let indicatorView = hud.indicatorView as? JGProgressHUDRingIndicatorView {
+ indicatorView.ringWidth = 1.5
+ }
+ hud.show(in: view)
+ hud.textLabel.text = NSLocalizedString(metadata.fileNameView, comment: "")
+ hud.detailTextLabel.text = NSLocalizedString("_tap_to_cancel_", comment: "")
+ hud.tapOnHUDViewBlock = { hud in
+ downloadRequest?.cancel()
+ }
+
+ NCCommunication.shared.download(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath) { request in
+ downloadRequest = request
+ } taskHandler: { task in
+ // task
+ } progressHandler: { progress in
+ hud.progress = Float(progress.fractionCompleted)
+ } completionHandler: { _, _, _, _, _, error, _, _ in
+ if error == nil {
+ NCManageDatabase.shared.addLocalFile(metadata: self.metadata)
+ let urlVideo = NCKTVHTTPCache.shared.getVideoURL(metadata: self.metadata)
+ if let url = urlVideo.url {
+ self.url = url
+ self.isProxy = urlVideo.isProxy
+ if requiredConvert {
+#if MFFFLIB
+ self.convertVideo(withAlert: false)
+#endif
+ } else {
+ self.openAVPlayer()
+ }
+ }
+ }
+ hud.dismiss()
+ }
+ }
+}
diff --git a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift
index b28862d4b..297b111a1 100644
--- a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift
+++ b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift
@@ -30,8 +30,10 @@ import MediaPlayer
class NCPlayerToolBar: UIView {
- @IBOutlet weak var playerTopToolBarView: UIView!
+ @IBOutlet weak var playerTopToolBarView: UIStackView!
+ @IBOutlet weak var playerToolBarView: UIView!
@IBOutlet weak var pipButton: UIButton!
+ @IBOutlet weak var subtitleButton: UIButton!
@IBOutlet weak var muteButton: UIButton!
@IBOutlet weak var playButton: UIButton!
@IBOutlet weak var forwardButton: UIButton!
@@ -39,19 +41,32 @@ class NCPlayerToolBar: UIView {
@IBOutlet weak var playbackSlider: UISlider!
@IBOutlet weak var labelLeftTime: UILabel!
@IBOutlet weak var labelCurrentTime: UILabel!
-
+
enum sliderEventType {
case began
case ended
case moved
}
- private var ncplayer: NCPlayer?
+ var ncplayer: NCPlayer?
private var metadata: tableMetadata?
private var wasInPlay: Bool = false
private var playbackSliderEvent: sliderEventType = .ended
private var timerAutoHide: Timer?
+ private var timerAutoHideSeconds: Double {
+ get {
+ if NCUtility.shared.isSimulator() { // for test
+ return 15
+ } else {
+ return 3.5
+ }
+ }
+ }
+
+
+// NCUtility.shared.isSimulatorOrTestFlight()
+
var pictureInPictureController: AVPictureInPictureController?
weak var viewerMediaPage: NCViewerMediaPage?
@@ -60,27 +75,21 @@ class NCPlayerToolBar: UIView {
override func awakeFromNib() {
super.awakeFromNib()
- // for disable gesture of UIPageViewController
- let panRecognizer = UIPanGestureRecognizer(target: self, action: nil)
- addGestureRecognizer(panRecognizer)
- let singleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didSingleTapWith(gestureRecognizer:)))
- addGestureRecognizer(singleTapGestureRecognizer)
-
- self.layer.cornerRadius = 15
- self.layer.masksToBounds = true
-
let blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
blurEffectView.frame = self.bounds
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
- self.insertSubview(blurEffectView, at: 0)
-
+ playerToolBarView.insertSubview(blurEffectView, at: 0)
playerTopToolBarView.layer.cornerRadius = 10
playerTopToolBarView.layer.masksToBounds = true
+ playerTopToolBarView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tapTopToolBarWith(gestureRecognizer:))))
let blurEffectTopToolBarView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
blurEffectTopToolBarView.frame = playerTopToolBarView.bounds
blurEffectTopToolBarView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
playerTopToolBarView.insertSubview(blurEffectTopToolBarView, at: 0)
+ playerToolBarView.layer.cornerRadius = 10
+ playerToolBarView.layer.masksToBounds = true
+ playerToolBarView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tapToolBarWith(gestureRecognizer:))))
pipButton.setImage(NCUtility.shared.loadImage(named: "pip.enter", color: .lightGray), for: .normal)
pipButton.isEnabled = false
@@ -88,6 +97,10 @@ class NCPlayerToolBar: UIView {
muteButton.setImage(NCUtility.shared.loadImage(named: "audioOff", color: .lightGray), for: .normal)
muteButton.isEnabled = false
+ subtitleButton.setImage(NCUtility.shared.loadImage(named: "captions.bubble", color: .white), for: .normal)
+ subtitleButton.isEnabled = true
+ subtitleButton.isHidden = true
+
playbackSlider.value = 0
playbackSlider.minimumValue = 0
playbackSlider.maximumValue = 0
@@ -100,9 +113,17 @@ class NCPlayerToolBar: UIView {
labelLeftTime.text = NCUtility.shared.stringFromTime(.zero)
labelLeftTime.textColor = .lightGray
+ backButton.setImage(NCUtility.shared.loadImage(named: "gobackward.10", color: .lightGray), for: .normal)
backButton.isEnabled = false
- playButton.setImage(NCUtility.shared.loadImage(named: "play.fill", color: .lightGray), for: .normal)
+
+ if #available(iOS 13.0, *) {
+ playButton.setImage(NCUtility.shared.loadImage(named: "play.fill", color: .lightGray, symbolConfiguration: UIImage.SymbolConfiguration(pointSize: 30)), for: .normal)
+ } else {
+ playButton.setImage(NCUtility.shared.loadImage(named: "play.fill", color: .lightGray, size: 30), for: .normal)
+ }
playButton.isEnabled = false
+
+ forwardButton.setImage(NCUtility.shared.loadImage(named: "goforward.10", color: .lightGray), for: .normal)
forwardButton.isEnabled = false
NotificationCenter.default.addObserver(self, selector: #selector(handleInterruption), name: AVAudioSession.interruptionNotification, object: nil)
@@ -121,12 +142,12 @@ class NCPlayerToolBar: UIView {
}
// MARK: -
-
+
func setMetadata(_ metadata: tableMetadata) {
-
+
self.metadata = metadata
}
-
+
func setBarPlayer(ncplayer: NCPlayer) {
self.ncplayer = ncplayer
@@ -143,7 +164,7 @@ class NCPlayerToolBar: UIView {
}
public func updateToolBar() {
-
+
guard let ncplayer = self.ncplayer else { return }
// MUTE
@@ -209,7 +230,7 @@ class NCPlayerToolBar: UIView {
// MARK: Handle Notifications
@objc func handleRouteChange(notification: Notification) {
-
+
guard let userInfo = notification.userInfo, let reasonValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt, let reason = AVAudioSession.RouteChangeReason(rawValue: reasonValue) else { return }
switch reason {
@@ -265,25 +286,23 @@ class NCPlayerToolBar: UIView {
guard let metadata = self.metadata, ncplayer != nil, !metadata.livePhoto else { return }
if metadata.classFile != NCCommunicationCommon.typeClassFile.video.rawValue && metadata.classFile != NCCommunicationCommon.typeClassFile.audio.rawValue { return }
- #if MFFFLIB
+#if MFFFLIB
if MFFF.shared.existsMFFFSession(url: URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView))) {
self.hide()
return
}
- #endif
-
+#endif
+
timerAutoHide?.invalidate()
if enableTimerAutoHide {
startTimerAutoHide()
}
if !self.isHidden { return }
-
+
UIView.animate(withDuration: 0.3, animations: {
self.alpha = 1
- self.playerTopToolBarView.alpha = 1
}, completion: { (_: Bool) in
self.isHidden = false
- self.playerTopToolBarView.isHidden = false
})
updateToolBar()
@@ -298,10 +317,8 @@ class NCPlayerToolBar: UIView {
UIView.animate(withDuration: 0.3, animations: {
self.alpha = 0
- self.playerTopToolBarView.alpha = 0
}, completion: { (_: Bool) in
self.isHidden = true
- self.playerTopToolBarView.isHidden = true
})
}
@@ -315,7 +332,7 @@ class NCPlayerToolBar: UIView {
private func startTimerAutoHide() {
timerAutoHide?.invalidate()
- timerAutoHide = Timer.scheduledTimer(timeInterval: 3.5, target: self, selector: #selector(automaticHide), userInfo: nil, repeats: false)
+ timerAutoHide = Timer.scheduledTimer(timeInterval: timerAutoHideSeconds, target: self, selector: #selector(automaticHide), userInfo: nil, repeats: false)
}
private func reStartTimerAutoHide() {
@@ -369,7 +386,7 @@ class NCPlayerToolBar: UIView {
timerAutoHide?.invalidate()
}
-
+
// MARK: - Event / Gesture
@objc func onSliderValChanged(slider: UISlider, event: UIEvent) {
@@ -403,19 +420,11 @@ class NCPlayerToolBar: UIView {
// MARK: - Action
- @objc func didSingleTapWith(gestureRecognizer: UITapGestureRecognizer) {
- // nothing
- }
+ @objc func tapTopToolBarWith(gestureRecognizer: UITapGestureRecognizer) { }
- @IBAction func buttonPlayerToolBarTouchInside(_ sender: UIButton) {
- // nothing
- }
-
- @IBAction func buttonPlayerTopToolBarTouchInside(_ sender: UIButton) {
- // nothing
- }
+ @objc func tapToolBarWith(gestureRecognizer: UITapGestureRecognizer) { }
- @IBAction func playerPause(_ sender: Any) {
+ @IBAction func tapPlayerPause(_ sender: Any) {
if ncplayer?.player?.timeControlStatus == .playing {
ncplayer?.playerPause()
@@ -429,6 +438,7 @@ class NCPlayerToolBar: UIView {
if let reason = ncplayer?.player?.reasonForWaitingToPlay {
switch reason {
case .evaluatingBufferingRate:
+ self.ncplayer?.player?.playImmediately(atRate: 1)
print("reasonForWaitingToPlay.evaluatingBufferingRate")
case .toMinimizeStalls:
print("reasonForWaitingToPlay.toMinimizeStalls")
@@ -441,7 +451,7 @@ class NCPlayerToolBar: UIView {
}
}
- @IBAction func setMute(_ sender: Any) {
+ @IBAction func tapMute(_ sender: Any) {
let mute = CCUtility.getAudioMute()
@@ -451,7 +461,7 @@ class NCPlayerToolBar: UIView {
reStartTimerAutoHide()
}
- @IBAction func setPip(_ sender: Any) {
+ @IBAction func tapPip(_ sender: Any) {
guard let videoLayer = ncplayer?.videoLayer else { return }
@@ -472,32 +482,36 @@ class NCPlayerToolBar: UIView {
}
}
- @IBAction func forwardButtonSec(_ sender: Any) {
+ @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()
- }
- */
+ if metadata?.classFile == NCCommunicationCommon.typeClassFile.video.rawValue {
+ skip(seconds: 10)
+ } else if metadata?.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
+ forward()
+ }
+ */
}
- @IBAction func backButtonSec(_ sender: Any) {
+ @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()
- }
- */
+ if metadata?.classFile == NCCommunicationCommon.typeClassFile.video.rawValue {
+ skip(seconds: -10)
+ } else if metadata?.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
+ backward()
+ }
+ */
+ }
+
+ @IBAction func tapSubtitle(_ sender: Any) {
+ self.ncplayer?.showAlertSubtitles()
}
-
+
func forward() {
var index: Int = 0
diff --git a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.xib b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.xib
new file mode 100644
index 000000000..9007a31d4
--- /dev/null
+++ b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.xib
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+ <device id="retina6_1" orientation="portrait" appearance="light"/>
+ <dependencies>
+ <deployment identifier="iOS"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
+ <capability name="Image references" minToolsVersion="12.0"/>
+ <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"/>
+ <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="NCPlayerToolBar" customModule="Nextcloud" customModuleProvider="target">
+ <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="XfW-XC-eMf" userLabel="Player Top Tool Bar">
+ <rect key="frame" x="299" y="54" width="105" height="35"/>
+ <subviews>
+ <button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="a3d-ja-utA">
+ <rect key="frame" x="5" y="5" width="25" height="25"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="25" id="TIW-zu-jSX"/>
+ <constraint firstAttribute="width" constant="25" id="jR3-bv-VnZ"/>
+ </constraints>
+ <state key="normal" image="pip.enter" catalog="system"/>
+ <connections>
+ <action selector="tapPip:" destination="iN0-l3-epB" eventType="touchUpInside" id="fB5-g1-OnB"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Mqe-Hd-USv">
+ <rect key="frame" x="40" y="5" width="25" height="25"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="25" id="HQs-6R-hb9"/>
+ <constraint firstAttribute="height" constant="25" id="s43-Qc-Shn"/>
+ </constraints>
+ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <state key="normal" image="captions.bubble" catalog="system"/>
+ <connections>
+ <action selector="tapSubtitle:" destination="iN0-l3-epB" eventType="touchUpInside" id="Cxi-6E-bKD"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Fml-c2-FMY">
+ <rect key="frame" x="75" y="5" width="25" height="25"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="25" id="S8g-UR-4zh"/>
+ <constraint firstAttribute="height" constant="25" id="zjo-O1-SI2"/>
+ </constraints>
+ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+ <state key="normal" image="audioOn"/>
+ <connections>
+ <action selector="tapMute:" destination="iN0-l3-epB" eventType="touchUpInside" id="FWr-cn-Pgw"/>
+ </connections>
+ </button>
+ </subviews>
+ <directionalEdgeInsets key="directionalLayoutMargins" top="5" leading="5" bottom="5" trailing="5"/>
+ </stackView>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="85m-50-8yp">
+ <rect key="frame" x="10" y="794" width="394" height="58"/>
+ <subviews>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ixi-yR-HDH" userLabel="Container play">
+ <rect key="frame" x="0.0" y="0.0" width="118" height="58"/>
+ <subviews>
+ <button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="uP7-aY-x4n">
+ <rect key="frame" x="3.5" y="9" width="40" height="40"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="40" id="0jv-Tl-Nch"/>
+ <constraint firstAttribute="height" constant="40" id="jnZ-cX-iJY"/>
+ </constraints>
+ <state key="normal" image="gobackward.10" catalog="system"/>
+ <connections>
+ <action selector="tapBack:" destination="iN0-l3-epB" eventType="touchUpInside" id="q3g-BH-iUc"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hx9-d5-yiD">
+ <rect key="frame" x="39" y="9" width="40" height="40"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="40" id="Ime-ag-2Hm"/>
+ <constraint firstAttribute="height" constant="40" id="snM-fJ-0LV"/>
+ </constraints>
+ <state key="normal">
+ <imageReference key="image" image="play.fill" catalog="system" symbolScale="default"/>
+ <preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="default"/>
+ </state>
+ <connections>
+ <action selector="tapPlayerPause:" destination="iN0-l3-epB" eventType="touchUpInside" id="XHf-om-3g9"/>
+ </connections>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="bGn-IC-3V1">
+ <rect key="frame" x="74.5" y="9" width="40" height="40"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="40" id="VDT-no-B6f"/>
+ <constraint firstAttribute="width" constant="40" id="eA5-wy-Sqb"/>
+ </constraints>
+ <state key="normal" image="goforward.10" catalog="system"/>
+ <connections>
+ <action selector="tapForward:" destination="iN0-l3-epB" eventType="touchUpInside" id="45z-IH-Fyr"/>
+ </connections>
+ </button>
+ </subviews>
+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <constraints>
+ <constraint firstItem="hx9-d5-yiD" firstAttribute="centerY" secondItem="ixi-yR-HDH" secondAttribute="centerY" id="Brn-9w-mrJ"/>
+ <constraint firstItem="bGn-IC-3V1" firstAttribute="centerY" secondItem="ixi-yR-HDH" secondAttribute="centerY" id="JBD-51-iYm"/>
+ <constraint firstItem="uP7-aY-x4n" firstAttribute="centerY" secondItem="ixi-yR-HDH" secondAttribute="centerY" id="MPU-Hg-zQa"/>
+ <constraint firstItem="hx9-d5-yiD" firstAttribute="centerX" secondItem="ixi-yR-HDH" secondAttribute="centerX" id="Vyv-jg-Cwu"/>
+ <constraint firstItem="uP7-aY-x4n" firstAttribute="centerX" secondItem="ixi-yR-HDH" secondAttribute="centerX" multiplier="0.4" id="bwk-Bx-qVb"/>
+ <constraint firstItem="bGn-IC-3V1" firstAttribute="centerX" secondItem="ixi-yR-HDH" secondAttribute="centerX" multiplier="1.6" id="wJP-ph-5c5"/>
+ </constraints>
+ </view>
+ <slider opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="MY0-FC-j88">
+ <rect key="frame" x="121" y="14" width="265" height="31"/>
+ </slider>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="99:99:99" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="svM-TQ-AyQ">
+ <rect key="frame" x="338.5" y="44" width="45.5" height="12"/>
+ <fontDescription key="fontDescription" type="system" pointSize="10"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="00:00:00" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="OHB-2J-Gqb">
+ <rect key="frame" x="123" y="44" width="45" height="12"/>
+ <fontDescription key="fontDescription" type="system" pointSize="10"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <constraints>
+ <constraint firstItem="ixi-yR-HDH" firstAttribute="centerY" secondItem="85m-50-8yp" secondAttribute="centerY" id="5sz-fh-GbG"/>
+ <constraint firstItem="OHB-2J-Gqb" firstAttribute="leading" secondItem="MY0-FC-j88" secondAttribute="leading" id="6n7-If-xdS"/>
+ <constraint firstItem="ixi-yR-HDH" firstAttribute="height" secondItem="85m-50-8yp" secondAttribute="height" id="8xM-7l-FXN"/>
+ <constraint firstAttribute="height" constant="58" id="9Uv-dV-to4"/>
+ <constraint firstItem="svM-TQ-AyQ" firstAttribute="top" secondItem="MY0-FC-j88" secondAttribute="bottom" id="Aan-ac-nr9"/>
+ <constraint firstItem="MY0-FC-j88" firstAttribute="leading" secondItem="ixi-yR-HDH" secondAttribute="trailing" constant="5" id="BAz-4C-w3A"/>
+ <constraint firstAttribute="trailing" secondItem="svM-TQ-AyQ" secondAttribute="trailing" constant="10" id="JXl-DO-x6b"/>
+ <constraint firstItem="ixi-yR-HDH" firstAttribute="leading" secondItem="85m-50-8yp" secondAttribute="leading" id="Kh2-nU-bMU"/>
+ <constraint firstItem="ixi-yR-HDH" firstAttribute="width" secondItem="85m-50-8yp" secondAttribute="width" multiplier="0.3" id="gXG-4n-Ee3"/>
+ <constraint firstAttribute="trailing" secondItem="MY0-FC-j88" secondAttribute="trailing" constant="10" id="hBO-J2-Kdo"/>
+ <constraint firstItem="OHB-2J-Gqb" firstAttribute="top" secondItem="MY0-FC-j88" secondAttribute="bottom" id="jdb-Vq-WoF"/>
+ <constraint firstItem="MY0-FC-j88" firstAttribute="centerY" secondItem="85m-50-8yp" secondAttribute="centerY" id="lG8-DN-rTE"/>
+ </constraints>
+ </view>
+ </subviews>
+ <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <constraints>
+ <constraint firstItem="85m-50-8yp" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="10" id="5H2-Gg-PEb"/>
+ <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="85m-50-8yp" secondAttribute="trailing" constant="10" id="BXT-Qo-qFl"/>
+ <constraint firstItem="vUN-kp-3ea" firstAttribute="bottom" secondItem="85m-50-8yp" secondAttribute="bottom" constant="10" id="N7Q-PF-7lb"/>
+ <constraint firstItem="XfW-XC-eMf" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" constant="10" id="fq3-6h-kkx"/>
+ <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="XfW-XC-eMf" secondAttribute="trailing" constant="10" id="uYG-Ai-CGv"/>
+ </constraints>
+ <connections>
+ <outlet property="backButton" destination="uP7-aY-x4n" id="SyC-qV-IMq"/>
+ <outlet property="forwardButton" destination="bGn-IC-3V1" id="0OZ-f2-eWU"/>
+ <outlet property="labelCurrentTime" destination="OHB-2J-Gqb" id="pFy-CJ-x2A"/>
+ <outlet property="labelLeftTime" destination="svM-TQ-AyQ" id="UDV-Lh-12z"/>
+ <outlet property="muteButton" destination="Fml-c2-FMY" id="Fo1-Ep-ZPz"/>
+ <outlet property="pipButton" destination="a3d-ja-utA" id="9nt-RD-IXd"/>
+ <outlet property="playButton" destination="hx9-d5-yiD" id="Enk-Ge-2Yx"/>
+ <outlet property="playbackSlider" destination="MY0-FC-j88" id="bVe-Kc-80k"/>
+ <outlet property="playerToolBarView" destination="85m-50-8yp" id="eZK-p1-v65"/>
+ <outlet property="playerTopToolBarView" destination="XfW-XC-eMf" id="Qdp-IW-YhT"/>
+ <outlet property="subtitleButton" destination="Mqe-Hd-USv" id="ZHN-bf-WT5"/>
+ </connections>
+ <point key="canvasLocation" x="137.68115942028987" y="152.67857142857142"/>
+ </view>
+ </objects>
+ <resources>
+ <image name="audioOn" width="28" height="28"/>
+ <image name="captions.bubble" catalog="system" width="128" height="110"/>
+ <image name="gobackward.10" catalog="system" width="121" height="128"/>
+ <image name="goforward.10" catalog="system" width="121" height="128"/>
+ <image name="pip.enter" catalog="system" width="128" height="96"/>
+ <image name="play.fill" catalog="system" width="116" height="128"/>
+ </resources>
+</document>
diff --git a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCSubtitle/NCSubtitlePlayer.swift b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCSubtitle/NCSubtitlePlayer.swift
new file mode 100644
index 000000000..3955fe8b5
--- /dev/null
+++ b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCSubtitle/NCSubtitlePlayer.swift
@@ -0,0 +1,405 @@
+//
+// NCSubtitlePlayer.swift
+// Nextcloud
+//
+// Created by Federico Malagoni on 18/02/22.
+// Copyright © 2022 Federico Malagoni. All rights reserved.
+// Copyright © 2022 Marino Faggiana All rights reserved.
+//
+// Author Federico Malagoni <federico.malagoni@astrairidium.com>
+// 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 AVKit
+
+extension NCPlayer {
+
+ private struct AssociatedKeys {
+ static var FontKey = "FontKey"
+ static var ColorKey = "FontKey"
+ static var SubtitleKey = "SubtitleKey"
+ static var SubtitleContainerViewKey = "SubtitleContainerViewKey"
+ static var SubtitleContainerViewHeightKey = "SubtitleContainerViewHeightKey"
+ static var SubtitleHeightKey = "SubtitleHeightKey"
+ static var SubtitleWidthKey = "SubtitleWidthKey"
+ static var SubtitleContainerViewWidthKey = "SubtitleContainerViewWidthKey"
+ static var SubtitleBottomKey = "SubtitleBottomKey"
+ static var PayloadKey = "PayloadKey"
+ }
+
+ private var widthProportion: CGFloat {
+ return 0.9
+ }
+
+ private var bottomConstantPortrait: CGFloat {
+ get {
+ if UIDevice.current.hasNotch {
+ return -60
+ } else {
+ return -40
+ }
+ } set {
+ _ = newValue
+ }
+ }
+
+ private var bottomConstantLandscape: CGFloat {
+ get {
+ if UIDevice.current.hasNotch {
+ return -120
+ } else {
+ return -100
+ }
+ } set {
+ _ = newValue
+ }
+ }
+
+ var subtitleContainerView: UIView? {
+ get { return objc_getAssociatedObject(self, &AssociatedKeys.SubtitleContainerViewKey) as? UIView }
+ set (value) { objc_setAssociatedObject(self, &AssociatedKeys.SubtitleContainerViewKey, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)}
+ }
+
+ var subtitleLabel: UILabel? {
+ get { return objc_getAssociatedObject(self, &AssociatedKeys.SubtitleKey) as? UILabel }
+ set (value) { objc_setAssociatedObject(self, &AssociatedKeys.SubtitleKey, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
+ }
+
+ fileprivate var subtitleLabelHeightConstraint: NSLayoutConstraint? {
+ get { return objc_getAssociatedObject(self, &AssociatedKeys.SubtitleHeightKey) as? NSLayoutConstraint }
+ set (value) { objc_setAssociatedObject(self, &AssociatedKeys.SubtitleHeightKey, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
+ }
+
+ fileprivate var subtitleContainerViewHeightConstraint: NSLayoutConstraint? {
+ get { return objc_getAssociatedObject(self, &AssociatedKeys.SubtitleContainerViewHeightKey) as? NSLayoutConstraint }
+ set (value) { objc_setAssociatedObject(self, &AssociatedKeys.SubtitleContainerViewHeightKey, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
+ }
+
+ fileprivate var subtitleLabelBottomConstraint: NSLayoutConstraint? {
+ get { return objc_getAssociatedObject(self, &AssociatedKeys.SubtitleBottomKey) as? NSLayoutConstraint }
+ set (value) { objc_setAssociatedObject(self, &AssociatedKeys.SubtitleBottomKey, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
+ }
+
+ fileprivate var subtitleLabelWidthConstraint: NSLayoutConstraint? {
+ get { return objc_getAssociatedObject(self, &AssociatedKeys.SubtitleWidthKey) as? NSLayoutConstraint }
+ set (value) { objc_setAssociatedObject(self, &AssociatedKeys.SubtitleWidthKey, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
+ }
+ fileprivate var subtitleContainerViewWidthConstraint: NSLayoutConstraint? {
+ get { return objc_getAssociatedObject(self, &AssociatedKeys.SubtitleContainerViewWidthKey) as? NSLayoutConstraint }
+ set (value) { objc_setAssociatedObject(self, &AssociatedKeys.SubtitleContainerViewWidthKey, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
+ }
+
+ fileprivate var parsedPayload: NSDictionary? {
+ get { return objc_getAssociatedObject(self, &AssociatedKeys.PayloadKey) as? NSDictionary }
+ set (value) { objc_setAssociatedObject(self, &AssociatedKeys.PayloadKey, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
+ }
+
+ func setUpForSubtitle() {
+ self.subtitleUrls.removeAll()
+ if let url = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId) {
+ let enumerator = FileManager.default.enumerator(atPath: url)
+ let filePaths = (enumerator?.allObjects as? [String])
+ if let filePaths = filePaths {
+ let txtFilePaths = (filePaths.filter { $0.contains(".srt") }).sorted {
+ guard let str1LastChar = $0.dropLast(4).last, let str2LastChar = $1.dropLast(4).last else {
+ return false
+ }
+ return str1LastChar < str2LastChar
+ }
+ for txtFilePath in txtFilePaths {
+ let subtitleUrl = URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: txtFilePath))
+ self.subtitleUrls.append(subtitleUrl)
+ }
+ }
+ }
+ let (all, existing) = NCManageDatabase.shared.getSubtitles(account: metadata.account, serverUrl: metadata.serverUrl, fileName: metadata.fileName)
+ if !existing.isEmpty {
+ for subtitle in existing {
+ let subtitleUrl = URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(subtitle.ocId, fileNameView: subtitle.fileName))
+ self.subtitleUrls.append(subtitleUrl)
+ }
+ }
+ if all.count != existing.count {
+ NCContentPresenter.shared.messageNotification("_info_", description: "_subtitle_not_dowloaded_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorNoError)
+ }
+ self.setSubtitleToolbarIcon(subtitleUrls: subtitleUrls)
+ self.hideSubtitle()
+ }
+
+ func setSubtitleToolbarIcon(subtitleUrls: [URL]) {
+ if subtitleUrls.isEmpty {
+ playerToolBar?.subtitleButton.isHidden = true
+ } else {
+ playerToolBar?.subtitleButton.isHidden = false
+ }
+ }
+
+ func addSubtitlesTo(_ vc: UIViewController, _ playerToolBar: NCPlayerToolBar?) {
+ addSubtitleLabel(vc, playerToolBar)
+ NotificationCenter.default.addObserver(self, selector: #selector(deviceRotated(_:)), name: UIDevice.orientationDidChangeNotification, object: nil)
+ }
+
+ func loadText(filePath: URL, _ completion:@escaping (_ contents: String?) -> Void) {
+ DispatchQueue.global(qos: .background).async {
+ guard let data = try? Data(contentsOf: filePath),
+ let encoding = NCUtility.shared.getEncondingDataType(data: data) else {
+ return
+ }
+ if let decodedString = String(data: data, encoding: encoding) {
+ completion(decodedString)
+ } else {
+ completion(nil)
+ }
+ }
+ }
+
+ func open(fileFromLocal url: URL) {
+
+ subtitleLabel?.text = ""
+
+ self.loadText(filePath: url) { contents in
+ guard let contents = contents else {
+ return
+ }
+ DispatchQueue.main.async {
+ self.subtitleLabel?.text = ""
+ self.show(subtitles: contents)
+ }
+ }
+ }
+
+ @objc public func hideSubtitle() {
+ self.subtitleLabel?.isHidden = true
+ self.subtitleContainerView?.isHidden = true
+ self.currentSubtitle = nil
+ }
+
+ @objc public func showSubtitle(url: URL) {
+ self.subtitleLabel?.isHidden = false
+ self.subtitleContainerView?.isHidden = false
+ self.currentSubtitle = url
+ }
+
+ private func show(subtitles string: String) {
+ parsedPayload = try? NCSubtitles.parseSubRip(string)
+ if let parsedPayload = parsedPayload {
+ addPeriodicNotification(parsedPayload: parsedPayload)
+ }
+ }
+
+ private func showByDictionary(dictionaryContent: NSMutableDictionary) {
+ parsedPayload = dictionaryContent
+ if let parsedPayload = parsedPayload {
+ addPeriodicNotification(parsedPayload: parsedPayload)
+ }
+ }
+
+ func addPeriodicNotification(parsedPayload: NSDictionary) {
+ // Add periodic notifications
+ let interval = CMTimeMake(value: 1, timescale: 60)
+ self.player?.addPeriodicTimeObserver(forInterval: interval, queue: .main) { [weak self] time in
+ guard let strongSelf = self, let label = strongSelf.subtitleLabel, let containerView = strongSelf.subtitleContainerView else {
+ return
+ }
+ DispatchQueue.main.async {
+ label.text = NCSubtitles.searchSubtitles(strongSelf.parsedPayload, time.seconds)
+ strongSelf.adjustViewWidth(containerView: containerView)
+ strongSelf.adjustLabelHeight(label: label)
+ }
+ }
+ }
+
+ @objc private func deviceRotated(_ notification: Notification) {
+ guard let label = self.subtitleLabel,
+ let containerView = self.subtitleContainerView else { return }
+ DispatchQueue.main.async {
+ self.adjustViewWidth(containerView: containerView)
+ self.adjustLabelHeight(label: label)
+ self.adjustLabelBottom(label: label)
+ containerView.layoutIfNeeded()
+ label.layoutIfNeeded()
+ }
+ }
+
+ private func adjustLabelHeight(label: UILabel) {
+ let baseSize = CGSize(width: label.bounds.width, height: .greatestFiniteMagnitude)
+ let rect = label.sizeThatFits(baseSize)
+ if label.text != nil {
+ self.subtitleLabelHeightConstraint?.constant = rect.height + 5.0
+ } else {
+ self.subtitleLabelHeightConstraint?.constant = rect.height
+ }
+ }
+
+ private func adjustLabelBottom(label: UILabel) {
+ var bottomConstant: CGFloat = bottomConstantPortrait
+
+ switch UIApplication.shared.statusBarOrientation {
+ case .portrait:
+ bottomConstant = bottomConstantLandscape
+ case .landscapeLeft, .landscapeRight, .portraitUpsideDown:
+ bottomConstant = bottomConstantPortrait
+ default:
+ ()
+ }
+ subtitleLabelBottomConstraint?.constant = bottomConstant
+ }
+
+ private func adjustViewWidth(containerView: UIView) {
+ let widthConstant: CGFloat = UIScreen.main.bounds.width * widthProportion
+ subtitleContainerViewWidthConstraint!.constant = widthConstant
+ subtitleLabel?.preferredMaxLayoutWidth = (widthConstant - 20)
+ }
+
+ fileprivate func addSubtitleLabel(_ vc: UIViewController, _ playerToolBar: NCPlayerToolBar?) {
+ guard subtitleLabel == nil,
+ subtitleContainerView == nil else {
+ return
+ }
+ subtitleContainerView = UIView()
+ subtitleLabel = UILabel()
+
+ subtitleContainerView?.translatesAutoresizingMaskIntoConstraints = false
+ subtitleContainerView?.layer.cornerRadius = 5.0
+ subtitleContainerView?.layer.masksToBounds = true
+ subtitleContainerView?.layer.shouldRasterize = true
+ subtitleContainerView?.layer.rasterizationScale = UIScreen.main.scale
+ subtitleContainerView?.backgroundColor = UIColor.black.withAlphaComponent(0.35)
+
+ subtitleLabel?.translatesAutoresizingMaskIntoConstraints = false
+ subtitleLabel?.textAlignment = .center
+ subtitleLabel?.numberOfLines = 0
+ let fontSize = UIDevice.current.userInterfaceIdiom == .pad ? 38.0 : 20.0
+ subtitleLabel?.font = UIFont.incosolataMedium(size: fontSize)
+ subtitleLabel?.lineBreakMode = .byWordWrapping
+ subtitleLabel?.textColor = .white
+ subtitleLabel?.backgroundColor = .clear
+
+ subtitleContainerView?.addSubview(subtitleLabel!)
+
+ var isFound = false
+
+ for v in vc.view.subviews where v is UIScrollView {
+ if let scrollView = v as? UIScrollView {
+ for subView in scrollView.subviews where subView is imageVideoContainerView {
+ subView.addSubview(subtitleContainerView!)
+ isFound = true
+ break
+ }
+ }
+ }
+
+ if !isFound {
+ vc.view.addSubview(subtitleContainerView!)
+ }
+
+ NSLayoutConstraint.activate([
+ subtitleLabel!.centerXAnchor.constraint(equalTo: subtitleContainerView!.centerXAnchor),
+ subtitleLabel!.centerYAnchor.constraint(equalTo: subtitleContainerView!.centerYAnchor)
+ ])
+
+ subtitleContainerViewHeightConstraint = NSLayoutConstraint(item: subtitleContainerView!, attribute: .height, relatedBy: .equal, toItem: subtitleLabel!, attribute: .height, multiplier: 1.0, constant: 0.0)
+ vc.view?.addConstraint(subtitleContainerViewHeightConstraint!)
+
+ var bottomConstant: CGFloat = bottomConstantPortrait
+
+ switch UIApplication.shared.statusBarOrientation {
+ case .portrait, .portraitUpsideDown:
+ bottomConstant = bottomConstantLandscape
+ case .landscapeLeft, .landscapeRight:
+ bottomConstant = bottomConstantPortrait
+ default:
+ ()
+ }
+
+ let widthConstant: CGFloat = UIScreen.main.bounds.width * widthProportion
+
+ NSLayoutConstraint.activate([
+ subtitleContainerView!.centerXAnchor.constraint(equalTo: vc.view.centerXAnchor)
+ ])
+
+ subtitleContainerViewWidthConstraint = NSLayoutConstraint(item: subtitleContainerView!, attribute: .width, relatedBy: .lessThanOrEqual, toItem: nil,
+ attribute: .width, multiplier: 1, constant: widthConstant)
+
+ // setting default width == 0 because there is no text inside of the label
+ subtitleLabelWidthConstraint = NSLayoutConstraint(item: subtitleLabel!, attribute: .width, relatedBy: .equal, toItem: subtitleContainerView,
+ attribute: .width, multiplier: 1, constant: -20)
+
+ subtitleLabelBottomConstraint = NSLayoutConstraint(item: subtitleContainerView!, attribute: .bottom, relatedBy: .equal, toItem: vc.view, attribute:
+ .bottom, multiplier: 1, constant: bottomConstant)
+
+ vc.view?.addConstraint(subtitleContainerViewWidthConstraint!)
+ vc.view?.addConstraint(subtitleLabelWidthConstraint!)
+ vc.view?.addConstraint(subtitleLabelBottomConstraint!)
+ }
+
+ internal func showAlertSubtitles() {
+
+ let alert = UIAlertController(title: nil, message: NSLocalizedString("_subtitle_", comment: ""), preferredStyle: .actionSheet)
+
+ for url in subtitleUrls {
+
+ print("Play Subtitle at:\n\(url.path)")
+
+ let videoUrlTitle = self.metadata.fileName.alphanumeric.dropLast(3)
+ let subtitleUrlTitle = url.lastPathComponent.alphanumeric.dropLast(3)
+
+ var titleSubtitle = String(subtitleUrlTitle.dropFirst(videoUrlTitle.count))
+ if titleSubtitle.isEmpty {
+ titleSubtitle = NSLocalizedString("_subtitle_", comment: "")
+ }
+
+ let action = UIAlertAction(title: titleSubtitle, style: .default, handler: { [self] _ in
+
+ if NCUtilityFileSystem.shared.getFileSize(filePath: url.path) > 0 {
+
+ self.open(fileFromLocal: url)
+ if let viewController = viewController {
+ self.addSubtitlesTo(viewController, self.playerToolBar)
+ self.showSubtitle(url: url)
+ }
+
+ } else {
+
+ let alertError = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: NSLocalizedString("_subtitle_not_found_", comment: ""), preferredStyle: .alert)
+ alertError.addAction(UIKit.UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: nil))
+
+ viewController?.present(alertError, animated: true, completion: nil)
+ }
+ })
+ alert.addAction(action)
+ if currentSubtitle == url {
+ action.setValue(true, forKey: "checked")
+ }
+ }
+
+ let disable = UIAlertAction(title: NSLocalizedString("_disable_", comment: ""), style: .default, handler: { _ in
+ self.hideSubtitle()
+ })
+ alert.addAction(disable)
+ if currentSubtitle == nil {
+ disable.setValue(true, forKey: "checked")
+ }
+
+ alert.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel, handler: { _ in
+ }))
+
+ alert.popoverPresentationController?.sourceView = self.viewController?.view
+
+ self.viewController?.present(alert, animated: true, completion: nil)
+ }
+}
diff --git a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCSubtitle/NCSubtitles.swift b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCSubtitle/NCSubtitles.swift
new file mode 100644
index 000000000..3fb452420
--- /dev/null
+++ b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCSubtitle/NCSubtitles.swift
@@ -0,0 +1,150 @@
+//
+// NCSubtitles
+// Nextcloud
+//
+// Created by Marc Hervera.
+// Copyright 2017 Marc Hervera AVPlayerViewController-Subtitles v1.3.1 iOS
+//
+// Modified by Federico Malagoni on 23/02/22 for Nextcloud.
+//
+// Licensed under Apache License v2.0.
+//
+
+import AVKit
+
+class NCSubtitles {
+
+ // MARK: - Private properties
+
+ private var parsedPayload: NSDictionary?
+
+ // MARK: - Public methods
+
+ public init(file filePath: URL, encoding: String.Encoding = .utf8) throws {
+ // Get string
+ let string = try String(contentsOf: filePath, encoding: encoding)
+ // Parse string
+ parsedPayload = try NCSubtitles.parseSubRip(string)
+ }
+
+ public init(subtitles string: String) throws {
+ // Parse string
+ parsedPayload = try NCSubtitles.parseSubRip(string)
+ }
+
+ /// Search subtitles at time
+ ///
+ /// - Parameter time: Time
+ /// - Returns: String if exists
+ public func searchSubtitles(at time: TimeInterval) -> String? {
+ return NCSubtitles.searchSubtitles(parsedPayload, time)
+ }
+
+ // MARK: - Static methods
+
+ /// Subtitle parser
+ ///
+ /// - Parameter payload: Input string
+ /// - Returns: NSDictionary
+ static func parseSubRip(_ payload: String) throws -> NSDictionary? {
+ // Prepare payload
+ var payload = payload.replacingOccurrences(of: "\n\r\n", with: "\n\n")
+ payload = payload.replacingOccurrences(of: "\n\n\n", with: "\n\n")
+ payload = payload.replacingOccurrences(of: "\r\n", with: "\n")
+
+ // Parsed dict
+ let parsed = NSMutableDictionary()
+
+ // Get groups
+ let regexStr = "(\\d+)\\n([\\d:,.]+)\\s+-{2}\\>\\s+([\\d:,.]+)\\n([\\s\\S]*?(?=\\n{2,}|$))"
+ let regex = try NSRegularExpression(pattern: regexStr, options: .caseInsensitive)
+ let matches = regex.matches(in: payload, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSRange(location: 0, length: payload.count))
+
+ for m in matches {
+ let group = (payload as NSString).substring(with: m.range)
+
+ // Get index
+ var regex = try NSRegularExpression(pattern: "^[0-9]+", options: .caseInsensitive)
+ var match = regex.matches(in: group, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSRange(location: 0, length: group.count))
+
+ guard let i = match.first else {
+ continue
+ }
+
+ let index = (group as NSString).substring(with: i.range)
+
+ // Get "from" & "to" time
+ regex = try NSRegularExpression(pattern: "\\d{1,2}:\\d{1,2}:\\d{1,2}[,.]\\d{1,3}", options: .caseInsensitive)
+ match = regex.matches(in: group, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSRange(location: 0, length: group.count))
+
+ guard match.count == 2 else {
+ continue
+ }
+
+ guard let from = match.first, let to = match.last else {
+ continue
+ }
+
+ var h: TimeInterval = 0.0, m: TimeInterval = 0.0, s: TimeInterval = 0.0, c: TimeInterval = 0.0
+
+ let fromStr = (group as NSString).substring(with: from.range)
+ var scanner = Scanner(string: fromStr)
+ scanner.scanDouble(&h)
+ scanner.scanString(":", into: nil)
+ scanner.scanDouble(&m)
+ scanner.scanString(":", into: nil)
+ scanner.scanDouble(&s)
+ scanner.scanString(",", into: nil)
+ scanner.scanDouble(&c)
+ let fromTime = (h * 3600.0) + (m * 60.0) + s + (c / 1000.0)
+
+ let toStr = (group as NSString).substring(with: to.range)
+ scanner = Scanner(string: toStr)
+ scanner.scanDouble(&h)
+ scanner.scanString(":", into: nil)
+ scanner.scanDouble(&m)
+ scanner.scanString(":", into: nil)
+ scanner.scanDouble(&s)
+ scanner.scanString(",", into: nil)
+ scanner.scanDouble(&c)
+ let toTime = (h * 3600.0) + (m * 60.0) + s + (c / 1000.0)
+
+ // Get text & check if empty
+ let range = NSRange(location: 0, length: to.range.location + to.range.length + 1)
+ guard (group as NSString).length - range.length > 0 else {
+ continue
+ }
+
+ let text = (group as NSString).replacingCharacters(in: range, with: "")
+
+ // Create final object
+ let final = NSMutableDictionary()
+ final["from"] = fromTime
+ final["to"] = toTime
+ final["text"] = text
+ parsed[index] = final
+ }
+
+ return parsed
+ }
+
+ /// Search subtitle on time
+ ///
+ /// - Parameters:
+ /// - payload: Inout payload
+ /// - time: Time
+ /// - Returns: String
+ static func searchSubtitles(_ payload: NSDictionary?, _ time: TimeInterval) -> String? {
+ let predicate = NSPredicate(format: "(%f >= %K) AND (%f <= %K)", time, "from", time, "to")
+
+ guard let values = payload?.allValues, let result = (values as NSArray).filtered(using: predicate).first as? NSDictionary else {
+ return nil
+ }
+
+ guard let text = result.value(forKey: "text") as? String else {
+ return nil
+ }
+
+ return text.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
+ }
+}
diff --git a/iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift b/iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift
index f276b5e92..92ffb8ceb 100644
--- a/iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift
+++ b/iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift
@@ -36,12 +36,12 @@ class NCViewerMedia: UIViewController {
@IBOutlet weak var statusViewImage: UIImageView!
@IBOutlet weak var statusLabel: UILabel!
@IBOutlet weak var detailView: NCViewerMediaDetailView!
- @IBOutlet weak var playerToolBar: NCPlayerToolBar!
private var _autoPlay: Bool = false
let appDelegate = UIApplication.shared.delegate as! AppDelegate
- var viewerMediaPage: NCViewerMediaPage?
+ weak var viewerMediaPage: NCViewerMediaPage?
+ var playerToolBar: NCPlayerToolBar?
var ncplayer: NCPlayer?
var image: UIImage?
var metadata: tableMetadata = tableMetadata()
@@ -92,23 +92,33 @@ class NCViewerMedia: UIViewController {
statusViewImage.image = nil
statusLabel.text = ""
}
+
+ if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
- playerToolBar.viewerMediaPage = viewerMediaPage
+ playerToolBar = Bundle.main.loadNibNamed("NCPlayerToolBar", owner: self, options: nil)?.first as? NCPlayerToolBar
+ if let playerToolBar = playerToolBar {
+ view.addSubview(playerToolBar)
+ playerToolBar.translatesAutoresizingMaskIntoConstraints = false
+ playerToolBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
+ playerToolBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
+ playerToolBar.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 0).isActive = true
+ playerToolBar.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: 0).isActive = true
+ playerToolBar.viewerMediaPage = viewerMediaPage
+ }
+ let urlVideo = NCKTVHTTPCache.shared.getVideoURL(metadata: metadata)
+ if let url = urlVideo.url {
+ 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)
+ }
+ }
+
detailViewTopConstraint.constant = 0
detailView.hide()
self.image = nil
self.imageVideoContainer.image = nil
- 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
- }
- }
+ reloadImage()
}
override func viewWillAppear(_ animated: Bool) {
@@ -119,6 +129,10 @@ class NCViewerMedia: UIViewController {
if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue, let viewerMediaPage = self.viewerMediaPage {
viewerMediaPage.currentScreenMode = viewerMediaPage.saveScreenModeImage
+ if viewerMediaPage.modifiedOcId.contains(metadata.ocId) {
+ viewerMediaPage.modifiedOcId.removeAll(where: { $0 == metadata.ocId })
+ reloadImage()
+ }
}
if viewerMediaPage?.currentScreenMode == .full {
@@ -148,25 +162,11 @@ class NCViewerMedia: UIViewController {
if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
- NCKTVHTTPCache.shared.restartProxy(user: appDelegate.user, password: appDelegate.password)
-
- if ncplayer == nil, let url = NCKTVHTTPCache.shared.getVideoURL(metadata: metadata) {
- self.ncplayer = NCPlayer.init(url: url, autoPlay: self.autoPlay, imageVideoContainer: self.imageVideoContainer, playerToolBar: self.playerToolBar, metadata: self.metadata, detailView: self.detailView, viewController: self)
- } else {
- self.ncplayer?.activateObserver(playerToolBar: self.playerToolBar)
- if detailView.isShow() == false && ncplayer?.isPlay() == false {
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterShowPlayerToolBar, userInfo: ["ocId": metadata.ocId, "enableTimerAutoHide": false])
- }
- }
-
if let ncplayer = self.ncplayer {
+ ncplayer.openAVPlayer()
self.viewerMediaPage?.updateCommandCenter(ncplayer: ncplayer, metadata: self.metadata)
}
- #if MFFFLIB
- MFFF.shared.setDelegate = self.ncplayer
- #endif
-
} else if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue {
viewerMediaPage?.clearCommandCenter()
@@ -196,6 +196,20 @@ class NCViewerMedia: UIViewController {
// MARK: - Image
+ 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
+ }
+ }
+ }
+ }
+
func loadImage(metadata: tableMetadata, completion: @escaping (_ ocId: String, _ image: UIImage?) -> Void) {
// Download preview
@@ -439,8 +453,13 @@ extension NCViewerMedia {
self.detailViewHeighConstraint.constant = 170
}
self.view.layoutIfNeeded()
-
- self.detailView.show(metadata:self.metadata, image: self.image, textColor: self.viewerMediaPage?.textColor, latitude: latitude, longitude: longitude, location: location, date: date, lensModel: lensModel, ncplayer: self.ncplayer ,delegate: self)
+ self.detailView.show(
+ metadata: self.metadata,
+ image: self.image,
+ textColor: self.viewerMediaPage?.textColor,
+ mediaMetadata: (latitude: latitude, longitude: longitude, location: location, date: date, lensModel: lensModel),
+ ncplayer: self.ncplayer,
+ delegate: self)
if let image = self.imageVideoContainer.image {
let ratioW = self.imageVideoContainer.frame.width / image.size.width
@@ -460,7 +479,7 @@ extension NCViewerMedia {
}
self.scrollView.pinchGestureRecognizer?.isEnabled = false
- self.playerToolBar.hide()
+ self.playerToolBar?.hide()
}
}
@@ -487,7 +506,13 @@ extension NCViewerMedia {
if self.detailView.isShow() {
CCUtility.setExif(metadata) { (latitude, longitude, location, date, lensModel) in
- self.detailView.show(metadata:self.metadata, image: self.image, textColor: self.viewerMediaPage?.textColor, latitude: latitude, longitude: longitude, location: location, date: date, lensModel: lensModel, ncplayer: self.ncplayer ,delegate: self)
+ self.detailView.show(
+ metadata: self.metadata,
+ image: self.image,
+ textColor: self.viewerMediaPage?.textColor,
+ mediaMetadata: (latitude: latitude, longitude: longitude, location: location, date: date, lensModel: lensModel),
+ ncplayer: self.ncplayer,
+ delegate: self)
}
}
}
diff --git a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift
index 350b795cb..15bd22701 100644
--- a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift
+++ b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift
@@ -25,6 +25,8 @@ import UIKit
import MapKit
import NCCommunication
+typealias NCImageMetadata = (latitude: Double, longitude: Double, location: String?, date: Date?, lensModel: String?)
+
public protocol NCViewerMediaDetailViewDelegate: AnyObject {
func downloadFullResolution()
}
@@ -52,8 +54,8 @@ class NCViewerMediaDetailView: UIView {
var metadata: tableMetadata?
var mapView: MKMapView?
var ncplayer: NCPlayer?
- var delegate: NCViewerMediaDetailViewDelegate?
-
+ weak var delegate: NCViewerMediaDetailViewDelegate?
+
override func awakeFromNib() {
super.awakeFromNib()
@@ -76,15 +78,15 @@ class NCViewerMediaDetailView: UIView {
self.mapView?.removeFromSuperview()
self.mapView = nil
}
-
- func show(metadata: tableMetadata, image: UIImage?, textColor: UIColor?, latitude: Double, longitude: Double, location: String?, date: Date?, lensModel: String?, ncplayer: NCPlayer?, delegate: NCViewerMediaDetailViewDelegate?) {
-
+
+ func show(metadata: tableMetadata, image: UIImage?, textColor: UIColor?, mediaMetadata: NCImageMetadata, ncplayer: NCPlayer?, delegate: NCViewerMediaDetailViewDelegate?) {
+
self.metadata = metadata
- self.latitude = latitude
- self.longitude = longitude
- self.location = location
- self.date = date
- self.lensModel = lensModel
+ self.latitude = mediaMetadata.latitude
+ self.longitude = mediaMetadata.longitude
+ self.location = mediaMetadata.location
+ self.date = mediaMetadata.date
+ self.lensModel = mediaMetadata.lensModel
self.ncplayer = ncplayer
self.delegate = delegate
@@ -93,25 +95,24 @@ class NCViewerMediaDetailView: UIView {
let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
- self.mapView = MKMapView()
- if let mapView = self.mapView {
- mapView.translatesAutoresizingMaskIntoConstraints = false
- self.mapContainer.addSubview(mapView)
-
- NSLayoutConstraint.activate([
- mapView.topAnchor.constraint(equalTo: self.mapContainer.topAnchor),
- mapView.bottomAnchor.constraint(equalTo: self.mapContainer.bottomAnchor),
- mapView.leadingAnchor.constraint(equalTo: self.mapContainer.leadingAnchor),
- mapView.trailingAnchor.constraint(equalTo: self.mapContainer.trailingAnchor)
- ])
-
- mapView.layer.cornerRadius = 6
- mapView.isZoomEnabled = true
- mapView.isScrollEnabled = false
- mapView.isUserInteractionEnabled = false
- mapView.addAnnotation(annotation)
- mapView.setRegion(MKCoordinateRegion(center: annotation.coordinate, latitudinalMeters: 500, longitudinalMeters: 500), animated: false)
- }
+ let mapView = MKMapView()
+ self.mapView = mapView
+ self.mapContainer.addSubview(mapView)
+
+ mapView.translatesAutoresizingMaskIntoConstraints = false
+ NSLayoutConstraint.activate([
+ mapView.topAnchor.constraint(equalTo: self.mapContainer.topAnchor),
+ mapView.bottomAnchor.constraint(equalTo: self.mapContainer.bottomAnchor),
+ mapView.leadingAnchor.constraint(equalTo: self.mapContainer.leadingAnchor),
+ mapView.trailingAnchor.constraint(equalTo: self.mapContainer.trailingAnchor)
+ ])
+
+ mapView.layer.cornerRadius = 6
+ mapView.isZoomEnabled = true
+ mapView.isScrollEnabled = false
+ mapView.isUserInteractionEnabled = false
+ mapView.addAnnotation(annotation)
+ mapView.setRegion(MKCoordinateRegion(center: annotation.coordinate, latitudinalMeters: 500, longitudinalMeters: 500), animated: false)
}
// Size
@@ -156,7 +157,7 @@ class NCViewerMediaDetailView: UIView {
}
// Message
- if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && !CCUtility.fileProviderStorageExists(metadata) && metadata.session == "" {
+ if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && !CCUtility.fileProviderStorageExists(metadata) && metadata.session.isEmpty {
messageButton.setTitle(NSLocalizedString("_try_download_full_resolution_", comment: ""), for: .normal)
messageButton.isHidden = false
} else {
@@ -188,23 +189,22 @@ class NCViewerMediaDetailView: UIView {
@IBAction func touchLocation(_ sender: Any) {
- if latitude != -1 && latitude != 0 && longitude != -1 && longitude != 0 {
-
- let latitude: CLLocationDegrees = self.latitude
- let longitude: CLLocationDegrees = self.longitude
-
- let regionDistance: CLLocationDistance = 10000
- let coordinates = CLLocationCoordinate2DMake(latitude, longitude)
- let regionSpan = MKCoordinateRegion(center: coordinates, latitudinalMeters: regionDistance, longitudinalMeters: regionDistance)
- let options = [
- MKLaunchOptionsMapCenterKey: NSValue(mkCoordinate: regionSpan.center),
- MKLaunchOptionsMapSpanKey: NSValue(mkCoordinateSpan: regionSpan.span)
- ]
- let placemark = MKPlacemark(coordinate: coordinates, addressDictionary: nil)
- let mapItem = MKMapItem(placemark: placemark)
- mapItem.name = location
- mapItem.openInMaps(launchOptions: options)
- }
+ guard latitude != -1, latitude != 0, longitude != -1, longitude != 0 else { return }
+
+ let latitude: CLLocationDegrees = self.latitude
+ let longitude: CLLocationDegrees = self.longitude
+
+ let regionDistance: CLLocationDistance = 10000
+ let coordinates = CLLocationCoordinate2DMake(latitude, longitude)
+ let regionSpan = MKCoordinateRegion(center: coordinates, latitudinalMeters: regionDistance, longitudinalMeters: regionDistance)
+ let options = [
+ MKLaunchOptionsMapCenterKey: NSValue(mkCoordinate: regionSpan.center),
+ MKLaunchOptionsMapSpanKey: NSValue(mkCoordinateSpan: regionSpan.span)
+ ]
+ let placemark = MKPlacemark(coordinate: coordinates, addressDictionary: nil)
+ let mapItem = MKMapItem(placemark: placemark)
+ mapItem.name = location
+ mapItem.openInMaps(launchOptions: options)
}
@IBAction func touchFavorite(_ sender: Any) {
@@ -212,12 +212,6 @@ class NCViewerMediaDetailView: UIView {
}
@IBAction func touchMessage(_ sender: Any) {
-
delegate?.downloadFullResolution()
}
-
- // MARK: -
- func secondsToHoursMinutesSeconds (seconds: Int) -> (Int, Int, Int) {
- return (seconds / 3600, (seconds % 3600) / 60, (seconds % 3600) % 60)
- }
}
diff --git a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.storyboard b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.storyboard
index 8e3d04ebb..329daf6cc 100644
--- a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.storyboard
+++ b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.storyboard
@@ -4,7 +4,6 @@
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
- <capability name="Image references" minToolsVersion="12.0"/>
<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"/>
@@ -109,6 +108,10 @@
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dJP-ZX-iug">
<rect key="frame" x="15" y="150" width="384" height="222"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <gestureRecognizers/>
+ <connections>
+ <outletCollection property="gestureRecognizers" destination="fvW-pC-4g1" appends="YES" id="gVL-xL-CmY"/>
+ </connections>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="size" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WXS-Lw-DkI">
<rect key="frame" x="15" y="36" width="80" height="16"/>
@@ -242,159 +245,6 @@
<outlet property="sizeValue" destination="XLb-0a-du9" id="9jm-Ku-sgt"/>
</connections>
</view>
- <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dgJ-dQ-lSp" userLabel="Player Top Tool Bar">
- <rect key="frame" x="299" y="10" width="100" height="45"/>
- <subviews>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9aW-Pg-83x" userLabel="Button Player Top Tool Bar">
- <rect key="frame" x="0.0" y="0.0" width="100" height="45"/>
- <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
- <connections>
- <action selector="buttonPlayerTopToolBarTouchInside:" destination="sBp-t2-eFh" eventType="touchUpInside" id="Afs-Nt-FaQ"/>
- </connections>
- </button>
- <button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8AB-hx-yqN" userLabel="Mute Button">
- <rect key="frame" x="60" y="10" width="25" height="25"/>
- <constraints>
- <constraint firstAttribute="width" constant="25" id="6yU-23-dkA"/>
- <constraint firstAttribute="height" constant="25" id="hBk-Ku-BAd"/>
- </constraints>
- <state key="normal" image="audioOn"/>
- <connections>
- <action selector="setMute:" destination="sBp-t2-eFh" eventType="touchUpInside" id="cVl-BA-mPJ"/>
- </connections>
- </button>
- <button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="NwE-zQ-Y5D" userLabel="Mute Button">
- <rect key="frame" x="15" y="10" width="25" height="25"/>
- <constraints>
- <constraint firstAttribute="width" constant="25" id="CaQ-c0-MES"/>
- <constraint firstAttribute="height" constant="25" id="N06-qe-ZVY"/>
- </constraints>
- <state key="normal" image="pip.enter" catalog="system"/>
- <connections>
- <action selector="setPip:" destination="sBp-t2-eFh" eventType="touchUpInside" id="svR-8R-DQY"/>
- </connections>
- </button>
- </subviews>
- <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- <constraints>
- <constraint firstAttribute="trailing" secondItem="9aW-Pg-83x" secondAttribute="trailing" id="8db-gr-hzG"/>
- <constraint firstItem="NwE-zQ-Y5D" firstAttribute="centerY" secondItem="dgJ-dQ-lSp" secondAttribute="centerY" id="Ad6-Aj-hvc"/>
- <constraint firstAttribute="bottom" secondItem="9aW-Pg-83x" secondAttribute="bottom" id="B8A-Zh-HYL"/>
- <constraint firstAttribute="width" constant="100" id="LTs-QZ-nVw"/>
- <constraint firstAttribute="trailing" secondItem="8AB-hx-yqN" secondAttribute="trailing" constant="15" id="bQK-xA-Jyu"/>
- <constraint firstItem="NwE-zQ-Y5D" firstAttribute="leading" secondItem="dgJ-dQ-lSp" secondAttribute="leading" constant="15" id="cZY-tl-BOh"/>
- <constraint firstItem="9aW-Pg-83x" firstAttribute="leading" secondItem="dgJ-dQ-lSp" secondAttribute="leading" id="clL-y7-JuR"/>
- <constraint firstItem="9aW-Pg-83x" firstAttribute="top" secondItem="dgJ-dQ-lSp" secondAttribute="top" id="jQP-bV-BQ9"/>
- <constraint firstItem="8AB-hx-yqN" firstAttribute="centerY" secondItem="dgJ-dQ-lSp" secondAttribute="centerY" id="uNT-D4-mK3"/>
- <constraint firstAttribute="height" constant="45" id="xf9-B5-HMs"/>
- </constraints>
- </view>
- <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sBp-t2-eFh" customClass="NCPlayerToolBar" customModule="Nextcloud" customModuleProvider="target">
- <rect key="frame" x="15" y="661" width="384" height="65"/>
- <subviews>
- <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="a0D-B0-eGX" userLabel="Button Player Tool Bar">
- <rect key="frame" x="0.0" y="0.0" width="384" height="65"/>
- <connections>
- <action selector="buttonPlayerToolBarTouchInside:" destination="sBp-t2-eFh" eventType="touchUpInside" id="hyl-lR-OGD"/>
- </connections>
- </button>
- <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Z2D-bl-6Qu" userLabel="Container play">
- <rect key="frame" x="0.0" y="0.0" width="115.33333333333333" height="65"/>
- <subviews>
- <button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Isy-sX-Gji">
- <rect key="frame" x="3" y="12.666666666666629" width="40" height="40"/>
- <constraints>
- <constraint firstAttribute="width" constant="40" id="COm-r2-ubw"/>
- <constraint firstAttribute="height" constant="40" id="mbb-ql-zCc"/>
- </constraints>
- <state key="normal" image="gobackward.10" catalog="system"/>
- <connections>
- <action selector="backButtonSec:" destination="sBp-t2-eFh" eventType="touchUpInside" id="Q46-Tp-inF"/>
- </connections>
- </button>
- <button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="x3E-b2-obf">
- <rect key="frame" x="37.666666666666629" y="12.666666666666629" width="40" height="40"/>
- <constraints>
- <constraint firstAttribute="width" constant="40" id="Cmv-LX-Phg"/>
- <constraint firstAttribute="height" constant="40" id="djE-Ml-YD0"/>
- </constraints>
- <state key="normal">
- <imageReference key="image" image="play.fill" catalog="system" symbolScale="default"/>
- <preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="default"/>
- </state>
- <connections>
- <action selector="playerPause:" destination="sBp-t2-eFh" eventType="touchUpInside" id="pRl-bT-hpi"/>
- </connections>
- </button>
- <button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="F9L-PP-AbM">
- <rect key="frame" x="72" y="12.666666666666629" width="40" height="40"/>
- <constraints>
- <constraint firstAttribute="width" constant="40" id="hlL-XQ-OLa"/>
- <constraint firstAttribute="height" constant="40" id="vEe-Fb-a9N"/>
- </constraints>
- <state key="normal" image="goforward.10" catalog="system"/>
- <connections>
- <action selector="forwardButtonSec:" destination="sBp-t2-eFh" eventType="touchUpInside" id="QPi-TQ-rNF"/>
- </connections>
- </button>
- </subviews>
- <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- <constraints>
- <constraint firstItem="F9L-PP-AbM" firstAttribute="centerY" secondItem="Z2D-bl-6Qu" secondAttribute="centerY" id="Hb6-zo-b2N"/>
- <constraint firstItem="x3E-b2-obf" firstAttribute="centerX" secondItem="Z2D-bl-6Qu" secondAttribute="centerX" id="Hj0-C7-K75"/>
- <constraint firstItem="F9L-PP-AbM" firstAttribute="centerX" secondItem="Z2D-bl-6Qu" secondAttribute="centerX" multiplier="1.6" id="a8O-oF-jJM"/>
- <constraint firstItem="Isy-sX-Gji" firstAttribute="centerX" secondItem="Z2D-bl-6Qu" secondAttribute="centerX" multiplier="0.4" id="mLO-jA-XH6"/>
- <constraint firstItem="Isy-sX-Gji" firstAttribute="centerY" secondItem="Z2D-bl-6Qu" secondAttribute="centerY" id="ngz-yI-ozW"/>
- <constraint firstItem="x3E-b2-obf" firstAttribute="centerY" secondItem="Z2D-bl-6Qu" secondAttribute="centerY" id="qMZ-ZT-IWE"/>
- </constraints>
- </view>
- <slider opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="SR4-e8-1hC">
- <rect key="frame" x="118.33333333333331" y="17.666666666666629" width="257.66666666666663" height="31"/>
- </slider>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="99:99:99" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="OUD-HH-cXH">
- <rect key="frame" x="328.66666666666669" y="47.666666666666629" width="45.333333333333314" height="12"/>
- <fontDescription key="fontDescription" type="system" pointSize="10"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="00:00:00" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kVv-X4-6SK">
- <rect key="frame" x="120.33333333333331" y="47.666666666666629" width="45" height="12"/>
- <fontDescription key="fontDescription" type="system" pointSize="10"/>
- <nil key="textColor"/>
- <nil key="highlightedColor"/>
- </label>
- </subviews>
- <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
- <constraints>
- <constraint firstItem="Z2D-bl-6Qu" firstAttribute="width" secondItem="sBp-t2-eFh" secondAttribute="width" multiplier="0.3" id="13g-iK-lwr"/>
- <constraint firstItem="kVv-X4-6SK" firstAttribute="leading" secondItem="SR4-e8-1hC" secondAttribute="leading" id="5hb-O9-gEt"/>
- <constraint firstItem="SR4-e8-1hC" firstAttribute="leading" secondItem="Z2D-bl-6Qu" secondAttribute="trailing" constant="5" id="6He-ZU-Vwa"/>
- <constraint firstItem="Z2D-bl-6Qu" firstAttribute="height" secondItem="sBp-t2-eFh" secondAttribute="height" id="AbA-kH-vt3"/>
- <constraint firstAttribute="height" constant="65" id="EyI-HW-pHA"/>
- <constraint firstItem="SR4-e8-1hC" firstAttribute="centerY" secondItem="sBp-t2-eFh" secondAttribute="centerY" id="L8n-9C-y6b"/>
- <constraint firstItem="a0D-B0-eGX" firstAttribute="leading" secondItem="sBp-t2-eFh" secondAttribute="leading" id="OIL-1t-uuh"/>
- <constraint firstAttribute="trailing" secondItem="SR4-e8-1hC" secondAttribute="trailing" constant="10" id="Q3r-ex-Cpf"/>
- <constraint firstAttribute="bottom" secondItem="a0D-B0-eGX" secondAttribute="bottom" id="a3T-pV-xrr"/>
- <constraint firstItem="Z2D-bl-6Qu" firstAttribute="centerY" secondItem="sBp-t2-eFh" secondAttribute="centerY" id="gdD-MC-K1m"/>
- <constraint firstItem="a0D-B0-eGX" firstAttribute="top" secondItem="sBp-t2-eFh" secondAttribute="top" id="itu-re-FU4"/>
- <constraint firstAttribute="trailing" secondItem="OUD-HH-cXH" secondAttribute="trailing" constant="10" id="j5v-RG-0JI"/>
- <constraint firstItem="Z2D-bl-6Qu" firstAttribute="leading" secondItem="sBp-t2-eFh" secondAttribute="leading" id="jHq-yM-afK"/>
- <constraint firstItem="kVv-X4-6SK" firstAttribute="top" secondItem="SR4-e8-1hC" secondAttribute="bottom" id="l6a-l5-ZvL"/>
- <constraint firstAttribute="trailing" secondItem="a0D-B0-eGX" secondAttribute="trailing" id="lbh-DN-SZF"/>
- <constraint firstItem="OUD-HH-cXH" firstAttribute="top" secondItem="SR4-e8-1hC" secondAttribute="bottom" id="wwk-tz-5dj"/>
- </constraints>
- <connections>
- <outlet property="backButton" destination="Isy-sX-Gji" id="RBh-0O-yAN"/>
- <outlet property="forwardButton" destination="F9L-PP-AbM" id="cc0-4F-r5v"/>
- <outlet property="labelCurrentTime" destination="kVv-X4-6SK" id="vyf-Bb-TPL"/>
- <outlet property="labelLeftTime" destination="OUD-HH-cXH" id="MjW-XN-Uer"/>
- <outlet property="muteButton" destination="8AB-hx-yqN" id="9zQ-k7-auv"/>
- <outlet property="pipButton" destination="NwE-zQ-Y5D" id="veJ-QD-fOd"/>
- <outlet property="playButton" destination="x3E-b2-obf" id="0Nw-L4-W7M"/>
- <outlet property="playbackSlider" destination="SR4-e8-1hC" id="Khx-Oe-NEQ"/>
- <outlet property="playerTopToolBarView" destination="dgJ-dQ-lSp" id="22g-Yn-k5r"/>
- </connections>
- </view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
@@ -413,19 +263,14 @@
<viewLayoutGuide key="safeArea" id="Yo6-7W-moG"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
- <constraint firstItem="Yo6-7W-moG" firstAttribute="trailing" secondItem="dgJ-dQ-lSp" secondAttribute="trailing" constant="15" id="15m-hD-wYt"/>
<constraint firstAttribute="bottom" secondItem="CdQ-LC-Trx" secondAttribute="bottom" id="4qB-8y-OcG"/>
<constraint firstAttribute="trailing" secondItem="CdQ-LC-Trx" secondAttribute="trailing" id="IwE-oE-d3Y"/>
- <constraint firstItem="Yo6-7W-moG" firstAttribute="bottom" secondItem="sBp-t2-eFh" secondAttribute="bottom" constant="10" id="QHF-av-zeT"/>
- <constraint firstItem="Yo6-7W-moG" firstAttribute="trailing" secondItem="sBp-t2-eFh" secondAttribute="trailing" constant="15" id="TCr-e0-gnG"/>
<constraint firstItem="2AU-85-K8y" firstAttribute="leading" secondItem="Yo6-7W-moG" secondAttribute="leading" constant="10" id="X10-OG-EKg"/>
<constraint firstItem="Yo6-7W-moG" firstAttribute="top" secondItem="2AU-85-K8y" secondAttribute="top" constant="-10" id="avO-83-uMQ"/>
<constraint firstItem="Yo6-7W-moG" firstAttribute="bottom" secondItem="P8R-4f-zAl" secondAttribute="top" constant="400" id="bor-cg-Alz"/>
<constraint firstItem="P8R-4f-zAl" firstAttribute="leading" secondItem="Yo6-7W-moG" secondAttribute="leading" id="dly-i5-fPW"/>
- <constraint firstItem="dgJ-dQ-lSp" firstAttribute="top" secondItem="Yo6-7W-moG" secondAttribute="top" constant="10" id="g7l-5Z-sJj"/>
<constraint firstItem="CdQ-LC-Trx" firstAttribute="leading" secondItem="fIE-H6-KKc" secondAttribute="leading" id="g8C-2m-KkX"/>
<constraint firstItem="CdQ-LC-Trx" firstAttribute="top" secondItem="fIE-H6-KKc" secondAttribute="top" id="hcQ-lB-JwU"/>
- <constraint firstItem="sBp-t2-eFh" firstAttribute="leading" secondItem="Yo6-7W-moG" secondAttribute="leading" constant="15" id="hwP-QY-nRI"/>
<constraint firstItem="Yo6-7W-moG" firstAttribute="trailing" secondItem="P8R-4f-zAl" secondAttribute="trailing" id="jf2-Nv-gFi"/>
</constraints>
</view>
@@ -436,24 +281,23 @@
<outlet property="imageVideoContainer" destination="kPV-JM-UnM" id="2pA-VW-FuK"/>
<outlet property="imageViewBottomConstraint" destination="vEd-X2-yGs" id="wp3-67-aZ2"/>
<outlet property="imageViewTopConstraint" destination="tdo-XY-uqv" id="AM2-tz-fSt"/>
- <outlet property="playerToolBar" destination="sBp-t2-eFh" id="E24-0a-bN6"/>
<outlet property="scrollView" destination="CdQ-LC-Trx" id="3np-FR-s39"/>
<outlet property="statusLabel" destination="DAi-gz-qGP" id="zZH-1B-HiI"/>
<outlet property="statusViewImage" destination="2AU-85-K8y" id="22h-Ec-bj0"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="fbE-Jv-mLH" userLabel="First Responder" sceneMemberID="firstResponder"/>
+ <tapGestureRecognizer id="fvW-pC-4g1">
+ <connections>
+ <action selector="touchLocation:" destination="P8R-4f-zAl" id="qyd-d2-RyB"/>
+ </connections>
+ </tapGestureRecognizer>
</objects>
<point key="canvasLocation" x="4547.826086956522" y="776.9021739130435"/>
</scene>
</scenes>
<resources>
- <image name="audioOn" width="28" height="28"/>
- <image name="gobackward.10" catalog="system" width="121" height="128"/>
- <image name="goforward.10" catalog="system" width="121" height="128"/>
<image name="networkInProgress" width="300" height="300"/>
- <image name="pip.enter" catalog="system" width="128" height="96"/>
- <image name="play.fill" catalog="system" width="116" height="128"/>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
diff --git a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.swift b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.swift
index 5a304f6ea..253073658 100644
--- a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.swift
+++ b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.swift
@@ -44,6 +44,7 @@ class NCViewerMediaPage: UIViewController {
}
var metadatas: [tableMetadata] = []
+ var modifiedOcId: [String] = []
var currentIndex = 0
var nextIndex: Int?
var ncplayerLivePhoto: NCPlayer?
@@ -96,6 +97,8 @@ 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(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)
@@ -104,24 +107,24 @@ class NCViewerMediaPage: UIViewController {
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)
- // Clear
if let ncplayer = currentViewController.ncplayer, ncplayer.isPlay() {
ncplayer.playerPause()
ncplayer.saveCurrentTime()
}
- currentViewController.playerToolBar.stopTimerAutoHide()
+ currentViewController.playerToolBar?.stopTimerAutoHide()
clearCommandCenter()
metadatas.removeAll()
ncplayerLivePhoto = nil
-
- #if MFFFLIB
- MFFF.shared.dismissMessage()
- #endif
-
+
// 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)
@@ -130,6 +133,8 @@ 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.notificationCenterUploadedFile), object: nil)
+
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterHidePlayerToolBar), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterShowPlayerToolBar), object: nil)
@@ -147,6 +152,10 @@ class NCViewerMediaPage: UIViewController {
}
}
+ override var prefersHomeIndicatorAutoHidden: Bool {
+ return currentScreenMode == .full
+ }
+
// MARK: -
func getViewerMedia(index: Int, metadata: tableMetadata) -> NCViewerMedia {
@@ -180,7 +189,7 @@ class NCViewerMediaPage: UIViewController {
progressView.isHidden = false
if !currentViewController.detailView.isShow() {
- currentViewController.playerToolBar.show(enableTimerAutoHide: enableTimerAutoHide)
+ currentViewController.playerToolBar?.show(enableTimerAutoHide: enableTimerAutoHide)
}
NCUtility.shared.colorNavigationController(navigationController, backgroundColor: NCBrandColor.shared.systemBackground, titleColor: NCBrandColor.shared.label, tintColor: nil, withoutShadow: false)
@@ -192,7 +201,7 @@ class NCViewerMediaPage: UIViewController {
navigationController?.setNavigationBarHidden(true, animated: true)
progressView.isHidden = true
- currentViewController.playerToolBar.hide()
+ currentViewController.playerToolBar?.hide()
view.backgroundColor = .black
textColor = .white
@@ -205,6 +214,7 @@ class NCViewerMediaPage: UIViewController {
}
setNeedsStatusBarAppearanceUpdate()
+ setNeedsUpdateOfHomeIndicatorAutoHidden()
currentViewController.reloadDetail()
}
@@ -229,6 +239,22 @@ class NCViewerMediaPage: UIViewController {
}
}
+ @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)
+ }
+ }
+ }
+ }
+ }
+
@objc func deleteFile(_ notification: NSNotification) {
if let userInfo = notification.userInfo as NSDictionary? {
@@ -344,7 +370,7 @@ class NCViewerMediaPage: UIViewController {
skipForwardCommand = MPRemoteCommandCenter.shared().skipForwardCommand.addTarget { event in
let seconds = Float64((event as! MPSkipIntervalCommandEvent).interval)
- self.currentViewController.playerToolBar.skip(seconds: seconds)
+ self.currentViewController.playerToolBar?.skip(seconds: seconds)
return.success
}
@@ -352,7 +378,7 @@ class NCViewerMediaPage: UIViewController {
skipBackwardCommand = MPRemoteCommandCenter.shared().skipBackwardCommand.addTarget { event in
let seconds = Float64((event as! MPSkipIntervalCommandEvent).interval)
- self.currentViewController.playerToolBar.skip(seconds: -seconds)
+ self.currentViewController.playerToolBar?.skip(seconds: -seconds)
return.success
}
}
@@ -444,16 +470,12 @@ extension NCViewerMediaPage: UIPageViewControllerDelegate, UIPageViewControllerD
direction = .reverse
}
- currentViewController.ncplayer?.deactivateObserver()
-
let viewerMedia = getViewerMedia(index: currentIndex, metadata: metadatas[currentIndex])
pageViewController.setViewControllers([viewerMedia], direction: direction, animated: true, completion: nil)
}
func reloadCurrentPage() {
-
- currentViewController.ncplayer?.deactivateObserver()
-
+
let viewerMedia = getViewerMedia(index: currentIndex, metadata: metadatas[currentIndex])
viewerMedia.autoPlay = false
pageViewController.setViewControllers([viewerMedia], direction: .forward, animated: false, completion: nil)
@@ -463,8 +485,6 @@ extension NCViewerMediaPage: UIPageViewControllerDelegate, UIPageViewControllerD
currentIndex = index
- currentViewController.ncplayer?.deactivateObserver()
-
let viewerMedia = getViewerMedia(index: currentIndex, metadata: metadatas[currentIndex])
viewerMedia.autoPlay = autoPlay
pageViewController.setViewControllers([viewerMedia], direction: direction, animated: true, completion: nil)
@@ -474,15 +494,15 @@ extension NCViewerMediaPage: UIPageViewControllerDelegate, UIPageViewControllerD
if currentIndex == 0 { return nil }
- let viewerMedia = getViewerMedia(index: currentIndex-1, metadata: metadatas[currentIndex-1])
+ let viewerMedia = getViewerMedia(index: currentIndex - 1, metadata: metadatas[currentIndex - 1])
return viewerMedia
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
- if currentIndex == metadatas.count-1 { return nil }
+ if currentIndex == metadatas.count - 1 { return nil }
- let viewerMedia = getViewerMedia(index: currentIndex+1, metadata: metadatas[currentIndex+1])
+ let viewerMedia = getViewerMedia(index: currentIndex + 1, metadata: metadatas[currentIndex + 1])
return viewerMedia
}
@@ -587,8 +607,11 @@ extension NCViewerMediaPage: UIGestureRecognizerDelegate {
AudioServicesPlaySystemSound(1519) // peek feedback
- if let url = NCKTVHTTPCache.shared.getVideoURL(metadata: metadata) {
- self.ncplayerLivePhoto = NCPlayer.init(url: url, autoPlay: true, imageVideoContainer: self.currentViewController.imageVideoContainer, playerToolBar: nil, metadata: metadata, detailView: nil, viewController: self)
+ let urlVideo = NCKTVHTTPCache.shared.getVideoURL(metadata: metadata)
+
+ if let url = urlVideo.url {
+ self.ncplayerLivePhoto = NCPlayer.init(url: url, autoPlay: true, isProxy: urlVideo.isProxy, imageVideoContainer: self.currentViewController.imageVideoContainer, playerToolBar: nil, metadata: metadata, detailView: nil, viewController: self)
+ self.ncplayerLivePhoto?.openAVPlayer()
}
}
diff --git a/iOSClient/Viewer/NCViewerNextcloudText/NCViewerNextcloudText.swift b/iOSClient/Viewer/NCViewerNextcloudText/NCViewerNextcloudText.swift
index a567e3ed2..f44cd3018 100644
--- a/iOSClient/Viewer/NCViewerNextcloudText/NCViewerNextcloudText.swift
+++ b/iOSClient/Viewer/NCViewerNextcloudText/NCViewerNextcloudText.swift
@@ -72,9 +72,9 @@ class NCViewerNextcloudText: UIViewController, WKNavigationDelegate, WKScriptMes
if editor == NCGlobal.shared.editorOnlyoffice {
webView.customUserAgent = NCUtility.shared.getCustomUserAgentOnlyOffice()
- } else {
- webView.customUserAgent = CCUtility.getUserAgent()
- }
+ } else if editor == NCGlobal.shared.editorText {
+ webView.customUserAgent = NCUtility.shared.getCustomUserAgentNCText()
+ } // else: use default
webView.load(request)
}
diff --git a/iOSClient/Viewer/NCViewerPDF/NCViewerPDF.swift b/iOSClient/Viewer/NCViewerPDF/NCViewerPDF.swift
index c0884fa77..a188fcb93 100644
--- a/iOSClient/Viewer/NCViewerPDF/NCViewerPDF.swift
+++ b/iOSClient/Viewer/NCViewerPDF/NCViewerPDF.swift
@@ -23,21 +23,34 @@
import UIKit
import PDFKit
+import EasyTipView
class NCViewerPDF: UIViewController, NCViewerPDFSearchDelegate {
- let appDelegate = UIApplication.shared.delegate as! AppDelegate
var metadata = tableMetadata()
var imageIcon: UIImage?
+ private var filePath = ""
+
private var pdfView = PDFView()
- private var thumbnailViewHeight: CGFloat = 40
+ private var pdfThumbnailScrollView = UIScrollView()
private var pdfThumbnailView = PDFThumbnailView()
private var pdfDocument: PDFDocument?
private let pageView = UIView()
private let pageViewLabel = UILabel()
+ private var tipView: EasyTipView?
+
+ private let thumbnailViewHeight: CGFloat = 70
+ private let thumbnailViewWidth: CGFloat = 80
+ private let thumbnailPadding: CGFloat = 2
+ private let animateDuration: TimeInterval = 0.3
+
+ private var defaultBackgroundColor: UIColor = .clear
+
+ private var pdfThumbnailScrollViewTopAnchor: NSLayoutConstraint?
+ private var pdfThumbnailScrollViewTrailingAnchor: NSLayoutConstraint?
+ private var pdfThumbnailScrollViewWidthAnchor: NSLayoutConstraint?
private var pageViewWidthAnchor: NSLayoutConstraint?
- private var filePath = ""
// MARK: - View Life Cycle
@@ -48,78 +61,131 @@ class NCViewerPDF: UIViewController, NCViewerPDFSearchDelegate {
override func viewDidLoad() {
filePath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!
-
- pdfView = PDFView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height))
pdfDocument = PDFDocument(url: URL(fileURLWithPath: filePath))
+ let pageCount = CGFloat(pdfDocument?.pageCount ?? 0)
+ if #available(iOS 13.0, *) {
+ defaultBackgroundColor = pdfView.backgroundColor
+ } else {
+ defaultBackgroundColor = .lightGray
+ }
+ view.backgroundColor = defaultBackgroundColor
+
+ navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "more")!.image(color: NCBrandColor.shared.label, size: 25), style: .plain, target: self, action: #selector(self.openMenuMore))
+ navigationItem.title = metadata.fileNameView
+ // PDF VIEW
+
+ if UIDevice.current.userInterfaceIdiom == .phone {
+ pdfView = PDFView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height))
+ } else {
+ pdfView = PDFView(frame: CGRect(x: 0, y: 0, width: view.frame.width-thumbnailViewWidth, height: view.frame.height))
+ }
+ pdfView.autoresizingMask = [.flexibleWidth, .flexibleHeight, .flexibleTopMargin, .flexibleLeftMargin]
pdfView.document = pdfDocument
- pdfView.backgroundColor = NCBrandColor.shared.systemBackground
- pdfView.displayMode = .singlePageContinuous
pdfView.autoScales = true
- pdfView.displayDirection = CCUtility.getPDFDisplayDirection()
- pdfView.autoresizingMask = [.flexibleWidth, .flexibleHeight, .flexibleTopMargin, .flexibleBottomMargin]
- pdfView.usePageViewController(true, withViewOptions: nil)
-
+ pdfView.displayMode = .singlePageContinuous
+ pdfView.displayDirection = .vertical
+ pdfView.maxScaleFactor = 4.0
+ pdfView.minScaleFactor = pdfView.scaleFactorForSizeToFit
view.addSubview(pdfView)
+ // PDF THUMBNAIL
+
+ pdfThumbnailScrollView.translatesAutoresizingMaskIntoConstraints = false
+ pdfThumbnailScrollView.backgroundColor = defaultBackgroundColor
+ pdfThumbnailScrollView.showsVerticalScrollIndicator = false
+ view.addSubview(pdfThumbnailScrollView)
+
+ pdfThumbnailScrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
+ pdfThumbnailScrollViewTopAnchor = pdfThumbnailScrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)
+ pdfThumbnailScrollViewTopAnchor?.isActive = true
+ pdfThumbnailScrollViewTrailingAnchor = pdfThumbnailScrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
+ pdfThumbnailScrollViewTrailingAnchor?.isActive = true
+ pdfThumbnailScrollViewWidthAnchor = pdfThumbnailScrollView.widthAnchor.constraint(equalToConstant: thumbnailViewWidth)
+ pdfThumbnailScrollViewWidthAnchor?.isActive = true
+
pdfThumbnailView.translatesAutoresizingMaskIntoConstraints = false
pdfThumbnailView.pdfView = pdfView
- pdfThumbnailView.layoutMode = .horizontal
- pdfThumbnailView.thumbnailSize = CGSize(width: 40, height: thumbnailViewHeight)
+ pdfThumbnailView.layoutMode = .vertical
+ pdfThumbnailView.thumbnailSize = CGSize(width: thumbnailViewHeight, height: thumbnailViewHeight)
pdfThumbnailView.backgroundColor = .clear
- // pdfThumbnailView.layer.shadowOffset.height = -5
- // pdfThumbnailView.layer.shadowOpacity = 0.25
-
- view.addSubview(pdfThumbnailView)
-
- pdfThumbnailView.heightAnchor.constraint(equalToConstant: thumbnailViewHeight).isActive = true
- pdfThumbnailView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
- pdfThumbnailView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
- pdfThumbnailView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
+ if UIDevice.current.userInterfaceIdiom == .phone {
+ self.pdfThumbnailScrollView.isHidden = true
+ } else {
+ self.pdfThumbnailScrollView.isHidden = false
+ }
+ pdfThumbnailScrollView.addSubview(pdfThumbnailView)
+
+ NSLayoutConstraint.activate([
+ pdfThumbnailView.topAnchor.constraint(equalTo: pdfThumbnailScrollView.topAnchor),
+ pdfThumbnailView.bottomAnchor.constraint(equalTo: pdfThumbnailScrollView.bottomAnchor),
+ pdfThumbnailView.leadingAnchor.constraint(equalTo: pdfThumbnailScrollView.leadingAnchor),
+ pdfThumbnailView.leadingAnchor.constraint(equalTo: pdfThumbnailScrollView.trailingAnchor, constant: (UIApplication.shared.keyWindow?.safeAreaInsets.left ?? 0)),
+ pdfThumbnailView.widthAnchor.constraint(equalToConstant: thumbnailViewWidth)
+ ])
+ let contentViewCenterY = pdfThumbnailView.centerYAnchor.constraint(equalTo: pdfThumbnailScrollView.centerYAnchor)
+ contentViewCenterY.priority = .defaultLow
+ let contentViewHeight = pdfThumbnailView.heightAnchor.constraint(equalToConstant: CGFloat(pageCount * thumbnailViewHeight) + CGFloat(pageCount * thumbnailPadding) + 30)
+ contentViewHeight.priority = .defaultLow
+ NSLayoutConstraint.activate([
+ contentViewCenterY,
+ contentViewHeight
+ ])
+
+ // COUNTER PDF PAGE VIEW
pageView.translatesAutoresizingMaskIntoConstraints = false
pageView.layer.cornerRadius = 10
- pageView.backgroundColor = UIColor.gray.withAlphaComponent(0.3)
-
+ pageView.backgroundColor = NCBrandColor.shared.systemBackground.withAlphaComponent(
+ UIAccessibility.isReduceTransparencyEnabled ? 1 : 0.5
+ )
view.addSubview(pageView)
- pageView.heightAnchor.constraint(equalToConstant: 30).isActive = true
+ NSLayoutConstraint.activate([
+ pageView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10),
+ pageView.heightAnchor.constraint(equalToConstant: 30),
+ pageView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 10)
+ ])
pageViewWidthAnchor = pageView.widthAnchor.constraint(equalToConstant: 10)
pageViewWidthAnchor?.isActive = true
- pageView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 4).isActive = true
- pageView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 7).isActive = true
pageViewLabel.translatesAutoresizingMaskIntoConstraints = false
pageViewLabel.textAlignment = .center
- pageViewLabel.textColor = .gray
-
+ pageViewLabel.textColor = NCBrandColor.shared.label
pageView.addSubview(pageViewLabel)
- pageViewLabel.leftAnchor.constraint(equalTo: pageView.leftAnchor).isActive = true
- pageViewLabel.rightAnchor.constraint(equalTo: pageView.rightAnchor).isActive = true
- pageViewLabel.topAnchor.constraint(equalTo: pageView.topAnchor).isActive = true
- pageViewLabel.bottomAnchor.constraint(equalTo: pageView.bottomAnchor).isActive = true
+ NSLayoutConstraint.activate([
+ pageViewLabel.topAnchor.constraint(equalTo: pageView.topAnchor),
+ pageViewLabel.leftAnchor.constraint(equalTo: pageView.leftAnchor),
+ pageViewLabel.rightAnchor.constraint(equalTo: pageView.rightAnchor),
+ pageViewLabel.bottomAnchor.constraint(equalTo: pageView.bottomAnchor)
+ ])
- pdfView.backgroundColor = NCBrandColor.shared.systemBackground
- pdfView.layoutIfNeeded()
- handlePageChange()
+ // GESTURE
- let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTap(_:)))
- tapGesture.numberOfTapsRequired = 1
- pdfView.addGestureRecognizer(tapGesture)
+ let tapPdfView = UITapGestureRecognizer(target: self, action: #selector(tapPdfView))
+ tapPdfView.numberOfTapsRequired = 1
+ pdfView.addGestureRecognizer(tapPdfView)
// recognize single / double tap
for gesture in pdfView.gestureRecognizers! {
- tapGesture.require(toFail: gesture)
+ tapPdfView.require(toFail: gesture)
}
- }
- override func viewWillAppear(_ animated: Bool) {
- super.viewWillAppear(animated)
+ let swipePdfView = UISwipeGestureRecognizer(target: self, action: #selector(gestureClosePdfThumbnail))
+ swipePdfView.direction = .right
+ swipePdfView.delegate = self
+ pdfView.addGestureRecognizer(swipePdfView)
- appDelegate.activeViewController = self
+ let edgePdfView = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(gestureOpenPdfThumbnail))
+ edgePdfView.edges = .right
+ edgePdfView.delegate = self
+ pdfView.addGestureRecognizer(edgePdfView)
+
+ let swipePdfThumbnailScrollView = UISwipeGestureRecognizer(target: self, action: #selector(gestureClosePdfThumbnail))
+ swipePdfThumbnailScrollView.direction = .right
+ pdfThumbnailScrollView.addGestureRecognizer(swipePdfThumbnailScrollView)
- //
NotificationCenter.default.addObserver(self, selector: #selector(favoriteFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterFavoriteFile), object: nil)
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)
@@ -128,19 +194,62 @@ class NCViewerPDF: UIViewController, NCViewerPDFSearchDelegate {
NotificationCenter.default.addObserver(self, selector: #selector(viewUnload), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMenuDetailClose), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(searchText), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMenuSearchTextPDF), object: nil)
- NotificationCenter.default.addObserver(self, selector: #selector(direction(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMenuPDFDisplayDirection), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(goToPage), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMenuGotToPageInPDF), object: nil)
+
NotificationCenter.default.addObserver(self, selector: #selector(handlePageChange), name: Notification.Name.PDFViewPageChanged, object: nil)
- //
- navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "more")!.image(color: NCBrandColor.shared.label, size: 25), style: .plain, target: self, action: #selector(self.openMenuMore))
+ // Tip
+ if UIDevice.current.userInterfaceIdiom == .phone && !NCManageDatabase.shared.tipExists(NCGlobal.shared.tipNCViewerPDFThumbnail){
- navigationController?.navigationBar.prefersLargeTitles = true
- navigationItem.title = metadata.fileNameView
+ var preferences = EasyTipView.Preferences()
+ preferences.drawing.foregroundColor = .white
+ preferences.drawing.backgroundColor = NCBrandColor.shared.nextcloud
+ preferences.drawing.textAlignment = .left
+ preferences.drawing.arrowPosition = .right
+ preferences.drawing.cornerRadius = 10
+
+ preferences.positioning.bubbleInsets.right = UIApplication.shared.keyWindow?.safeAreaInsets.right ?? 0
+
+ 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_pdf_thumbnails_", comment: ""), preferences: preferences, delegate: self)
+ }
+
+ setConstraints()
+ handlePageChange()
+ }
+
+ override func viewDidAppear(_ animated: Bool) {
+ super.viewDidAppear(animated)
+
+ self.tipView?.show(forView: self.pdfThumbnailScrollView, withinSuperview: self.view)
+ }
+
+ @objc func viewUnload() {
+
+ navigationController?.popViewController(animated: true)
+ }
+
+ override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
+ super.viewWillTransition(to: size, with: coordinator)
+
+ coordinator.animate(alongsideTransition: { context in
+ if UIDevice.current.userInterfaceIdiom == .phone {
+ // Close
+ self.tipView?.dismiss()
+ self.pdfThumbnailScrollViewTrailingAnchor?.constant = self.thumbnailViewWidth + (UIApplication.shared.keyWindow?.safeAreaInsets.right ?? 0)
+ self.pdfThumbnailScrollView.isHidden = true
+ }
+ }, completion: { context in
+ self.setConstraints()
+ })
}
- override func viewWillDisappear(_ animated: Bool) {
- super.viewWillDisappear(animated)
+ deinit {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterFavoriteFile), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDeleteFile), object: nil)
@@ -150,17 +259,11 @@ class NCViewerPDF: UIViewController, NCViewerPDFSearchDelegate {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMenuDetailClose), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMenuSearchTextPDF), object: nil)
- NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMenuPDFDisplayDirection), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMenuGotToPageInPDF), object: nil)
NotificationCenter.default.removeObserver(self, name: Notification.Name.PDFViewPageChanged, object: nil)
}
- @objc func viewUnload() {
-
- navigationController?.popViewController(animated: true)
- }
-
// MARK: - NotificationCenter
@objc func uploadedFile(_ notification: NSNotification) {
@@ -234,17 +337,6 @@ class NCViewerPDF: UIViewController, NCViewerPDFSearchDelegate {
self.present(navigaionController, animated: true)
}
- @objc func direction(_ notification: NSNotification) {
-
- if let userInfo = notification.userInfo as NSDictionary? {
- if let direction = userInfo["direction"] as? PDFDisplayDirection {
- pdfView.displayDirection = direction
- CCUtility.setPDFDisplayDirection(direction)
- handlePageChange()
- }
- }
- }
-
@objc func goToPage() {
guard let pdfDocument = pdfView.document else { return }
@@ -270,72 +362,178 @@ class NCViewerPDF: UIViewController, NCViewerPDFSearchDelegate {
// MARK: - Action
@objc func openMenuMore() {
+
if imageIcon == nil { imageIcon = UIImage(named: "file_pdf") }
NCViewer.shared.toggleMenu(viewController: self, metadata: metadata, webView: false, imageIcon: imageIcon)
}
// MARK: - Gesture Recognizer
- @objc func didTap(_ recognizer: UITapGestureRecognizer) {
+ @objc func tapPdfView(_ recognizer: UITapGestureRecognizer) {
- if navigationController?.isNavigationBarHidden ?? false {
+ pdfThumbnailScrollViewTopAnchor?.isActive = false
- navigationController?.setNavigationBarHidden(false, animated: false)
- pdfThumbnailView.isHidden = false
- pdfView.backgroundColor = NCBrandColor.shared.systemBackground
+ if navigationController?.isNavigationBarHidden ?? false {
+ navigationController?.setNavigationBarHidden(false, animated: true)
+ pdfThumbnailScrollViewTopAnchor = pdfThumbnailScrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)
} else {
+ navigationController?.setNavigationBarHidden(true, animated: true)
+ pdfThumbnailScrollViewTopAnchor = pdfThumbnailScrollView.topAnchor.constraint(equalTo: view.topAnchor)
+ }
+
+ pdfThumbnailScrollViewTopAnchor?.isActive = true
+
+ handlePageChange()
+ }
- let point = recognizer.location(in: pdfView)
- if point.y > pdfView.frame.height - thumbnailViewHeight { return }
+ @objc func gestureOpenPdfThumbnail(_ recognizer: UIScreenEdgePanGestureRecognizer) {
- navigationController?.setNavigationBarHidden(true, animated: false)
- pdfThumbnailView.isHidden = true
- pdfView.backgroundColor = .black
+ if UIDevice.current.userInterfaceIdiom == .phone && self.pdfThumbnailScrollView.isHidden {
+ if let tipView = self.tipView {
+ tipView.dismiss()
+ NCManageDatabase.shared.addTip(NCGlobal.shared.tipNCViewerPDFThumbnail)
+ self.tipView = nil
+ }
+ self.pdfThumbnailScrollView.isHidden = false
+ self.pdfThumbnailScrollViewWidthAnchor?.constant = thumbnailViewWidth + (UIApplication.shared.keyWindow?.safeAreaInsets.right ?? 0)
+ UIView.animate(withDuration: animateDuration, animations: {
+ self.pdfThumbnailScrollViewTrailingAnchor?.constant = 0
+ self.view.layoutIfNeeded()
+ })
}
+ }
- handlePageChange()
+ @objc func gestureClosePdfThumbnail(_ recognizer: UIScreenEdgePanGestureRecognizer) {
+
+ if recognizer.state == .recognized && UIDevice.current.userInterfaceIdiom == .phone && !self.pdfThumbnailScrollView.isHidden {
+ UIView.animate(withDuration: animateDuration) {
+ self.pdfThumbnailScrollViewTrailingAnchor?.constant = self.thumbnailViewWidth + (UIApplication.shared.keyWindow?.safeAreaInsets.right ?? 0)
+ self.view.layoutIfNeeded()
+ } completion: { _ in
+ self.pdfThumbnailScrollView.isHidden = true
+ }
+ }
}
// MARK: -
+ func setConstraints() {
+
+ let widthThumbnail = thumbnailViewWidth + (UIApplication.shared.keyWindow?.safeAreaInsets.right ?? 0)
+
+ UIView.animate(withDuration: animateDuration, animations: {
+ if UIDevice.current.userInterfaceIdiom == .phone {
+ // Close
+ self.pdfThumbnailScrollView.isHidden = true
+ self.pdfThumbnailScrollViewTrailingAnchor?.constant = widthThumbnail
+ self.pdfThumbnailScrollViewWidthAnchor?.constant = widthThumbnail
+ } else {
+ // Open
+ self.pdfThumbnailScrollViewTrailingAnchor?.constant = 0
+ self.pdfThumbnailScrollViewWidthAnchor?.constant = widthThumbnail
+ }
+ self.view.layoutIfNeeded()
+ self.pdfView.autoScales = true
+ })
+ }
+
@objc func handlePageChange() {
guard let curPage = pdfView.currentPage?.pageRef?.pageNumber else { pageView.alpha = 0; return }
guard let totalPages = pdfView.document?.pageCount else { return }
+ let visibleRect = CGRect(x: pdfThumbnailScrollView.contentOffset.x, y: pdfThumbnailScrollView.contentOffset.y, width: pdfThumbnailScrollView.bounds.size.width, height: pdfThumbnailScrollView.bounds.size.height)
+ let centerPoint = CGPoint(x: visibleRect.size.width/2, y: visibleRect.size.height/2)
+ let currentPageY = CGFloat(curPage) * thumbnailViewHeight + CGFloat(curPage) * thumbnailPadding
+ var gotoY = currentPageY - centerPoint.y
+
+ let startY = visibleRect.origin.y < 0 ? 0 : (visibleRect.origin.y + thumbnailViewHeight)
+ let endY = visibleRect.origin.y + visibleRect.height
+
+ if currentPageY < startY {
+ if gotoY < 0 { gotoY = 0 }
+ pdfThumbnailScrollView.setContentOffset(CGPoint(x: 0, y: gotoY), animated: true)
+ } else if currentPageY > endY {
+ if gotoY > pdfThumbnailView.frame.height - visibleRect.height {
+ gotoY = pdfThumbnailView.frame.height - visibleRect.height
+ }
+ pdfThumbnailScrollView.setContentOffset(CGPoint(x: 0, y: gotoY), animated: true)
+ } else {
+ print("visible")
+ }
+
pageView.alpha = 1
pageViewLabel.text = String(curPage) + " " + NSLocalizedString("_of_", comment: "") + " " + String(totalPages)
pageViewWidthAnchor?.constant = pageViewLabel.intrinsicContentSize.width + 10
- UIView.animate(withDuration: 1.0, delay: 3.0, animations: {
+ UIView.animate(withDuration: 1.0, delay: 2.5, animations: {
self.pageView.alpha = 0
})
}
func searchPdfSelection(_ pdfSelection: PDFSelection) {
- pdfSelection.color = .yellow
- pdfView.currentSelection = pdfSelection
- pdfView.go(to: pdfSelection)
+ removeAllAnnotations()
+
+ pdfSelection.pages.forEach { page in
+ let highlight = PDFAnnotation(bounds: pdfSelection.bounds(for: page), forType: .highlight, withProperties: nil)
+ highlight.endLineStyle = .square
+ highlight.color = .yellow
+ page.addAnnotation(highlight)
+ }
+ if let page = pdfSelection.pages.first {
+ pdfView.go(to: page)
+ }
+ handlePageChange()
}
private func selectPage(with label: String) {
guard let pdf = pdfView.document else { return }
- if let pageNr = Int(label) {
- if pageNr > 0 && pageNr <= pdf.pageCount {
- if let page = pdf.page(at: pageNr - 1) {
- self.pdfView.go(to: page)
- }
- } else {
- let alertController = UIAlertController(title: NSLocalizedString("_invalid_page_", comment: ""),
- message: NSLocalizedString("_the_entered_page_number_doesn't_exist_", comment: ""),
- preferredStyle: .alert)
- alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: nil))
- self.present(alertController, animated: true, completion: nil)
- }
- }
- }
+ if let pageNr = Int(label) {
+ if pageNr > 0 && pageNr <= pdf.pageCount {
+ if let page = pdf.page(at: pageNr - 1) {
+ self.pdfView.go(to: page)
+ }
+ } else {
+ let alertController = UIAlertController(title: NSLocalizedString("_invalid_page_", comment: ""),
+ message: NSLocalizedString("_the_entered_page_number_doesn't_exist_", comment: ""),
+ preferredStyle: .alert)
+ alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: nil))
+ self.present(alertController, animated: true, completion: nil)
+ }
+ }
+ }
+
+ func removeAllAnnotations() {
+
+ guard let document = pdfDocument else { return }
+
+ for i in 0..<document.pageCount {
+ if let page = document.page(at: i) {
+ let annotations = page.annotations
+ for annotation in annotations {
+ page.removeAnnotation(annotation)
+ }
+ }
+ }
+ }
+}
+
+extension NCViewerPDF: UIGestureRecognizerDelegate {
+
+ func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
+ return true
+ }
+}
+
+extension NCViewerPDF: EasyTipViewDelegate {
+
+ func easyTipViewDidTap(_ tipView: EasyTipView) {
+ NCManageDatabase.shared.addTip(NCGlobal.shared.tipNCViewerPDFThumbnail)
+ }
+
+ func easyTipViewDidDismiss(_ tipView: EasyTipView) { }
}
diff --git a/iOSClient/Viewer/NCViewerPDF/NCViewerPDFSearch.swift b/iOSClient/Viewer/NCViewerPDF/NCViewerPDFSearch.swift
index d86c840c9..cda6cbf65 100644
--- a/iOSClient/Viewer/NCViewerPDF/NCViewerPDFSearch.swift
+++ b/iOSClient/Viewer/NCViewerPDF/NCViewerPDFSearch.swift
@@ -81,7 +81,8 @@ class NCViewerPDFSearch: UITableViewController, UISearchBarDelegate, PDFDocument
// }
let pdfPage = pdfSelection.pages.first
- cell.pageNumberLabel.text = NSLocalizedString("_scan_document_pdf_page_", comment: "") + ": " + (pdfPage?.label ?? "")
+ let pageNumber = pdfPage?.pageRef?.pageNumber ?? 0
+ cell.pageNumberLabel.text = NSLocalizedString("_scan_document_pdf_page_", comment: "") + ": " + String(pageNumber)
let extendSelection = pdfSelection.copy() as! PDFSelection
extendSelection.extend(atStart: 10)
diff --git a/iOSClient/Viewer/NCViewerQuickLook/NCViewerQuickLook.swift b/iOSClient/Viewer/NCViewerQuickLook/NCViewerQuickLook.swift
index 7a96388d9..cff53169d 100644
--- a/iOSClient/Viewer/NCViewerQuickLook/NCViewerQuickLook.swift
+++ b/iOSClient/Viewer/NCViewerQuickLook/NCViewerQuickLook.swift
@@ -4,8 +4,10 @@
//
// Created by Marino Faggiana on 03/05/2020.
// Copyright © 2020 Marino Faggiana. All rights reserved.
+// Copyright © 2022 Henrik Storch. All rights reserved.
//
// Author Marino Faggiana <marino.faggiana@nextcloud.com>
+// Author Henrik Storch <henrik.storch@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
@@ -27,26 +29,24 @@ import NCCommunication
@objc class NCViewerQuickLook: QLPreviewController {
- let appDelegate = UIApplication.shared.delegate as! AppDelegate
- var url: URL?
+ let url: URL
var previewItems: [PreviewItem] = []
- var editingMode: Bool
- enum saveModeType {
- case overwrite
- case copy
- case discard
- }
- var saveMode: saveModeType = .discard
+ var isEditingEnabled: Bool
var metadata: tableMetadata?
+ // if the document has any changes (annotations)
+ var hasChanges = false
+
+ // used to display the save alert
+ var parentVC: UIViewController?
+
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
- @objc init(with url: URL, editingMode: Bool, metadata: tableMetadata?) {
-
+ @objc init(with url: URL, isEditingEnabled: Bool, metadata: tableMetadata?) {
self.url = url
- self.editingMode = editingMode
+ self.isEditingEnabled = isEditingEnabled
if let metadata = metadata {
self.metadata = tableMetadata.init(value: metadata)
}
@@ -60,72 +60,50 @@ import NCCommunication
self.dataSource = self
self.delegate = self
self.currentPreviewItemIndex = 0
-
- self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissPreviewController))
}
override func viewDidLoad() {
super.viewDidLoad()
-
- if editingMode && metadata?.classFile == NCCommunicationCommon.typeClassFile.image.rawValue {
- Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { t in
- if self.navigationItem.rightBarButtonItems?.count ?? 0 > 1 || !(self.navigationController?.isToolbarHidden ?? false) {
- if #available(iOS 14.0, *) {
- if self.navigationItem.rightBarButtonItems?.count ?? 0 > 1 {
- if let buttonItem = self.navigationItem.rightBarButtonItems?.last {
- _ = buttonItem.target?.perform(buttonItem.action, with: buttonItem)
- }
- } else {
- if let buttonItem = self.navigationItem.rightBarButtonItems?.first {
- _ = buttonItem.target?.perform(buttonItem.action, with: buttonItem)
- }
- }
- } else {
- if let buttonItem = self.navigationItem.rightBarButtonItems?.filter({$0.customView != nil}).first?.customView as? UIButton {
- buttonItem.sendActions(for: .touchUpInside)
- }
- }
- t.invalidate()
- }
- })
- }
-
- if editingMode && metadata?.livePhoto == true {
- NCContentPresenter.shared.messageNotification("", description: "_message_disable_overwrite_livephoto_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorCharactersForbidden)
+ guard isEditingEnabled else { return }
+
+ if metadata?.livePhoto == true {
+ NCContentPresenter.shared.messageNotification(
+ "", description: "_message_disable_overwrite_livephoto_",
+ delay: NCGlobal.shared.dismissAfterSecond,
+ type: NCContentPresenter.messageType.info,
+ errorCode: NCGlobal.shared.errorCharactersForbidden)
}
}
- @objc func dismissPreviewController() {
-
- if editingMode {
-
- let alertController = UIAlertController(title: NSLocalizedString("_save_", comment: ""), message: "", preferredStyle: .alert)
-
- if metadata?.livePhoto == false {
- alertController.addAction(UIAlertAction(title: NSLocalizedString("_overwrite_original_", comment: ""), style: .default) { (_: UIAlertAction) in
- self.saveMode = .overwrite
- self.dismiss(animated: true)
- })
- }
-
- alertController.addAction(UIAlertAction(title: NSLocalizedString("_save_as_copy_", comment: ""), style: .default) { (_: UIAlertAction) in
- self.saveMode = .copy
- self.dismiss(animated: true)
- })
-
- alertController.addAction(UIAlertAction(title: NSLocalizedString("_discard_changes_", comment: ""), style: .destructive) { (_: UIAlertAction) in
- self.saveMode = .discard
- self.dismiss(animated: true)
- })
+ override func viewDidAppear(_ animated: Bool) {
+ super.viewDidAppear(animated)
+ // needs to be saved bc in didDisappear presentingVC is already nil
+ self.parentVC = presentingViewController
+ }
- alertController.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel) { (_: UIAlertAction) in })
+ override func viewDidDisappear(_ animated: Bool) {
+ super.viewDidDisappear(animated)
- self.present(alertController, animated: true)
+ guard isEditingEnabled, hasChanges, let metadata = metadata else { return }
+ let alertController = UIAlertController(title: NSLocalizedString("_save_", comment: ""), message: nil, preferredStyle: .alert)
+ var message: String?
+ if metadata.livePhoto {
+ message = NSLocalizedString("_message_disable_overwrite_livephoto_", comment: "")
+ } else if metadata.lock {
+ message = NSLocalizedString("_file_locked_no_override_", comment: "")
} else {
-
- self.dismiss(animated: true)
+ alertController.addAction(UIAlertAction(title: NSLocalizedString("_overwrite_original_", comment: ""), style: .default) { _ in
+ self.saveModifiedFile(override: true)
+ })
}
+ alertController.message = message
+
+ alertController.addAction(UIAlertAction(title: NSLocalizedString("_save_as_copy_", comment: ""), style: .default) { _ in
+ self.saveModifiedFile(override: false)
+ })
+ alertController.addAction(UIAlertAction(title: NSLocalizedString("_discard_changes_", comment: ""), style: .destructive) { _ in })
+ parentVC?.present(alertController, animated: true)
}
}
@@ -139,46 +117,51 @@ extension NCViewerQuickLook: QLPreviewControllerDataSource, QLPreviewControllerD
previewItems[index]
}
- func previewController(_ controller: QLPreviewController, didUpdateContentsOf previewItem: QLPreviewItem) {
- }
-
@available(iOS 13.0, *)
func previewController(_ controller: QLPreviewController, editingModeFor previewItem: QLPreviewItem) -> QLPreviewItemEditingMode {
- if editingMode {
- return .createCopy
- } else {
- return .disabled
- }
+ return isEditingEnabled ? .createCopy : .disabled
}
- func previewController(_ controller: QLPreviewController, didSaveEditedCopyOf previewItem: QLPreviewItem, at modifiedContentsURL: URL) {
-
- if saveMode != .discard {
-
- guard let metadata = self.metadata else { return }
- let ocId = NSUUID().uuidString
- let size = NCUtilityFileSystem.shared.getFileSize(filePath: modifiedContentsURL.path)
-
- if saveMode == .copy {
- let fileName = NCUtilityFileSystem.shared.createFileName(metadata.fileNameView, serverUrl: metadata.serverUrl, account: metadata.account)
- metadata.fileName = fileName
- metadata.fileNameView = fileName
- }
-
- let fileNamePath = CCUtility.getDirectoryProviderStorageOcId(ocId, fileNameView: metadata.fileNameView)!
+ fileprivate func saveModifiedFile(override: Bool) {
+ guard let metadata = self.metadata else { return }
- if NCUtilityFileSystem.shared.copyFile(atPath: modifiedContentsURL.path, toPath: fileNamePath) {
+ let ocId = NSUUID().uuidString
+ let size = NCUtilityFileSystem.shared.getFileSize(filePath: url.path)
- let metadataForUpload = NCManageDatabase.shared.createMetadata(account: metadata.account, user: metadata.user, userId: metadata.userId, fileName: metadata.fileName, fileNameView: metadata.fileNameView, ocId: ocId, serverUrl: metadata.serverUrl, urlBase: metadata.urlBase, url: modifiedContentsURL.path, contentType: "", livePhoto: false)
+ if !override {
+ let fileName = NCUtilityFileSystem.shared.createFileName(metadata.fileNameView, serverUrl: metadata.serverUrl, account: metadata.account)
+ metadata.fileName = fileName
+ metadata.fileNameView = fileName
+ }
- metadataForUpload.session = NCNetworking.shared.sessionIdentifierBackground
- metadataForUpload.sessionSelector = NCGlobal.shared.selectorUploadFile
- metadataForUpload.size = size
- metadataForUpload.status = NCGlobal.shared.metadataStatusWaitUpload
+ guard let fileNamePath = CCUtility.getDirectoryProviderStorageOcId(ocId, fileNameView: metadata.fileNameView),
+ NCUtilityFileSystem.shared.copyFile(atPath: url.path, toPath: fileNamePath) else { return }
+
+ let metadataForUpload = NCManageDatabase.shared.createMetadata(
+ account: metadata.account,
+ user: metadata.user,
+ userId: metadata.userId,
+ fileName: metadata.fileName,
+ fileNameView: metadata.fileNameView,
+ ocId: ocId,
+ serverUrl: metadata.serverUrl,
+ urlBase: metadata.urlBase,
+ url: url.path,
+ contentType: "",
+ livePhoto: false)
+
+ metadataForUpload.session = NCNetworking.shared.sessionIdentifierBackground
+ metadataForUpload.sessionSelector = NCGlobal.shared.selectorUploadFile
+ metadataForUpload.size = size
+ metadataForUpload.status = NCGlobal.shared.metadataStatusWaitUpload
+ (UIApplication.shared.delegate as? AppDelegate)?.networkingProcessUpload?.createProcessUploads(metadatas: [metadataForUpload])
+ }
- appDelegate.networkingProcessUpload?.createProcessUploads(metadatas: [metadataForUpload])
- }
- }
+ func previewController(_ controller: QLPreviewController, didSaveEditedCopyOf previewItem: QLPreviewItem, at modifiedContentsURL: URL) {
+ // easier to handle that way than to use `.updateContents`
+ // needs to be moved otherwise it will only be called once!
+ guard NCUtilityFileSystem.shared.moveFile(atPath: modifiedContentsURL.path, toPath: url.path) else { return }
+ hasChanges = true
}
}