diff --git a/.gitattributes b/.gitattributes index 5cd1ca6a31..d0107afc62 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,3 @@ *. filter=lfs diff=lfs merge=lfs -text *.framework filter=lfs diff=lfs merge=lfs -text +/** merge=union diff --git a/.github/workflows/nmc-custom-client.yml b/.github/workflows/nmc-custom-client.yml new file mode 100644 index 0000000000..9c3e86c1bc --- /dev/null +++ b/.github/workflows/nmc-custom-client.yml @@ -0,0 +1,45 @@ +### +# SPDX-License-Identifier: AGPL-3.0 +# +# Author: Bernd rederlechner +# +# Builds a stable release package based on a release assembly +# customisation-- +# +# As soon as a package is deployed to production, the tag and the branch +# MUST STAY FOR 2 years and not deleted. +# +# Release packages, tags and customisation branches not delivered to production should +# be deleted asap a newer release is available. +# + +name: MCLOUD custom client merge + +on: + workflow_dispatch: + inputs: + branch: + type: choice + description: Custom build from base branch + options: + - master + - stable-4.9.7 + - stable-5.2.1 + - stable-5.2.7 + - stable-5.5.0 + - stable-5.5.5 + - stable-6.1.3 + - stable-6.2.7 + - stable-6.6.0 + - stable-6.6.3 + # - v3.0.8 + default: master + +jobs: + assemble-custom: + uses: nextmcloud/.github/.github/workflows/nmc-custom-client.yml@master + with: + trunk: 'master' + stable: ${{ inputs.branch }} + result: ${{ format('customisation-{0}-{1}', github.actor, inputs.branch) }} + secrets: inherit diff --git a/.github/workflows/nmc-custom-stables.yml b/.github/workflows/nmc-custom-stables.yml new file mode 100644 index 0000000000..735fd8e7b6 --- /dev/null +++ b/.github/workflows/nmc-custom-stables.yml @@ -0,0 +1,46 @@ +### +# SPDX-License-Identifier: AGPL-3.0 +# +# Author: Bernd rederlechner +# +# Builds a stable release package based on a release assembly +# customisation-- +# +# As soon as a package is deployed to production, the tag and the branch +# MUST STAY FOR 2 years and not deleted. +# +# Release packages, tags and customisation branches not delivered to production should +# be deleted asap a newer release is available. +# + +name: MCLOUD create stable backports + +on: + workflow_dispatch: + inputs: + branch: + type: choice + description: Custom build from base branch + options: + - stable-6.6.3 + - stable-6.6.0 + - stable-6.5.0 + - stable-6.2.7 + - stable-6.1.3 + - stable-5.5.5 + - stable-5.5.4 + - stable-5.2.7 + - stable-5.2.1 + - stable-4.9.7 + - 4.9.6 + - 4.9.5 + default: stable-6.6.0 + default: stable-6.6.3 + +jobs: + backport-custom: + uses: nextmcloud/.github/.github/workflows/nmc-custom-stables.yml@master + with: + trunk: 'master' + stable: ${{ inputs.branch }} + secrets: inherit diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Contents.json b/Brand/Custom.xcassets/AppIcon.appiconset/Contents.json old mode 100755 new mode 100644 index 602e395b95..406236518a --- a/Brand/Custom.xcassets/AppIcon.appiconset/Contents.json +++ b/Brand/Custom.xcassets/AppIcon.appiconset/Contents.json @@ -3,151 +3,151 @@ { "size" : "20x20", "idiom" : "iphone", - "filename" : "nextcloud-icon40@1x.png", + "filename" : "Icon-App-20x20@2x.png", "scale" : "2x" }, { "size" : "20x20", "idiom" : "iphone", - "filename" : "nextcloud-icon60@3x.png", + "filename" : "Icon-App-20x20@3x.png", "scale" : "3x" }, { "size" : "29x29", "idiom" : "iphone", - "filename" : "nextcloud-icon29@1x.png", + "filename" : "Icon-App-29x29@1x.png", "scale" : "1x" }, { "size" : "29x29", "idiom" : "iphone", - "filename" : "nextcloud-icon58@2x.png", + "filename" : "Icon-App-29x29@2x.png", "scale" : "2x" }, { "size" : "29x29", "idiom" : "iphone", - "filename" : "nextcloud-icon87@3x.png", + "filename" : "Icon-App-29x29@3x.png", "scale" : "3x" }, { "size" : "40x40", "idiom" : "iphone", - "filename" : "nextcloud-icon80@2x.png", + "filename" : "Icon-App-40x40@2x.png", "scale" : "2x" }, { "size" : "40x40", "idiom" : "iphone", - "filename" : "nextcloud-icon120@3x.png", + "filename" : "Icon-App-40x40@3x.png", "scale" : "3x" }, { "size" : "57x57", "idiom" : "iphone", - "filename" : "nextcloud-icon57@1x.png", + "filename" : "Icon-App-57x57@1x.png", "scale" : "1x" }, { "size" : "57x57", "idiom" : "iphone", - "filename" : "nextcloud-icon114@2x.png", + "filename" : "Icon-App-57x57@2x.png", "scale" : "2x" }, { "size" : "60x60", "idiom" : "iphone", - "filename" : "nextcloud-icon120@2x.png", + "filename" : "Icon-App-60x60@2x.png", "scale" : "2x" }, { "size" : "60x60", "idiom" : "iphone", - "filename" : "nextcloud-icon180@3x.png", + "filename" : "Icon-App-60x60@3x.png", "scale" : "3x" }, { "size" : "20x20", "idiom" : "ipad", - "filename" : "nextcloud-icon20@1x.png", + "filename" : "Icon-App-20x20@1x.png", "scale" : "1x" }, { "size" : "20x20", "idiom" : "ipad", - "filename" : "nextcloud-icon40@2x.png", + "filename" : "Icon-App-20x20@2x.png", "scale" : "2x" }, { "size" : "29x29", "idiom" : "ipad", - "filename" : "nextcloud-icon29@1x-1.png", + "filename" : "Icon-App-29x29@1x.png", "scale" : "1x" }, { "size" : "29x29", "idiom" : "ipad", - "filename" : "nextcloud-icon58@2x-1.png", + "filename" : "Icon-App-29x29@2x.png", "scale" : "2x" }, { "size" : "40x40", "idiom" : "ipad", - "filename" : "nextcloud-icon40@1x-1.png", + "filename" : "Icon-App-40x40@1x.png", "scale" : "1x" }, { "size" : "40x40", "idiom" : "ipad", - "filename" : "nextcloud-icon80@2x-1.png", + "filename" : "Icon-App-40x40@2x.png", "scale" : "2x" }, { "size" : "50x50", "idiom" : "ipad", - "filename" : "nextcloud-icon50@1x.png", + "filename" : "Icon-Small-50x50@1x.png", "scale" : "1x" }, { "size" : "50x50", "idiom" : "ipad", - "filename" : "nextcloud-icon100@2x.png", + "filename" : "Icon-Small-50x50@2x.png", "scale" : "2x" }, { "size" : "72x72", "idiom" : "ipad", - "filename" : "nextcloud-icon72@1x.png", + "filename" : "Icon-App-72x72@1x.png", "scale" : "1x" }, { "size" : "72x72", "idiom" : "ipad", - "filename" : "nextcloud-icon144@2x.png", + "filename" : "Icon-App-72x72@2x.png", "scale" : "2x" }, { "size" : "76x76", "idiom" : "ipad", - "filename" : "nextcloud-icon76@1x.png", + "filename" : "Icon-App-76x76@1x.png", "scale" : "1x" }, { "size" : "76x76", "idiom" : "ipad", - "filename" : "nextcloud-icon152@2x.png", + "filename" : "Icon-App-76x76@2x.png", "scale" : "2x" }, { "size" : "83.5x83.5", "idiom" : "ipad", - "filename" : "nextcloud-icon167@2x.png", + "filename" : "Icon-App-83.5x83.5@2x.png", "scale" : "2x" }, { "size" : "1024x1024", "idiom" : "ios-marketing", - "filename" : "nextcloud-icon1024@1x.png", + "filename" : "ItunesArtwork@2x.png", "scale" : "1x" } ], diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000000..af3e6ecf2c Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000000..9ebf9ce76f Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000..7ad68d21bd Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000000..8816885ac9 Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000..9c2707be28 Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000000..49b2d9df4f Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000000..9ebf9ce76f Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000..a77ffbbc9f Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000..f039b4325f Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png new file mode 100644 index 0000000000..2c7fed29f7 Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png new file mode 100644 index 0000000000..674c9ec404 Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000..f039b4325f Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000..30176fbcc5 Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png new file mode 100644 index 0000000000..49615f28be Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png new file mode 100644 index 0000000000..b0f1d413b0 Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000..02f8eb5ab3 Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000000..e21f6dfadd Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000000..d0a53d7de1 Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-Small-50x50@1x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-Small-50x50@1x.png new file mode 100644 index 0000000000..4701f66d28 Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-Small-50x50@1x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/Icon-Small-50x50@2x.png b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-Small-50x50@2x.png new file mode 100644 index 0000000000..5c6e52ade2 Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/Icon-Small-50x50@2x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png b/Brand/Custom.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png new file mode 100644 index 0000000000..74dce2b0aa Binary files /dev/null and b/Brand/Custom.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon100@2x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon100@2x.png deleted file mode 100644 index 2654d0b36f..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon100@2x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon1024@1x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon1024@1x.png deleted file mode 100644 index 686085377d..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon1024@1x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon114@2x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon114@2x.png deleted file mode 100644 index 742f9b5c11..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon114@2x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon120@2x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon120@2x.png deleted file mode 100644 index da4b62b9f9..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon120@2x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon120@3x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon120@3x.png deleted file mode 100644 index da4b62b9f9..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon120@3x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon144@2x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon144@2x.png deleted file mode 100644 index 2a53710170..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon144@2x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon152@2x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon152@2x.png deleted file mode 100644 index 20b3bdf67b..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon152@2x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon167@2x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon167@2x.png deleted file mode 100644 index fa53f0a732..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon167@2x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon180@3x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon180@3x.png deleted file mode 100644 index 11b972dd51..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon180@3x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon20@1x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon20@1x.png deleted file mode 100644 index 21320f1f5b..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon20@1x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon29@1x-1.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon29@1x-1.png deleted file mode 100644 index 3dc918c35a..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon29@1x-1.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon29@1x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon29@1x.png deleted file mode 100644 index 3dc918c35a..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon29@1x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon40@1x-1.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon40@1x-1.png deleted file mode 100644 index db726b2392..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon40@1x-1.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon40@1x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon40@1x.png deleted file mode 100644 index db726b2392..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon40@1x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon40@2x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon40@2x.png deleted file mode 100644 index db726b2392..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon40@2x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon50@1x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon50@1x.png deleted file mode 100644 index 3424f05526..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon50@1x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon57@1x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon57@1x.png deleted file mode 100644 index 6bc2dfd64b..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon57@1x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon58@2x-1.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon58@2x-1.png deleted file mode 100644 index f1180065d6..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon58@2x-1.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon58@2x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon58@2x.png deleted file mode 100644 index f1180065d6..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon58@2x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon60@3x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon60@3x.png deleted file mode 100644 index 5e976420ca..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon60@3x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon72@1x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon72@1x.png deleted file mode 100644 index 653a17c97c..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon72@1x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon76@1x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon76@1x.png deleted file mode 100644 index 644b00d949..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon76@1x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon80@2x-1.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon80@2x-1.png deleted file mode 100644 index 7b73dead05..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon80@2x-1.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon80@2x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon80@2x.png deleted file mode 100644 index 7b73dead05..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon80@2x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon87@3x.png b/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon87@3x.png deleted file mode 100644 index 65d972a7b9..0000000000 Binary files a/Brand/Custom.xcassets/AppIcon.appiconset/nextcloud-icon87@3x.png and /dev/null differ diff --git a/Brand/Custom.xcassets/introSlide1.imageset/Contents.json b/Brand/Custom.xcassets/introSlide1.imageset/Contents.json new file mode 100644 index 0000000000..65b05047b7 --- /dev/null +++ b/Brand/Custom.xcassets/introSlide1.imageset/Contents.json @@ -0,0 +1,33 @@ +{ + "images" : [ + { + "filename" : "introSlide1.png", + "idiom" : "iphone", + "scale" : "1x" + }, + { + "filename" : "introSlide1@2x.png", + "idiom" : "iphone", + "scale" : "2x" + }, + { + "filename" : "introSlide1@3x.png", + "idiom" : "iphone", + "scale" : "3x" + }, + { + "filename" : "Tablet Portrait - first slide-1.png", + "idiom" : "ipad", + "scale" : "1x" + }, + { + "filename" : "Tablet Portrait - first slide.png", + "idiom" : "ipad", + "scale" : "2x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Brand/Custom.xcassets/introSlide1.imageset/Tablet Portrait - first slide-1.png b/Brand/Custom.xcassets/introSlide1.imageset/Tablet Portrait - first slide-1.png new file mode 100644 index 0000000000..8a6354f8e9 Binary files /dev/null and b/Brand/Custom.xcassets/introSlide1.imageset/Tablet Portrait - first slide-1.png differ diff --git a/Brand/Custom.xcassets/introSlide1.imageset/Tablet Portrait - first slide.png b/Brand/Custom.xcassets/introSlide1.imageset/Tablet Portrait - first slide.png new file mode 100644 index 0000000000..8a6354f8e9 Binary files /dev/null and b/Brand/Custom.xcassets/introSlide1.imageset/Tablet Portrait - first slide.png differ diff --git a/Brand/Custom.xcassets/introSlide1.imageset/introSlide1.png b/Brand/Custom.xcassets/introSlide1.imageset/introSlide1.png new file mode 100644 index 0000000000..7ad97b76bc Binary files /dev/null and b/Brand/Custom.xcassets/introSlide1.imageset/introSlide1.png differ diff --git a/Brand/Custom.xcassets/introSlide1.imageset/introSlide1@2x.png b/Brand/Custom.xcassets/introSlide1.imageset/introSlide1@2x.png new file mode 100644 index 0000000000..7ad97b76bc Binary files /dev/null and b/Brand/Custom.xcassets/introSlide1.imageset/introSlide1@2x.png differ diff --git a/Brand/Custom.xcassets/introSlide1.imageset/introSlide1@3x.png b/Brand/Custom.xcassets/introSlide1.imageset/introSlide1@3x.png new file mode 100644 index 0000000000..271ec26fda Binary files /dev/null and b/Brand/Custom.xcassets/introSlide1.imageset/introSlide1@3x.png differ diff --git a/Brand/Custom.xcassets/introSlide2.imageset/Contents.json b/Brand/Custom.xcassets/introSlide2.imageset/Contents.json new file mode 100644 index 0000000000..6f14cfcd17 --- /dev/null +++ b/Brand/Custom.xcassets/introSlide2.imageset/Contents.json @@ -0,0 +1,33 @@ +{ + "images" : [ + { + "filename" : "introSlide2.png", + "idiom" : "iphone", + "scale" : "1x" + }, + { + "filename" : "introSlide2@2x.png", + "idiom" : "iphone", + "scale" : "2x" + }, + { + "filename" : "introSlide2@3x.png", + "idiom" : "iphone", + "scale" : "3x" + }, + { + "filename" : "Tablet Portrait - third slide-1.png", + "idiom" : "ipad", + "scale" : "1x" + }, + { + "filename" : "Tablet Portrait - third slide.png", + "idiom" : "ipad", + "scale" : "2x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Brand/Custom.xcassets/introSlide2.imageset/Tablet Portrait - third slide-1.png b/Brand/Custom.xcassets/introSlide2.imageset/Tablet Portrait - third slide-1.png new file mode 100644 index 0000000000..58357b3fb7 Binary files /dev/null and b/Brand/Custom.xcassets/introSlide2.imageset/Tablet Portrait - third slide-1.png differ diff --git a/Brand/Custom.xcassets/introSlide2.imageset/Tablet Portrait - third slide.png b/Brand/Custom.xcassets/introSlide2.imageset/Tablet Portrait - third slide.png new file mode 100644 index 0000000000..58357b3fb7 Binary files /dev/null and b/Brand/Custom.xcassets/introSlide2.imageset/Tablet Portrait - third slide.png differ diff --git a/Brand/Custom.xcassets/introSlide2.imageset/introSlide2.png b/Brand/Custom.xcassets/introSlide2.imageset/introSlide2.png new file mode 100644 index 0000000000..df3e9d9339 Binary files /dev/null and b/Brand/Custom.xcassets/introSlide2.imageset/introSlide2.png differ diff --git a/Brand/Custom.xcassets/introSlide2.imageset/introSlide2@2x.png b/Brand/Custom.xcassets/introSlide2.imageset/introSlide2@2x.png new file mode 100644 index 0000000000..df3e9d9339 Binary files /dev/null and b/Brand/Custom.xcassets/introSlide2.imageset/introSlide2@2x.png differ diff --git a/Brand/Custom.xcassets/introSlide2.imageset/introSlide2@3x.png b/Brand/Custom.xcassets/introSlide2.imageset/introSlide2@3x.png new file mode 100644 index 0000000000..17bf5d89a4 Binary files /dev/null and b/Brand/Custom.xcassets/introSlide2.imageset/introSlide2@3x.png differ diff --git a/Brand/Custom.xcassets/introSlide3.imageset/Contents.json b/Brand/Custom.xcassets/introSlide3.imageset/Contents.json new file mode 100644 index 0000000000..e15a5bbe53 --- /dev/null +++ b/Brand/Custom.xcassets/introSlide3.imageset/Contents.json @@ -0,0 +1,33 @@ +{ + "images" : [ + { + "filename" : "introSlide3.png", + "idiom" : "iphone", + "scale" : "1x" + }, + { + "filename" : "introSlide3@2x.png", + "idiom" : "iphone", + "scale" : "2x" + }, + { + "filename" : "introSlide3@3x.png", + "idiom" : "iphone", + "scale" : "3x" + }, + { + "filename" : "Tablet Portrait - second slide-1.png", + "idiom" : "ipad", + "scale" : "1x" + }, + { + "filename" : "Tablet Portrait - second slide.png", + "idiom" : "ipad", + "scale" : "2x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Brand/Custom.xcassets/introSlide3.imageset/Tablet Portrait - second slide-1.png b/Brand/Custom.xcassets/introSlide3.imageset/Tablet Portrait - second slide-1.png new file mode 100644 index 0000000000..395767ba7f Binary files /dev/null and b/Brand/Custom.xcassets/introSlide3.imageset/Tablet Portrait - second slide-1.png differ diff --git a/Brand/Custom.xcassets/introSlide3.imageset/Tablet Portrait - second slide.png b/Brand/Custom.xcassets/introSlide3.imageset/Tablet Portrait - second slide.png new file mode 100644 index 0000000000..395767ba7f Binary files /dev/null and b/Brand/Custom.xcassets/introSlide3.imageset/Tablet Portrait - second slide.png differ diff --git a/Brand/Custom.xcassets/introSlide3.imageset/introSlide3.png b/Brand/Custom.xcassets/introSlide3.imageset/introSlide3.png new file mode 100644 index 0000000000..bd19e31a5b Binary files /dev/null and b/Brand/Custom.xcassets/introSlide3.imageset/introSlide3.png differ diff --git a/Brand/Custom.xcassets/introSlide3.imageset/introSlide3@2x.png b/Brand/Custom.xcassets/introSlide3.imageset/introSlide3@2x.png new file mode 100644 index 0000000000..bd19e31a5b Binary files /dev/null and b/Brand/Custom.xcassets/introSlide3.imageset/introSlide3@2x.png differ diff --git a/Brand/Custom.xcassets/introSlide3.imageset/introSlide3@3x.png b/Brand/Custom.xcassets/introSlide3.imageset/introSlide3@3x.png new file mode 100644 index 0000000000..223fee7741 Binary files /dev/null and b/Brand/Custom.xcassets/introSlide3.imageset/introSlide3@3x.png differ diff --git a/Brand/Custom.xcassets/introSlideEight1.imageset/Contents.json b/Brand/Custom.xcassets/introSlideEight1.imageset/Contents.json new file mode 100644 index 0000000000..56a179f397 --- /dev/null +++ b/Brand/Custom.xcassets/introSlideEight1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "introSlideEight1@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Brand/Custom.xcassets/introSlideEight1.imageset/introSlideEight1@3x.png b/Brand/Custom.xcassets/introSlideEight1.imageset/introSlideEight1@3x.png new file mode 100644 index 0000000000..244802dfc2 Binary files /dev/null and b/Brand/Custom.xcassets/introSlideEight1.imageset/introSlideEight1@3x.png differ diff --git a/Brand/Custom.xcassets/introSlideEight2.imageset/Contents.json b/Brand/Custom.xcassets/introSlideEight2.imageset/Contents.json new file mode 100644 index 0000000000..4e7d271b20 --- /dev/null +++ b/Brand/Custom.xcassets/introSlideEight2.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "introSlideEight2@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Brand/Custom.xcassets/introSlideEight2.imageset/introSlideEight2@3x.png b/Brand/Custom.xcassets/introSlideEight2.imageset/introSlideEight2@3x.png new file mode 100644 index 0000000000..7cccb2c941 Binary files /dev/null and b/Brand/Custom.xcassets/introSlideEight2.imageset/introSlideEight2@3x.png differ diff --git a/Brand/Custom.xcassets/introSlideEight3.imageset/Contents.json b/Brand/Custom.xcassets/introSlideEight3.imageset/Contents.json new file mode 100644 index 0000000000..d1192931e8 --- /dev/null +++ b/Brand/Custom.xcassets/introSlideEight3.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "introSlideEight3@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Brand/Custom.xcassets/introSlideEight3.imageset/introSlideEight3@3x.png b/Brand/Custom.xcassets/introSlideEight3.imageset/introSlideEight3@3x.png new file mode 100644 index 0000000000..21adc87717 Binary files /dev/null and b/Brand/Custom.xcassets/introSlideEight3.imageset/introSlideEight3@3x.png differ diff --git a/Brand/Custom.xcassets/introSlideLand1.imageset/Contents.json b/Brand/Custom.xcassets/introSlideLand1.imageset/Contents.json new file mode 100644 index 0000000000..58788d977d --- /dev/null +++ b/Brand/Custom.xcassets/introSlideLand1.imageset/Contents.json @@ -0,0 +1,33 @@ +{ + "images" : [ + { + "filename" : "introSlide1.png", + "idiom" : "iphone", + "scale" : "1x" + }, + { + "filename" : "introSlide1@2x.png", + "idiom" : "iphone", + "scale" : "2x" + }, + { + "filename" : "introSlide1@3x.png", + "idiom" : "iphone", + "scale" : "3x" + }, + { + "filename" : "Tablet Landscape - first slide.png", + "idiom" : "ipad", + "scale" : "1x" + }, + { + "filename" : "Tablet Landscape - first slide-1.png", + "idiom" : "ipad", + "scale" : "2x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Brand/Custom.xcassets/introSlideLand1.imageset/Tablet Landscape - first slide-1.png b/Brand/Custom.xcassets/introSlideLand1.imageset/Tablet Landscape - first slide-1.png new file mode 100644 index 0000000000..6e3df04303 Binary files /dev/null and b/Brand/Custom.xcassets/introSlideLand1.imageset/Tablet Landscape - first slide-1.png differ diff --git a/Brand/Custom.xcassets/introSlideLand1.imageset/Tablet Landscape - first slide.png b/Brand/Custom.xcassets/introSlideLand1.imageset/Tablet Landscape - first slide.png new file mode 100644 index 0000000000..6e3df04303 Binary files /dev/null and b/Brand/Custom.xcassets/introSlideLand1.imageset/Tablet Landscape - first slide.png differ diff --git a/Brand/Custom.xcassets/introSlideLand1.imageset/introSlide1.png b/Brand/Custom.xcassets/introSlideLand1.imageset/introSlide1.png new file mode 100644 index 0000000000..7ad97b76bc Binary files /dev/null and b/Brand/Custom.xcassets/introSlideLand1.imageset/introSlide1.png differ diff --git a/Brand/Custom.xcassets/introSlideLand1.imageset/introSlide1@2x.png b/Brand/Custom.xcassets/introSlideLand1.imageset/introSlide1@2x.png new file mode 100644 index 0000000000..7ad97b76bc Binary files /dev/null and b/Brand/Custom.xcassets/introSlideLand1.imageset/introSlide1@2x.png differ diff --git a/Brand/Custom.xcassets/introSlideLand1.imageset/introSlide1@3x.png b/Brand/Custom.xcassets/introSlideLand1.imageset/introSlide1@3x.png new file mode 100644 index 0000000000..271ec26fda Binary files /dev/null and b/Brand/Custom.xcassets/introSlideLand1.imageset/introSlide1@3x.png differ diff --git a/Brand/Custom.xcassets/introSlideLand2.imageset/Contents.json b/Brand/Custom.xcassets/introSlideLand2.imageset/Contents.json new file mode 100644 index 0000000000..efbfa73a66 --- /dev/null +++ b/Brand/Custom.xcassets/introSlideLand2.imageset/Contents.json @@ -0,0 +1,33 @@ +{ + "images" : [ + { + "filename" : "introSlide2.png", + "idiom" : "iphone", + "scale" : "1x" + }, + { + "filename" : "introSlide2@2x.png", + "idiom" : "iphone", + "scale" : "2x" + }, + { + "filename" : "introSlide2@3x.png", + "idiom" : "iphone", + "scale" : "3x" + }, + { + "filename" : "Tablet Landscape - second slide.png", + "idiom" : "ipad", + "scale" : "1x" + }, + { + "filename" : "Tablet Landscape - second slide-1.png", + "idiom" : "ipad", + "scale" : "2x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Brand/Custom.xcassets/introSlideLand2.imageset/Tablet Landscape - second slide-1.png b/Brand/Custom.xcassets/introSlideLand2.imageset/Tablet Landscape - second slide-1.png new file mode 100644 index 0000000000..c5e3bca8af Binary files /dev/null and b/Brand/Custom.xcassets/introSlideLand2.imageset/Tablet Landscape - second slide-1.png differ diff --git a/Brand/Custom.xcassets/introSlideLand2.imageset/Tablet Landscape - second slide.png b/Brand/Custom.xcassets/introSlideLand2.imageset/Tablet Landscape - second slide.png new file mode 100644 index 0000000000..c5e3bca8af Binary files /dev/null and b/Brand/Custom.xcassets/introSlideLand2.imageset/Tablet Landscape - second slide.png differ diff --git a/Brand/Custom.xcassets/introSlideLand2.imageset/introSlide2.png b/Brand/Custom.xcassets/introSlideLand2.imageset/introSlide2.png new file mode 100644 index 0000000000..df3e9d9339 Binary files /dev/null and b/Brand/Custom.xcassets/introSlideLand2.imageset/introSlide2.png differ diff --git a/Brand/Custom.xcassets/introSlideLand2.imageset/introSlide2@2x.png b/Brand/Custom.xcassets/introSlideLand2.imageset/introSlide2@2x.png new file mode 100644 index 0000000000..df3e9d9339 Binary files /dev/null and b/Brand/Custom.xcassets/introSlideLand2.imageset/introSlide2@2x.png differ diff --git a/Brand/Custom.xcassets/introSlideLand2.imageset/introSlide2@3x.png b/Brand/Custom.xcassets/introSlideLand2.imageset/introSlide2@3x.png new file mode 100644 index 0000000000..17bf5d89a4 Binary files /dev/null and b/Brand/Custom.xcassets/introSlideLand2.imageset/introSlide2@3x.png differ diff --git a/Brand/Custom.xcassets/introSlideLand3.imageset/Contents.json b/Brand/Custom.xcassets/introSlideLand3.imageset/Contents.json new file mode 100644 index 0000000000..fce5b583fd --- /dev/null +++ b/Brand/Custom.xcassets/introSlideLand3.imageset/Contents.json @@ -0,0 +1,33 @@ +{ + "images" : [ + { + "filename" : "introSlide3.png", + "idiom" : "iphone", + "scale" : "1x" + }, + { + "filename" : "introSlide3@2x.png", + "idiom" : "iphone", + "scale" : "2x" + }, + { + "filename" : "introSlide3@3x.png", + "idiom" : "iphone", + "scale" : "3x" + }, + { + "filename" : "Tablet Landscape - third slide.png", + "idiom" : "ipad", + "scale" : "1x" + }, + { + "filename" : "Tablet Landscape - third slide-1.png", + "idiom" : "ipad", + "scale" : "2x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Brand/Custom.xcassets/introSlideLand3.imageset/Tablet Landscape - third slide-1.png b/Brand/Custom.xcassets/introSlideLand3.imageset/Tablet Landscape - third slide-1.png new file mode 100644 index 0000000000..faa2188a48 Binary files /dev/null and b/Brand/Custom.xcassets/introSlideLand3.imageset/Tablet Landscape - third slide-1.png differ diff --git a/Brand/Custom.xcassets/introSlideLand3.imageset/Tablet Landscape - third slide.png b/Brand/Custom.xcassets/introSlideLand3.imageset/Tablet Landscape - third slide.png new file mode 100644 index 0000000000..faa2188a48 Binary files /dev/null and b/Brand/Custom.xcassets/introSlideLand3.imageset/Tablet Landscape - third slide.png differ diff --git a/Brand/Custom.xcassets/introSlideLand3.imageset/introSlide3.png b/Brand/Custom.xcassets/introSlideLand3.imageset/introSlide3.png new file mode 100644 index 0000000000..bd19e31a5b Binary files /dev/null and b/Brand/Custom.xcassets/introSlideLand3.imageset/introSlide3.png differ diff --git a/Brand/Custom.xcassets/introSlideLand3.imageset/introSlide3@2x.png b/Brand/Custom.xcassets/introSlideLand3.imageset/introSlide3@2x.png new file mode 100644 index 0000000000..bd19e31a5b Binary files /dev/null and b/Brand/Custom.xcassets/introSlideLand3.imageset/introSlide3@2x.png differ diff --git a/Brand/Custom.xcassets/introSlideLand3.imageset/introSlide3@3x.png b/Brand/Custom.xcassets/introSlideLand3.imageset/introSlide3@3x.png new file mode 100644 index 0000000000..223fee7741 Binary files /dev/null and b/Brand/Custom.xcassets/introSlideLand3.imageset/introSlide3@3x.png differ diff --git a/Brand/Custom.xcassets/logo.imageset/logo.svg b/Brand/Custom.xcassets/logo.imageset/logo.svg index 076f295e4d..1c655786db 100644 --- a/Brand/Custom.xcassets/logo.imageset/logo.svg +++ b/Brand/Custom.xcassets/logo.imageset/logo.svg @@ -1 +1,19 @@ - + + + + + + + diff --git a/Brand/File_Provider_Extension.entitlements b/Brand/File_Provider_Extension.entitlements index 4ecc3f0d13..0123881826 100755 --- a/Brand/File_Provider_Extension.entitlements +++ b/Brand/File_Provider_Extension.entitlements @@ -4,11 +4,19 @@ com.apple.security.application-groups - group.it.twsweb.Crypto-Cloud + group.de.magentacloud.next.dev2.client keychain-access-groups - $(AppIdentifierPrefix)it.twsweb.Crypto-Cloud + $(AppIdentifierPrefix)de.magentacloud.next.dev2.client + com.apple.security.application-groups + + group.com.t-systems.pu-ds.magentacloud.qa + + keychain-access-groups + + $(AppIdentifierPrefix)MagentaCLOUD + diff --git a/Brand/File_Provider_Extension.plist b/Brand/File_Provider_Extension.plist index 7179d95e3a..6bf00d7182 100755 --- a/Brand/File_Provider_Extension.plist +++ b/Brand/File_Provider_Extension.plist @@ -5,7 +5,7 @@ CFBundleDevelopmentRegion en CFBundleDisplayName - Nextcloud + MagentaCLOUD CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -19,7 +19,7 @@ CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion - $(CURRENT_PROJECT_VERSION) + 34247 NSAppTransportSecurity NSAllowsArbitraryLoads @@ -33,7 +33,7 @@ NSExtensionFileProviderDocumentGroup - group.it.twsweb.Crypto-Cloud + group.de.magentacloud.next.dev2.client NSExtensionFileProviderSupportsEnumeration NSExtensionFileProviderSupportsPickingFolders @@ -43,5 +43,41 @@ NSExtensionPrincipalClass $(PRODUCT_MODULE_NAME).FileProviderExtension + CFBundleDevelopmentRegion + en + CFBundleDisplayName + MagentaCLOUD + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + XPC! + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + NSExtension + + NSExtensionFileProviderDocumentGroup + group.de.telekom.Mediencenter + NSExtensionFileProviderSupportsEnumeration + + NSExtensionFileProviderSupportsPickingFolders + + NSExtensionPointIdentifier + com.apple.fileprovider-nonui + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).FileProviderExtension + diff --git a/Brand/File_Provider_Extension_UI.entitlements b/Brand/File_Provider_Extension_UI.entitlements index 4ecc3f0d13..cc660b0e8a 100644 --- a/Brand/File_Provider_Extension_UI.entitlements +++ b/Brand/File_Provider_Extension_UI.entitlements @@ -4,11 +4,11 @@ com.apple.security.application-groups - group.it.twsweb.Crypto-Cloud + group.de.magentacloud.next.dev2.client keychain-access-groups - $(AppIdentifierPrefix)it.twsweb.Crypto-Cloud + $(AppIdentifierPrefix)de.magentacloud.next.dev2.client diff --git a/Brand/File_Provider_Extension_UI.plist b/Brand/File_Provider_Extension_UI.plist index 5e27de9fde..24ffb10304 100644 --- a/Brand/File_Provider_Extension_UI.plist +++ b/Brand/File_Provider_Extension_UI.plist @@ -3,7 +3,7 @@ CFBundleDisplayName - Nextcloud + MagentaCLOUD NSExtension NSExtensionFileProviderActions @@ -29,7 +29,7 @@ CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion - $(CURRENT_PROJECT_VERSION) + 34247 CFBundleInfoDictionaryVersion 6.0 CFBundleDevelopmentRegion diff --git a/Brand/Intro/NCIntro.storyboard b/Brand/Intro/NCIntro.storyboard index 1a4fabd425..c17b6df339 100644 --- a/Brand/Intro/NCIntro.storyboard +++ b/Brand/Intro/NCIntro.storyboard @@ -1,137 +1,123 @@ - + - + - + - - + + - - + + - - - - - + - - + + - - + - - - - + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - + + + + + + + - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - + - + - + diff --git a/Brand/Intro/NCIntroCollectionViewCell.xib b/Brand/Intro/NCIntroCollectionViewCell.xib index 7eed66d3ba..ab7c53a1de 100644 --- a/Brand/Intro/NCIntroCollectionViewCell.xib +++ b/Brand/Intro/NCIntroCollectionViewCell.xib @@ -1,56 +1,57 @@ - + - + - + - - + - - - - - - + + + + + + + + - - + + - + diff --git a/Brand/Intro/NCIntroViewController.swift b/Brand/Intro/NCIntroViewController.swift index c626a4c557..d4ee917c6f 100644 --- a/Brand/Intro/NCIntroViewController.swift +++ b/Brand/Intro/NCIntroViewController.swift @@ -4,6 +4,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later import UIKit +import NextcloudKit class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { @IBOutlet weak var buttonLogin: UIButton! @@ -11,22 +12,30 @@ class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICol @IBOutlet weak var buttonHost: UIButton! @IBOutlet weak var introCollectionView: UICollectionView! @IBOutlet weak var pageControl: UIPageControl! + @IBOutlet weak var contstraintBottomLoginButton: NSLayoutConstraint! weak var delegate: NCIntroViewController? // Controller var controller: NCMainTabBarController? private let appDelegate = (UIApplication.shared.delegate as? AppDelegate)! - private let titles = [NSLocalizedString("_intro_1_title_", comment: ""), NSLocalizedString("_intro_2_title_", comment: ""), NSLocalizedString("_intro_3_title_", comment: ""), NSLocalizedString("_intro_4_title_", comment: "")] - private let images = [UIImage(named: "intro1"), UIImage(named: "intro2"), UIImage(named: "intro3"), UIImage(named: "intro4")] - private var timer: Timer? + private let titles = [NSLocalizedString("", comment: ""), NSLocalizedString("", comment: ""), NSLocalizedString("", comment: "")] + private var images:[UIImage?] = [] + private var timerAutoScroll: Timer? + private var textColor: UIColor = .white private var textColorOpponent: UIColor = .black + private let imagesLandscape = [UIImage(named: "introSlideLand1"), UIImage(named: "introSlideLand2"), UIImage(named: "introSlideLand3")] + private let imagesPortrait = [UIImage(named: "introSlide1"), UIImage(named: "introSlide2"), UIImage(named: "introSlide3")] + private let imagesEightPortrait = [UIImage(named: "introSlideEight1"), UIImage(named: "introSlideEight2"), UIImage(named: "introSlideEight3")] // MARK: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() + + let isEightPlusDevice = UIScreen.main.bounds.height == 736 + images = UIDevice.current.orientation.isLandscape ? imagesLandscape : (isEightPlusDevice ? imagesEightPortrait : imagesPortrait) let isTooLight = NCBrandColor.shared.customer.isTooLight() let isTooDark = NCBrandColor.shared.customer.isTooDark() @@ -51,7 +60,7 @@ class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICol self.navigationController?.navigationBar.tintColor = textColor if !NCManageDatabase.shared.getAllTableAccount().isEmpty { - let navigationItemCancel = UIBarButtonItem(image: UIImage(systemName: "xmark"), style: .plain, target: self, action: #selector(actionCancel(_:))) + let navigationItemCancel = UIBarButtonItem(image: UIImage(systemName: "xmark"), style: .done, target: self, action: #selector(self.actionCancel)) navigationItemCancel.tintColor = textColor navigationItem.leftBarButtonItem = navigationItemCancel } @@ -64,10 +73,13 @@ class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICol buttonLogin.backgroundColor = textColor buttonLogin.setTitle(NSLocalizedString("_log_in_", comment: ""), for: .normal) - buttonSignUp.layer.cornerRadius = 8 + buttonSignUp.layer.cornerRadius = 20 + buttonSignUp.layer.borderColor = textColor.cgColor + buttonSignUp.layer.borderWidth = 1.0 buttonSignUp.setTitleColor(textColor, for: .normal) - buttonSignUp.backgroundColor = textColor.withAlphaComponent(0.2) + 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 @@ -82,7 +94,8 @@ class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICol view.backgroundColor = NCBrandColor.shared.customer - self.timer = Timer.scheduledTimer(timeInterval: 4, target: self, selector: (#selector(self.autoScroll(_:))), userInfo: nil, repeats: true) + timerAutoScroll = Timer.scheduledTimer(timeInterval: 5, target: self, selector: (#selector(NCIntroViewController.autoScroll)), userInfo: nil, repeats: true) + NotificationCenter.default.addObserver(self, selector: #selector(resetPageController(_:)), name: UIApplication.willEnterForegroundNotification, object: nil) } override var preferredStatusBarStyle: UIStatusBarStyle { @@ -93,23 +106,41 @@ class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICol } } + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + if (UIDevice.current.userInterfaceIdiom != .pad){ + AppUtility.lockOrientation(UIInterfaceOrientationMask.portrait, andRotateTo: UIInterfaceOrientation.portrait) + } + navigationController?.setNavigationBarHidden(true, animated: animated) + } + + override func viewDidLayoutSubviews() { + if UIScreen.main.bounds.width < 350 || UIScreen.main.bounds.height > 800 { + contstraintBottomLoginButton.constant = 15 + } + } + override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - - timer?.invalidate() - timer = nil + timerAutoScroll?.invalidate() + AppUtility.lockOrientation(UIInterfaceOrientationMask.all) + navigationController?.setNavigationBarHidden(false, animated: animated) } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { - super.viewWillTransition(to: size, with: coordinator) - - coordinator.animate(alongsideTransition: nil) { _ in - self.pageControl?.currentPage = 0 - self.introCollectionView?.collectionViewLayout.invalidateLayout() - } + let isEightPlusDevice = UIScreen.main.bounds.height == 736 + images = UIDevice.current.orientation.isLandscape ? imagesLandscape : (isEightPlusDevice ? imagesEightPortrait : imagesPortrait) + pageControl.currentPage = 0 + introCollectionView.collectionViewLayout.invalidateLayout() + self.introCollectionView.reloadData() + } + + @objc func resetPageController(_ notification: NSNotification){ + pageControl.currentPage = 0 + introCollectionView.scrollToItem(at: IndexPath(row: pageControl.currentPage, section: 0), at: .centeredHorizontally, animated: true) } - @objc func autoScroll(_ sender: Any?) { + @objc func autoScroll() { if pageControl.currentPage + 1 >= titles.count { pageControl.currentPage = 0 } else { @@ -133,6 +164,7 @@ class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICol cell.titleLabel.textColor = textColor cell.titleLabel.text = titles[indexPath.row] cell.imageView.image = images[indexPath.row] + cell.imageView.contentMode = .scaleAspectFill return cell } @@ -141,34 +173,52 @@ class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICol } func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { - timer = Timer.scheduledTimer(timeInterval: 4, target: self, selector: (#selector(autoScroll(_:))), userInfo: nil, repeats: true) - pageControl.currentPage = Int(scrollView.contentOffset.x) / Int(scrollView.frame.width) + timerAutoScroll = Timer.scheduledTimer(timeInterval: 5, target: self, selector: (#selector(NCIntroViewController.autoScroll)), userInfo: nil, repeats: true) + let page = Int(scrollView.contentOffset.x) / Int(scrollView.frame.width) + if pageControl.currentPage == (images.count - 1), pageControl.currentPage <= page { + pageControl.currentPage = 0 + introCollectionView.scrollToItem(at: IndexPath(row: pageControl.currentPage, section: 0), at: .centeredHorizontally, animated: false) + } else { + pageControl.currentPage = Int(scrollView.contentOffset.x) / Int(scrollView.frame.width) + } } func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { - timer?.invalidate() - timer = nil + timerAutoScroll?.invalidate() + timerAutoScroll = nil } // MARK: - Action - @objc func actionCancel(_ sender: Any?) { + @objc func actionCancel() { dismiss(animated: true) { } } @IBAction func login(_ sender: Any) { - if let viewController = UIStoryboard(name: "NCLogin", bundle: nil).instantiateViewController(withIdentifier: "NCLogin") as? NCLogin { - viewController.controller = self.controller - self.navigationController?.pushViewController(viewController, animated: true) + if NCBrandOptions.shared.use_AppConfig { + let loginViewPage = UIStoryboard(name: "NCLogin", bundle: Bundle.main).instantiateViewController(identifier: "NCLogin") + navigationController?.pushViewController(loginViewPage, animated: true) + } else { + if NextcloudKit.shared.isNetworkReachable() { + appDelegate.openLogin(viewController: navigationController, selector: NCGlobal.shared.introLogin, openLoginWeb: false) + } else { + showNoInternetAlert() + } } } + + func showNoInternetAlert(){ + let alertController = UIAlertController(title: NSLocalizedString("_no_internet_alert_title_", comment: ""), message: NSLocalizedString("_no_internet_alert_message_", comment: ""), preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { action in })) + self.present(alertController, animated: true) + } @IBAction func signupWithProvider(_ sender: Any) { - if let viewController = UIStoryboard(name: "NCLogin", bundle: nil).instantiateViewController(withIdentifier: "NCLoginProvider") as? NCLoginProvider { - viewController.controller = self.controller - viewController.initialURLString = NCBrandOptions.shared.linkloginPreferredProviders - self.navigationController?.pushViewController(viewController, animated: true) - } + appDelegate.openLogin(selector: NCGlobal.shared.introSignup) + } + + @IBAction func signup(_ sender: Any) { + appDelegate.openLogin(selector: NCGlobal.shared.introSignup) } @IBAction func host(_ sender: Any) { diff --git a/Brand/LaunchScreen.storyboard b/Brand/LaunchScreen.storyboard index 26840f6195..59fe1c3dd1 100755 --- a/Brand/LaunchScreen.storyboard +++ b/Brand/LaunchScreen.storyboard @@ -1,9 +1,9 @@ - + - + @@ -17,16 +17,37 @@ - + + + + + + + + + + + + - + - - + - + + diff --git a/Brand/NCBrand.swift b/Brand/NCBrand.swift index e042698b24..361c20dbbe 100755 --- a/Brand/NCBrand.swift +++ b/Brand/NCBrand.swift @@ -1,15 +1,32 @@ -// SPDX-FileCopyrightText: Nextcloud GmbH -// SPDX-FileCopyrightText: 2017 Marino Faggiana -// SPDX-License-Identifier: GPL-3.0-or-later +// +// NCBrandColor.swift +// Nextcloud +// +// Created by Marino Faggiana on 24/04/17. +// Copyright (c) 2017 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// import UIKit -import NextcloudKit let userAgent: String = { let appVersion: String = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String - // Original Nextcloud useragent "Mozilla/5.0 (iOS) Nextcloud-iOS/\(appVersion)-Nextcloud" - let suffixBrand = NCBrandOptions.shared.brandUserAgent.isEmpty ? "" : "-\(NCBrandOptions.shared.brandUserAgent)" - return "Mozilla/5.0 (iOS) Nextcloud-iOS/\(appVersion)\(suffixBrand)" + // Original Nextcloud useragent "Mozilla/5.0 (iOS) Nextcloud-iOS/\(appVersion)" + return "Mozilla/5.0 (iOS) Magenta-iOS/\(appVersion)" }() /* @@ -20,66 +37,124 @@ let userAgent: String = { The codename embodies the concept of dynamic, living matter — reflecting our vision of a platform that is not only powerful and reliable, but also capable of continuous transformation and intelligent adaptation. */ -final class NCBrandOptions: @unchecked Sendable { - static let shared = NCBrandOptions() +//final class NCBrandOptions: @unchecked Sendable { +// static let shared = NCBrandOptions() - var brand: String = "Nextcloud" - var brandUserAgent: String = "" - var textCopyrightNextcloudiOS: String = "Nextcloud Matheria for iOS %@ © 2025" - var textCopyrightNextcloudServer: String = "Nextcloud Server %@" - var loginBaseUrl: String = "https://cloud.nextcloud.com" + var brand: String = "MagentaCLOUD" + var brandUserAgent: String = "MagentaCLOUD" + var textCopyrightNextcloudiOS: String = "MagentaCLOUD for iOS %@" + var textCopyrightNextcloudServer: String = "MagentaCLOUD Server %@" + var loginBaseUrl: String = "https://magentacloud.de" var pushNotificationServerProxy: String = "" var linkLoginHost: String = "https://nextcloud.com/install" var linkloginPreferredProviders: String = "https://nextcloud.com/signup-ios" var webLoginAutenticationProtocol: String = "nc://" // example "abc://" - var privacy: String = "https://nextcloud.com/privacy" + var privacy: String = "https://static.magentacloud.de/privacy/datenschutzhinweise_app.htm" var sourceCode: String = "https://github.com/nextcloud/ios" var mobileconfig: String = "/remote.php/dav/provisioning/apple-provisioning.mobileconfig" var appStoreUrl: String = "https://apps.apple.com/in/app/nextcloud/id1125420102" +@objc class NCBrandOptions: NSObject, @unchecked Sendable { + @objc static let shared: NCBrandOptions = { + let instance = NCBrandOptions() + return instance + }() + + @objc public var brand: String = "MagentaCLOUD" + @objc public var textCopyrightNextcloudiOS: String = "MagentaCLOUD for iOS %@" + @objc public var textCopyrightNextcloudServer: String = "MagentaCLOUD Server %@" + @objc public var loginBaseUrl: String = "https://magentacloud.de" + + @objc public var pushNotificationServerProxy: String = "https://push-notifications.nextcloud.com" + @objc public var linkLoginHost: String = "https://nextcloud.com/install" + @objc public var linkloginPreferredProviders: String = "https://nextcloud.com/signup-ios" + @objc public var webLoginAutenticationProtocol: String = "nc://" // example "abc://" + @objc public var privacy: String = "https://nextcloud.com/privacy" + @objc public var sourceCode: String = "https://github.com/nextcloud/ios" + @objc public var mobileconfig: String = "/remote.php/dav/provisioning/apple-provisioning.mobileconfig" + @objc public var appStoreUrl: String = "https://apps.apple.com/de/app/magentacloud-cloud-speicher/id312838242" + + // Personalized + @objc public var webCloseViewProtocolPersonalized: String = "" // example "abc://change/plan" Don't touch me !! + @objc public var folderBrandAutoUpload: String = "" // example "_auto_upload_folder_" Don't touch me !! // Auto Upload default folder - var folderDefaultAutoUpload: String = "Photos" + @objc public var folderDefaultAutoUpload: String = Locale.current.languageCode == "de" ? "Kamera-Medien" : "Camera-Media" // Capabilities Group - var capabilitiesGroup: String = "group.it.twsweb.Crypto-Cloud" - var capabilitiesGroupApps: String = "group.com.nextcloud.apps" - + var capabilitiesGroup: String = "group.de.magentacloud.next.dev2.client" + var capabilitiesGroupApps: String = "group.de.magentacloud.next.dev2.client.apps" + // Options + +//#if DEBUG + // QA : + @objc public var capabilitiesGroup: String = "group.com.t-systems.pu-ds.magentacloud.qa" + @objc public var capabilitiesGroupApps: String = "group.com.t-systems.pu-ds.magentacloud.qa" +//#else +// // PROD : +// @objc public var capabilitiesGroup: String = "group.de.telekom.Mediencenter" +// @objc public var capabilitiesGroupApps: String = "group.de.telekom.Mediencenter" +//#endif + // BRAND ONLY - var use_AppConfig: Bool = false // Don't touch me !! + var use_AppConfig: Bool = false + // Set use_login_web_personalized to true for prod and false for configurable path + @objc public var use_login_web_personalized: Bool = true // Don't touch me !! + @objc public var use_AppConfig: Bool = false // Don't touch me !! + @objc public var use_GroupApps: Bool = true // Don't touch me !! + @objc public var use_default_auto_upload: Bool = false // Use server theming color - var use_themingColor: Bool = true + var use_themingColor: Bool = false - var disable_intro: Bool = false - var disable_request_login_url: Bool = false - var disable_multiaccount: Bool = false + var disable_intro: Bool = true + var disable_request_login_url: Bool = true + var disable_multiaccount: Bool = true var disable_more_external_site: Bool = false var disable_openin_file: Bool = false // Don't touch me !! - var disable_crash_service: Bool = false + var disable_crash_service: Bool = true var disable_log: Bool = false var disable_mobileconfig: Bool = false - var disable_show_more_nextcloud_apps_in_settings: Bool = false + var disable_show_more_nextcloud_apps_in_settings: Bool = true var doNotAskPasscodeAtStartup: Bool = false var disable_source_code_in_settings: Bool = false var enforce_passcode_lock = false + @objc public var use_themingColor: Bool = false + @objc public var use_themingLogo: Bool = false + @objc public var use_storeLocalAutoUploadAll: Bool = false + @objc public var use_loginflowv2: Bool = false + + @objc var disable_intro: Bool = false//true + @objc var disable_request_login_url: Bool = false//true + @objc public var disable_multiaccount: Bool = true + @objc public var disable_manage_account: Bool = false + @objc var disable_more_external_site: Bool = false + @objc var disable_openin_file: Bool = false // Don't touch me !! + @objc var disable_crash_service: Bool = true + @objc var disable_log: Bool = false + @objc var disable_mobileconfig: Bool = false + @objc var disable_show_more_nextcloud_apps_in_settings: Bool = true + @objc var doNotAskPasscodeAtStartup: Bool = false + @objc var disable_source_code_in_settings: Bool = false + @objc var enforce_passcode_lock = false + @objc var use_in_app_browser_for_login = false var enforce_privacyScreenEnabled = false - // Example: (name: "Name 1", url: "https://cloud.nextcloud.com"),(name: "Name 2", url: "https://cloud.nextcloud.com") + // (name: "Name 1", url: "https://cloud.nextcloud.com"),(name: "Name 2", url: "https://cloud.nextcloud.com") var enforce_servers: [(name: String, url: String)] = [] // Internal option behaviour - var cleanUpDay: Int = 0 // Set default "Delete all cached files older than" possible days value are: 0, 1, 7, 30, 90, 180, 365 + @objc var cleanUpDay: Int = 0 // Set default "Delete all cached files older than" possible days value are: 0, 1, 7, 30, 90, 180, 365 // Max request/download/upload concurrent - let httpMaximumConnectionsPerHost: Int = 8 - let httpMaximumConnectionsPerHostInDownload: Int = 8 - let httpMaximumConnectionsPerHostInUpload: Int = 8 + let httpMaximumConnectionsPerHost: Int = 6 + let httpMaximumConnectionsPerHostInDownload: Int = 6 + let httpMaximumConnectionsPerHostInUpload: Int = 6 // Max request/download/upload process let numMaximumProcess: Int = 50 // Number of failed attempts after reset app - let resetAppPasscodeAttempts: Int = 10 + @objc let resetAppPasscodeAttempts: Int = 10 let passcodeSecondsFail: Int = 60 // Info Paging @@ -87,7 +162,7 @@ final class NCBrandOptions: @unchecked Sendable { case activity, sharing } - init() { + override init() { // wrapper AppConfig if let configurationManaged = UserDefaults.standard.dictionary(forKey: "com.apple.configuration.managed"), use_AppConfig { if let str = configurationManaged[NCGlobal.shared.configuration_brand] as? String { @@ -105,6 +180,9 @@ final class NCBrandOptions: @unchecked Sendable { if let str = configurationManaged[NCGlobal.shared.configuration_disable_log] as? String { disable_log = (str as NSString).boolValue } + if let str = configurationManaged[NCGlobal.shared.configuration_disable_manage_account] as? String { + disable_manage_account = (str as NSString).boolValue + } if let str = configurationManaged[NCGlobal.shared.configuration_disable_more_external_site] as? String { disable_more_external_site = (str as NSString).boolValue } @@ -129,12 +207,22 @@ final class NCBrandOptions: @unchecked Sendable { } } -final class NCBrandColor: @unchecked Sendable { - static let shared = NCBrandColor() +class NCBrandColor: NSObject, @unchecked Sendable { + @objc static let shared: NCBrandColor = { + let instance = NCBrandColor() + return instance + }() // This is rewrited from customet theme, default is Nextcloud color - let customer: UIColor = UIColor(red: 0.0 / 255.0, green: 130.0 / 255.0, blue: 201.0 / 255.0, alpha: 1.0) // Nextcloud : #0082C9 - var customerText: UIColor = .white + let customer: UIColor = UIColor(red: 226.0/255.0, green: 0.0/255.0, blue: 116.0/255.0, alpha: 1.0) + var customerText: UIColor = UIColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 1.0) + // Color + @objc let customer: UIColor = UIColor(red: 226.0/255.0, green: 0.0/255.0, blue: 116.0/255.0, alpha: 1.0) + @objc var customerText: UIColor = .white + + @objc var brand: UIColor // don't touch me + @objc var brandElement: UIColor // don't touch me + @objc var brandText: UIColor = UIColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 1.0) // INTERNAL DEFINE COLORS private var themingColor = ThreadSafeDictionary() @@ -149,7 +237,7 @@ final class NCBrandColor: @unchecked Sendable { let textColor: UIColor = .label let textColor2: UIColor = .secondaryLabel - var systemMint: UIColor { + @objc var systemMint: UIColor { get { return UIColor(red: 0.0 / 255.0, green: 199.0 / 255.0, blue: 190.0 / 255.0, alpha: 1.0) } @@ -173,7 +261,11 @@ final class NCBrandColor: @unchecked Sendable { } } - init() { } + override init() { + brand = customer + brandElement = customer + brandText = customerText + } /** Generate colors from the official nextcloud color. @@ -330,4 +422,78 @@ final class NCBrandColor: @unchecked Sendable { } return .white } + + @objc public var iconColor: UIColor{ + if #available(iOS 13.0, *) { + if UITraitCollection.current.userInterfaceStyle == .dark { + return UIColor(displayP3Red: 204.0/255.0, green: 204.0/255.0, blue: 204.0/255.0, alpha: 1.0) + }else { + return UIColor(red: 38.0/255.0, green: 38.0/255.0, blue: 38.0/255.0, alpha: 1.0) + } + } else { + return UIColor(red: 38.0/255.0, green: 38.0/255.0, blue: 38.0/255.0, alpha: 1.0) + } + } + + @objc public var notificationAction: UIColor { + return UIColor(red: 0/255.0, green: 153/255.0, blue: 255/255.0, alpha: 1.0) + } + + @objc public var secondarySystemGroupedBackground: UIColor = UIColor.secondarySystemGroupedBackground + @objc public var label: UIColor = UIColor.label + @objc public var backgroundForm: UIColor = UIColor(red: 244.0/255.0, green: 244.0/255.0, blue: 244.0/255.0, alpha: 1.0) + @objc public let graySoft: UIColor = UIColor(red: 162.0/255.0, green: 162.0/255.0, blue: 162.0/255.0, alpha: 0.5) + @objc public let systemGray4: UIColor = UIColor.systemGray4 + @objc public let systemBackground: UIColor = UIColor.systemBackground + @objc public let textInfo: UIColor = UIColor(red: 153.0/255.0, green: 153.0/255.0, blue: 153.0/255.0, alpha: 1.0) + @objc public let systemGray: UIColor = UIColor.systemGray + @objc public let customerDarkGrey: UIColor = UIColor(red: 38.0/255.0, green: 38.0/255.0, blue: 38.0/255.0, alpha: 1.0) + @objc public var fileFolderName: UIColor = UIColor(displayP3Red: 102.0/255.0, green: 102.0/255.0, blue: 102.0/255.0, alpha: 1.0) + @objc public let optionItem: UIColor = UIColor(red: 178.0/255.0, green: 178.0/255.0, blue: 178.0/255.0, alpha: 1.0) + @objc public var singleTitleColorButton: UIColor = UIColor(red: 25.0/255.0, green: 25.0/255.0, blue: 25.0/255.0, alpha: 1.0) + @objc public var shareCellTitleColor: UIColor = UIColor(displayP3Red: 242.0/255.0, green: 242.0/255.0, blue: 242.0/255.0, alpha: 1.0) + @objc public var gray60: UIColor { + if UITraitCollection.current.userInterfaceStyle == .dark { + return UIColor(red: 178.0/255.0, green: 178.0/255.0, blue: 178.0/255.0, alpha: 1.0) + } else { + return UIColor(red: 102.0/255.0, green: 102.0/255.0, blue: 102.0/255.0, alpha: 1.0) + } + } + @objc public var systemGray2: UIColor = UIColor.systemGray2 + @objc public var shareByEmailTextColor: UIColor = UIColor(displayP3Red: 13.0/255.0, green: 57.0/255.0, blue: 223.0/255.0, alpha: 1.0) + @objc public var memoryConsuptionBackground: UIColor { + if UITraitCollection.current.userInterfaceStyle == .dark { + return UIColor(red: 25.0/255.0, green: 25.0/255.0, blue: 25.0/255.0, alpha: 1.0) + } else { + return UIColor(red: 244.0/255.0, green: 244.0/255.0, blue: 244.0/255.0, alpha: 1.0) + } + } + @objc public var nmcGray0: UIColor{ + if UITraitCollection.current.userInterfaceStyle == .dark { + return UIColor(displayP3Red: 242.0/255.0, green: 242.0/255.0, blue: 242.0/255.0, alpha: 1.0) + }else { + return UIColor(red: 19.0/255.0, green: 19.0/255.0, blue: 19.0/255.0, alpha: 1.0) + } + } + @objc public var commonViewInfoText: UIColor = UIColor(displayP3Red: 102.0/255.0, green: 102.0/255.0, blue: 102.0/255.0, alpha: 1.0) + @objc public let progressColorGreen60: UIColor = UIColor(red: 115.0/255.0, green: 195.0/255.0, blue: 84.0/255.0, alpha: 1.0) + @objc public var seperatorRename: UIColor = UIColor(red: 235.0/255.0, green: 235.0/255.0, blue: 235.0/255.0, alpha: 1.0) + @objc public let gray: UIColor = UIColor(red: 104.0/255.0, green: 104.0/255.0, blue: 104.0/255.0, alpha: 1.0) + @objc public var nmcIconSharedWithMe: UIColor = UIColor(displayP3Red: 0.0/255.0, green: 153.0/255.0, blue: 255.0/255.0, alpha: 1.0) + + var shareBlueColor: UIColor{ + if UITraitCollection.current.userInterfaceStyle == .dark { + return UIColor(hex: "#7d94f9")! + }else { + return UIColor(hex: "#2238df")! + } + } + + var shareBlackColor: UIColor{ + if UITraitCollection.current.userInterfaceStyle == .dark { + return UIColor.white + }else { + return UIColor.black + } + } } diff --git a/Brand/Notification_Service_Extension.entitlements b/Brand/Notification_Service_Extension.entitlements index 9cf2061f89..f0d4f751b3 100644 --- a/Brand/Notification_Service_Extension.entitlements +++ b/Brand/Notification_Service_Extension.entitlements @@ -6,13 +6,25 @@ com.apple.security.application-groups - group.it.twsweb.Crypto-Cloud + group.de.magentacloud.next.dev2.client com.apple.security.network.client keychain-access-groups - $(AppIdentifierPrefix)it.twsweb.Crypto-Cloud + $(AppIdentifierPrefix)de.magentacloud.next.dev2.client + com.apple.security.app-sandbox + + com.apple.security.application-groups + + group.com.t-systems.pu-ds.magentacloud.qa + + com.apple.security.network.client + + keychain-access-groups + + $(AppIdentifierPrefix)MagentaCLOUD + diff --git a/Brand/Notification_Service_Extension.plist b/Brand/Notification_Service_Extension.plist index 7cba1da5f6..f79cb6c238 100644 --- a/Brand/Notification_Service_Extension.plist +++ b/Brand/Notification_Service_Extension.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion - $(CURRENT_PROJECT_VERSION) + 34247 NSExtension NSExtensionPointIdentifier @@ -27,5 +27,30 @@ NSExtensionPrincipalClass $(PRODUCT_MODULE_NAME).NotificationService + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Notification Service Extension + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSExtension + + NSExtensionPointIdentifier + com.apple.usernotifications.service + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).NotificationService + diff --git a/Brand/Share.entitlements b/Brand/Share.entitlements index 9cf2061f89..f0d4f751b3 100755 --- a/Brand/Share.entitlements +++ b/Brand/Share.entitlements @@ -6,13 +6,25 @@ com.apple.security.application-groups - group.it.twsweb.Crypto-Cloud + group.de.magentacloud.next.dev2.client com.apple.security.network.client keychain-access-groups - $(AppIdentifierPrefix)it.twsweb.Crypto-Cloud + $(AppIdentifierPrefix)de.magentacloud.next.dev2.client + com.apple.security.app-sandbox + + com.apple.security.application-groups + + group.com.t-systems.pu-ds.magentacloud.qa + + com.apple.security.network.client + + keychain-access-groups + + $(AppIdentifierPrefix)MagentaCLOUD + diff --git a/Brand/Share.plist b/Brand/Share.plist index 567991a236..cb142b9c3f 100755 --- a/Brand/Share.plist +++ b/Brand/Share.plist @@ -5,7 +5,7 @@ CFBundleDevelopmentRegion en CFBundleDisplayName - Nextcloud + MagentaCLOUD CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -19,11 +19,11 @@ CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion - $(CURRENT_PROJECT_VERSION) + 34247 NSAppTransportSecurity NSAllowsArbitraryLoads - + NSExtension @@ -31,12 +31,41 @@ NSExtensionActivationRule SUBQUERY (extensionItems, $extensionItem, SUBQUERY ($extensionItem.attachments,$attachment,(ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.data")).@count == $extensionItem.attachments.@count).@count > 0 + CFBundleDevelopmentRegion + en + CFBundleDisplayName + MagentaCLOUD + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + XPC! + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + NSExtension + + NSExtensionAttributes + + NSExtensionActivationRule + SUBQUERY (extensionItems, $extensionItem, SUBQUERY ($extensionItem.attachments,$attachment,(ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.data")).@count == $extensionItem.attachments.@count).@count > 0 - - NSExtensionMainStoryboard - MainInterface - NSExtensionPointIdentifier - com.apple.share-services - + + NSExtensionMainStoryboard + MainInterface + NSExtensionPointIdentifier + com.apple.share-services + diff --git a/Brand/Widget.entitlements b/Brand/Widget.entitlements index 9cf2061f89..9107ab40b6 100644 --- a/Brand/Widget.entitlements +++ b/Brand/Widget.entitlements @@ -6,13 +6,13 @@ com.apple.security.application-groups - group.it.twsweb.Crypto-Cloud + group.de.magentacloud.next.dev2.client com.apple.security.network.client keychain-access-groups - $(AppIdentifierPrefix)it.twsweb.Crypto-Cloud + $(AppIdentifierPrefix)de.magentacloud.next.dev2.client diff --git a/Brand/WidgetDashboardIntentHandler.entitlements b/Brand/WidgetDashboardIntentHandler.entitlements index 9cf2061f89..9107ab40b6 100644 --- a/Brand/WidgetDashboardIntentHandler.entitlements +++ b/Brand/WidgetDashboardIntentHandler.entitlements @@ -6,13 +6,13 @@ com.apple.security.application-groups - group.it.twsweb.Crypto-Cloud + group.de.magentacloud.next.dev2.client com.apple.security.network.client keychain-access-groups - $(AppIdentifierPrefix)it.twsweb.Crypto-Cloud + $(AppIdentifierPrefix)de.magentacloud.next.dev2.client diff --git a/Brand/iOSClient.entitlements b/Brand/iOSClient.entitlements index f4b9c9dcce..63987b375f 100755 --- a/Brand/iOSClient.entitlements +++ b/Brand/iOSClient.entitlements @@ -8,8 +8,8 @@ com.apple.security.application-groups - group.com.nextcloud.apps - group.it.twsweb.Crypto-Cloud + group.de.magentacloud.next.dev2.client.apps + group.de.magentacloud.next.dev2.client com.apple.security.device.audio-input @@ -23,7 +23,29 @@ keychain-access-groups - $(AppIdentifierPrefix)it.twsweb.Crypto-Cloud + $(AppIdentifierPrefix)de.magentacloud.next.dev2.client + aps-environment + development + com.apple.security.app-sandbox + + com.apple.security.application-groups + + group.com.t-systems.pu-ds.magentacloud.qa + + com.apple.security.device.audio-input + + com.apple.security.device.camera + + com.apple.security.network.client + + com.apple.security.personal-information.location + + com.apple.security.personal-information.photos-library + + keychain-access-groups + + $(AppIdentifierPrefix)MagentaCLOUD + diff --git a/Brand/iOSClient.plist b/Brand/iOSClient.plist index ec039e4074..b4aa6ca82b 100755 --- a/Brand/iOSClient.plist +++ b/Brand/iOSClient.plist @@ -12,7 +12,7 @@ CFBundleDevelopmentRegion en CFBundleDisplayName - Nextcloud + MagentaCLOUD CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -41,11 +41,9 @@ CFBundleVersion - $(CURRENT_PROJECT_VERSION) - ITSAppUsesNonExemptEncryption - - ITSEncryptionExportComplianceCode - 8e9f9874-938e-460b-a9be-f82cb3393971 + 34247 + ITSAppUsesNonExemptEncryption + LSApplicationQueriesSchemes nextcloudtalk @@ -60,7 +58,7 @@ NSAppTransportSecurity NSAllowsArbitraryLoads - + NSCameraUsageDescription Camera access is required to scan documents and make photo and video. @@ -194,5 +192,196 @@ + BGTaskSchedulerPermittedIdentifiers + + com.nextcloud.refreshTask + com.nextcloud.processingTask + + CFBundleAllowMixedLocalizations + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + MagentaCLOUD + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + $(MARKETING_VERSION) + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleSignature + ???? + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLName + it.twsweb.Nextcloud + CFBundleURLSchemes + + nextcloud + + + + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + ITSAppUsesNonExemptEncryption + + LSApplicationQueriesSchemes + + nextcloudtalk + nextcloudnotes + + LSMinimumSystemVersion + 12.3 + LSRequiresIPhoneOS + + LSSupportsOpeningDocumentsInPlace + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + NSCameraUsageDescription + Camera access is required to scan documents and make photo and video. + NSFaceIDUsageDescription + Face ID is required to authenticate using face recognition. + NSLocationAlwaysAndWhenInUseUsageDescription + The app will show your location on a map. + NSLocationAlwaysUsageDescription + The app will show your location on a map. + NSLocationWhenInUseUsageDescription + The app will show your location on a map. + NSMicrophoneUsageDescription + Microphone access is required to create voice notes. + NSPhotoLibraryAddUsageDescription + Photo library access is required to upload your photos and videos to your cloud. + NSPhotoLibraryUsageDescription + Photo library access is required to upload your photos and videos to your cloud. + NSUserActivityTypes + + AccountIntent + DashboardIntent + + NSUserTrackingUsageDescription + App would like to access IDFA for tracking purpose + PHPhotoLibraryPreventAutomaticLimitedAccessAlert + + UIAppFonts + + Inconsolata-Light.ttf + Inconsolata-Regular.ttf + Inconsolata-ExtraLight.ttf + Inconsolata-Medium.ttf + Inconsolata-Bold.ttf + Inconsolata-ExtraBold.ttf + Inconsolata-Black.ttf + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + + + + + UIBackgroundModes + + audio + fetch + processing + remote-notification + + UIFileSharingEnabled + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UIRequiresFullScreen + + UIStatusBarHidden + + UIStatusBarStyle + UIStatusBarStyleLightContent + UISupportedInterfaceOrientations + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + UIInterfaceOrientationPortrait + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + + UIViewControllerBasedStatusBarAppearance + + UTExportedTypeDeclarations + + + UTTypeConformsTo + + public.movie + + UTTypeDescription + Matroska Video File + UTTypeIconFiles + + UTTypeIdentifier + com.apple.quicktime.mkv + UTTypeReferenceURL + http://www.matroska.org/ + UTTypeTagSpecification + + public.filename-extension + + mkv + + + + + UTTypeConformsTo + + public.text + + UTTypeDescription + SRT Subtitle Format + UTTypeIconFiles + + UTTypeIdentifier + com.company.srt + UTTypeReferenceURL + + UTTypeTagSpecification + + public.filename-extension + + srt + + + + diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index d3dc9dee77..aa9120c180 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 3704EB2A23D5A58400455C5B /* NCMenu.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3704EB2923D5A58400455C5B /* NCMenu.storyboard */; }; 370D26AF248A3D7A00121797 /* NCCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370D26AE248A3D7A00121797 /* NCCellProtocol.swift */; }; 371B5A2E23D0B04500FAFAE9 /* NCMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371B5A2D23D0B04500FAFAE9 /* NCMenu.swift */; }; + 3781B9B023DB2B7E006B4B1D /* AppDelegate+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3781B9AF23DB2B7E006B4B1D /* AppDelegate+Menu.swift */; }; 8491B1CD273BBA82001C8C5B /* UIViewController+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8491B1CC273BBA82001C8C5B /* UIViewController+Menu.swift */; }; AA3C85E82D36B08C00F74F12 /* UITestBackend.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA3C85E72D36B08C00F74F12 /* UITestBackend.swift */; }; AA3C85EB2D36BBFB00F74F12 /* OCSResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA3C85EA2D36BBF400F74F12 /* OCSResponse.swift */; }; @@ -45,7 +46,6 @@ AAA7BC2E2D3E39F1008F1A22 /* CapabilitiesResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA7BC2D2D3E39EC008F1A22 /* CapabilitiesResponse.swift */; }; AAA7BC302D3E3B88008F1A22 /* CapabilityResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA7BC2F2D3E3B83008F1A22 /* CapabilityResponse.swift */; }; AABD0C8A2D5F67A400F009E6 /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = AABD0C892D5F67A200F009E6 /* XCUIElement.swift */; }; - AABD0C9B2D5F73FC00F009E6 /* Placeholder.swift in Sources */ = {isa = PBXBuildFile; fileRef = AABD0C9A2D5F73FA00F009E6 /* Placeholder.swift */; }; AAE330042D2ED20200B04903 /* NCShareNavigationTitleSetting.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE330032D2ED1FF00B04903 /* NCShareNavigationTitleSetting.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 */; }; @@ -91,6 +91,313 @@ AFCE353527E4ED5900FEA6C2 /* DateFormatter+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353427E4ED5900FEA6C2 /* DateFormatter+Extension.swift */; }; AFCE353727E4ED7B00FEA6C2 /* NCShareCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353627E4ED7B00FEA6C2 /* NCShareCells.swift */; }; AFCE353927E5DE0500FEA6C2 /* Shareable.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* Shareable.swift */; }; + B5BEBD2F2E93AD540002C9E5 /* iOSClient.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2A2E93AD540002C9E5 /* iOSClient.plist */; }; + B5BEBD302E93AD540002C9E5 /* Share.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2E2E93AD540002C9E5 /* Share.plist */; }; + B5BEBD312E93AD540002C9E5 /* Notification_Service_Extension.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2C2E93AD540002C9E5 /* Notification_Service_Extension.plist */; }; + B5BEBD322E93AD540002C9E5 /* File_Provider_Extension.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD282E93AD540002C9E5 /* File_Provider_Extension.plist */; }; + B5BEBD332E93AD540002C9E5 /* iOSClient.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2A2E93AD540002C9E5 /* iOSClient.plist */; }; + B5BEBD342E93AD540002C9E5 /* Share.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2E2E93AD540002C9E5 /* Share.plist */; }; + B5BEBD352E93AD540002C9E5 /* Notification_Service_Extension.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2C2E93AD540002C9E5 /* Notification_Service_Extension.plist */; }; + B5BEBD362E93AD540002C9E5 /* File_Provider_Extension.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD282E93AD540002C9E5 /* File_Provider_Extension.plist */; }; + B5BEBD372E93AD540002C9E5 /* iOSClient.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2A2E93AD540002C9E5 /* iOSClient.plist */; }; + B5BEBD382E93AD540002C9E5 /* Share.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2E2E93AD540002C9E5 /* Share.plist */; }; + B5BEBD392E93AD540002C9E5 /* Notification_Service_Extension.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2C2E93AD540002C9E5 /* Notification_Service_Extension.plist */; }; + B5BEBD3A2E93AD540002C9E5 /* File_Provider_Extension.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD282E93AD540002C9E5 /* File_Provider_Extension.plist */; }; + B5BEBD3B2E93AD540002C9E5 /* iOSClient.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2A2E93AD540002C9E5 /* iOSClient.plist */; }; + B5BEBD3C2E93AD540002C9E5 /* Share.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2E2E93AD540002C9E5 /* Share.plist */; }; + B5BEBD3D2E93AD540002C9E5 /* Notification_Service_Extension.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2C2E93AD540002C9E5 /* Notification_Service_Extension.plist */; }; + B5BEBD3E2E93AD540002C9E5 /* File_Provider_Extension.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD282E93AD540002C9E5 /* File_Provider_Extension.plist */; }; + B5BEBD3F2E93AD540002C9E5 /* iOSClient.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2A2E93AD540002C9E5 /* iOSClient.plist */; }; + B5BEBD402E93AD540002C9E5 /* Share.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2E2E93AD540002C9E5 /* Share.plist */; }; + B5BEBD412E93AD540002C9E5 /* Notification_Service_Extension.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2C2E93AD540002C9E5 /* Notification_Service_Extension.plist */; }; + B5BEBD422E93AD540002C9E5 /* File_Provider_Extension.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD282E93AD540002C9E5 /* File_Provider_Extension.plist */; }; + B5BEBD432E93AD540002C9E5 /* iOSClient.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2A2E93AD540002C9E5 /* iOSClient.plist */; }; + B5BEBD442E93AD540002C9E5 /* Share.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2E2E93AD540002C9E5 /* Share.plist */; }; + B5BEBD452E93AD540002C9E5 /* Notification_Service_Extension.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2C2E93AD540002C9E5 /* Notification_Service_Extension.plist */; }; + B5BEBD462E93AD540002C9E5 /* File_Provider_Extension.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD282E93AD540002C9E5 /* File_Provider_Extension.plist */; }; + B5BEBD472E93AD540002C9E5 /* iOSClient.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2A2E93AD540002C9E5 /* iOSClient.plist */; }; + B5BEBD482E93AD540002C9E5 /* Share.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2E2E93AD540002C9E5 /* Share.plist */; }; + B5BEBD492E93AD540002C9E5 /* Notification_Service_Extension.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2C2E93AD540002C9E5 /* Notification_Service_Extension.plist */; }; + B5BEBD4A2E93AD540002C9E5 /* File_Provider_Extension.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD282E93AD540002C9E5 /* File_Provider_Extension.plist */; }; + B5BEBD4B2E93AD540002C9E5 /* iOSClient.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2A2E93AD540002C9E5 /* iOSClient.plist */; }; + B5BEBD4C2E93AD540002C9E5 /* Share.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2E2E93AD540002C9E5 /* Share.plist */; }; + B5BEBD4D2E93AD540002C9E5 /* Notification_Service_Extension.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD2C2E93AD540002C9E5 /* Notification_Service_Extension.plist */; }; + B5BEBD4E2E93AD540002C9E5 /* File_Provider_Extension.plist in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD282E93AD540002C9E5 /* File_Provider_Extension.plist */; }; + B5BEBD522E93AE1C0002C9E5 /* TestConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD502E93AE1C0002C9E5 /* TestConstants.swift */; }; + B5BEBD532E93AE1C0002C9E5 /* BaseXCTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD4F2E93AE1C0002C9E5 /* BaseXCTestCase.swift */; }; + B5BEBD542E93AE1C0002C9E5 /* TestConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD502E93AE1C0002C9E5 /* TestConstants.swift */; }; + B5BEBD552E93AE1C0002C9E5 /* BaseXCTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD4F2E93AE1C0002C9E5 /* BaseXCTestCase.swift */; }; + B5BEBD562E93AE1C0002C9E5 /* TestConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD502E93AE1C0002C9E5 /* TestConstants.swift */; }; + B5BEBD572E93AE1C0002C9E5 /* BaseXCTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD4F2E93AE1C0002C9E5 /* BaseXCTestCase.swift */; }; + B5BEBD5B2E93AE2F0002C9E5 /* LoginIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD5A2E93AE2F0002C9E5 /* LoginIntegrationTests.swift */; }; + B5BEBD5C2E93AE2F0002C9E5 /* BaseIntegrationXCTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD582E93AE2F0002C9E5 /* BaseIntegrationXCTestCase.swift */; }; + B5BEBD5D2E93AE2F0002C9E5 /* FilesIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD592E93AE2F0002C9E5 /* FilesIntegrationTests.swift */; }; + B5BEBD6B2E93AE4B0002C9E5 /* SharingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD6A2E93AE4B0002C9E5 /* SharingTest.swift */; }; + B5BEBD6C2E93AE4B0002C9E5 /* AssetUploadTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD5E2E93AE4B0002C9E5 /* AssetUploadTest.swift */; }; + B5BEBD6D2E93AE4B0002C9E5 /* NCNotificationText.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD642E93AE4B0002C9E5 /* NCNotificationText.swift */; }; + B5BEBD6E2E93AE4B0002C9E5 /* SettingsTestCases.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD692E93AE4B0002C9E5 /* SettingsTestCases.swift */; }; + B5BEBD6F2E93AE4B0002C9E5 /* CollaboraTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD602E93AE4B0002C9E5 /* CollaboraTestCase.swift */; }; + B5BEBD702E93AE4B0002C9E5 /* MoveAndCopyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD632E93AE4B0002C9E5 /* MoveAndCopyTests.swift */; }; + B5BEBD712E93AE4B0002C9E5 /* MoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD622E93AE4B0002C9E5 /* MoreTests.swift */; }; + B5BEBD722E93AE4B0002C9E5 /* RenameFileTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD672E93AE4B0002C9E5 /* RenameFileTests.swift */; }; + B5BEBD732E93AE4B0002C9E5 /* AudioUploadTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD5F2E93AE4B0002C9E5 /* AudioUploadTests.swift */; }; + B5BEBD742E93AE4B0002C9E5 /* OnboardingTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD652E93AE4B0002C9E5 /* OnboardingTestCase.swift */; }; + B5BEBD752E93AE4B0002C9E5 /* E2EETests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD612E93AE4B0002C9E5 /* E2EETests.swift */; }; + B5BEBD762E93AE4B0002C9E5 /* ScanTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD682E93AE4B0002C9E5 /* ScanTests.swift */; }; + B5BEBD772E93AE4B0002C9E5 /* PrivacyPolicyTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD662E93AE4B0002C9E5 /* PrivacyPolicyTest.swift */; }; + B5BEBD7D2E93AEA30002C9E5 /* AnalyticsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD7B2E93AEA30002C9E5 /* AnalyticsService.swift */; }; + B5BEBD7E2E93AEA30002C9E5 /* MoEngageAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD782E93AEA30002C9E5 /* MoEngageAnalytics.swift */; }; + B5BEBD7F2E93AEA30002C9E5 /* AnalyticsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD7A2E93AEA30002C9E5 /* AnalyticsHelper.swift */; }; + B5BEBD802E93AEA30002C9E5 /* AnalyticsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD7B2E93AEA30002C9E5 /* AnalyticsService.swift */; }; + B5BEBD812E93AEA30002C9E5 /* MoEngageAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD782E93AEA30002C9E5 /* MoEngageAnalytics.swift */; }; + B5BEBD822E93AEA30002C9E5 /* AnalyticsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD7A2E93AEA30002C9E5 /* AnalyticsHelper.swift */; }; + B5BEBD832E93AEA30002C9E5 /* AnalyticsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD7B2E93AEA30002C9E5 /* AnalyticsService.swift */; }; + B5BEBD842E93AEA30002C9E5 /* MoEngageAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD782E93AEA30002C9E5 /* MoEngageAnalytics.swift */; }; + B5BEBD852E93AEA30002C9E5 /* AnalyticsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD7A2E93AEA30002C9E5 /* AnalyticsHelper.swift */; }; + B5BEBD862E93AEA30002C9E5 /* AnalyticsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD7B2E93AEA30002C9E5 /* AnalyticsService.swift */; }; + B5BEBD872E93AEA30002C9E5 /* MoEngageAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD782E93AEA30002C9E5 /* MoEngageAnalytics.swift */; }; + B5BEBD882E93AEA30002C9E5 /* AnalyticsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD7A2E93AEA30002C9E5 /* AnalyticsHelper.swift */; }; + B5BEBD892E93AEA30002C9E5 /* AnalyticsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD7B2E93AEA30002C9E5 /* AnalyticsService.swift */; }; + B5BEBD8A2E93AEA30002C9E5 /* MoEngageAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD782E93AEA30002C9E5 /* MoEngageAnalytics.swift */; }; + B5BEBD8B2E93AEA30002C9E5 /* AnalyticsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD7A2E93AEA30002C9E5 /* AnalyticsHelper.swift */; }; + B5BEBD8C2E93AEA30002C9E5 /* AnalyticsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD7B2E93AEA30002C9E5 /* AnalyticsService.swift */; }; + B5BEBD8D2E93AEA30002C9E5 /* MoEngageAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD782E93AEA30002C9E5 /* MoEngageAnalytics.swift */; }; + B5BEBD8E2E93AEA30002C9E5 /* AnalyticsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD7A2E93AEA30002C9E5 /* AnalyticsHelper.swift */; }; + B5BEBD8F2E93AEA30002C9E5 /* AnalyticsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD7B2E93AEA30002C9E5 /* AnalyticsService.swift */; }; + B5BEBD902E93AEA30002C9E5 /* MoEngageAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD782E93AEA30002C9E5 /* MoEngageAnalytics.swift */; }; + B5BEBD912E93AEA30002C9E5 /* AnalyticsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD7A2E93AEA30002C9E5 /* AnalyticsHelper.swift */; }; + B5BEBD942E93AED80002C9E5 /* AppUpdater.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD922E93AED80002C9E5 /* AppUpdater.swift */; }; + B5BEBD952E93AED80002C9E5 /* AppUpdater.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD922E93AED80002C9E5 /* AppUpdater.swift */; }; + B5BEBD962E93AED80002C9E5 /* AppUpdater.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD922E93AED80002C9E5 /* AppUpdater.swift */; }; + B5BEBD972E93AED80002C9E5 /* AppUpdater.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD922E93AED80002C9E5 /* AppUpdater.swift */; }; + B5BEBD982E93AED80002C9E5 /* AppUpdater.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD922E93AED80002C9E5 /* AppUpdater.swift */; }; + B5BEBD992E93AED80002C9E5 /* AppUpdater.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD922E93AED80002C9E5 /* AppUpdater.swift */; }; + B5BEBD9A2E93AED80002C9E5 /* AppUpdater.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD922E93AED80002C9E5 /* AppUpdater.swift */; }; + B5BEBDA32E93AF010002C9E5 /* AppUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD9B2E93AF010002C9E5 /* AppUtility.swift */; }; + B5BEBDA42E93AF010002C9E5 /* AdjustHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDA02E93AF010002C9E5 /* AdjustHelper.m */; }; + B5BEBDA52E93AF010002C9E5 /* TealiumHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDA12E93AF010002C9E5 /* TealiumHelper.swift */; }; + B5BEBDA62E93AF010002C9E5 /* NCEmptyDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD9C2E93AF010002C9E5 /* NCEmptyDataSet.swift */; }; + B5BEBDA72E93AF010002C9E5 /* NCEmptyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD9D2E93AF010002C9E5 /* NCEmptyView.xib */; }; + B5BEBDA82E93AF010002C9E5 /* NCEmptyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD9D2E93AF010002C9E5 /* NCEmptyView.xib */; }; + B5BEBDA92E93AF010002C9E5 /* AppUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD9B2E93AF010002C9E5 /* AppUtility.swift */; }; + B5BEBDAA2E93AF010002C9E5 /* AdjustHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDA02E93AF010002C9E5 /* AdjustHelper.m */; }; + B5BEBDAB2E93AF010002C9E5 /* TealiumHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDA12E93AF010002C9E5 /* TealiumHelper.swift */; }; + B5BEBDAC2E93AF010002C9E5 /* NCEmptyDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD9C2E93AF010002C9E5 /* NCEmptyDataSet.swift */; }; + B5BEBDAD2E93AF010002C9E5 /* AppUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD9B2E93AF010002C9E5 /* AppUtility.swift */; }; + B5BEBDAE2E93AF010002C9E5 /* AdjustHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDA02E93AF010002C9E5 /* AdjustHelper.m */; }; + B5BEBDAF2E93AF010002C9E5 /* TealiumHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDA12E93AF010002C9E5 /* TealiumHelper.swift */; }; + B5BEBDB02E93AF010002C9E5 /* NCEmptyDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD9C2E93AF010002C9E5 /* NCEmptyDataSet.swift */; }; + B5BEBDB12E93AF010002C9E5 /* NCEmptyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD9D2E93AF010002C9E5 /* NCEmptyView.xib */; }; + B5BEBDB22E93AF010002C9E5 /* AppUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD9B2E93AF010002C9E5 /* AppUtility.swift */; }; + B5BEBDB32E93AF010002C9E5 /* AdjustHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDA02E93AF010002C9E5 /* AdjustHelper.m */; }; + B5BEBDB42E93AF010002C9E5 /* TealiumHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDA12E93AF010002C9E5 /* TealiumHelper.swift */; }; + B5BEBDB52E93AF010002C9E5 /* NCEmptyDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD9C2E93AF010002C9E5 /* NCEmptyDataSet.swift */; }; + B5BEBDB62E93AF010002C9E5 /* NCEmptyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD9D2E93AF010002C9E5 /* NCEmptyView.xib */; }; + B5BEBDB72E93AF010002C9E5 /* AppUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD9B2E93AF010002C9E5 /* AppUtility.swift */; }; + B5BEBDB82E93AF010002C9E5 /* AdjustHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDA02E93AF010002C9E5 /* AdjustHelper.m */; }; + B5BEBDB92E93AF010002C9E5 /* TealiumHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDA12E93AF010002C9E5 /* TealiumHelper.swift */; }; + B5BEBDBA2E93AF010002C9E5 /* NCEmptyDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD9C2E93AF010002C9E5 /* NCEmptyDataSet.swift */; }; + B5BEBDBB2E93AF010002C9E5 /* NCEmptyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD9D2E93AF010002C9E5 /* NCEmptyView.xib */; }; + B5BEBDBC2E93AF010002C9E5 /* AppUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD9B2E93AF010002C9E5 /* AppUtility.swift */; }; + B5BEBDBD2E93AF010002C9E5 /* AdjustHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDA02E93AF010002C9E5 /* AdjustHelper.m */; }; + B5BEBDBE2E93AF010002C9E5 /* TealiumHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDA12E93AF010002C9E5 /* TealiumHelper.swift */; }; + B5BEBDBF2E93AF010002C9E5 /* NCEmptyDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD9C2E93AF010002C9E5 /* NCEmptyDataSet.swift */; }; + B5BEBDC02E93AF010002C9E5 /* NCEmptyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD9D2E93AF010002C9E5 /* NCEmptyView.xib */; }; + B5BEBDC12E93AF010002C9E5 /* NCEmptyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBD9D2E93AF010002C9E5 /* NCEmptyView.xib */; }; + B5BEBDC22E93AF010002C9E5 /* AppUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD9B2E93AF010002C9E5 /* AppUtility.swift */; }; + B5BEBDC32E93AF010002C9E5 /* AdjustHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDA02E93AF010002C9E5 /* AdjustHelper.m */; }; + B5BEBDC42E93AF010002C9E5 /* TealiumHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDA12E93AF010002C9E5 /* TealiumHelper.swift */; }; + B5BEBDC52E93AF010002C9E5 /* NCEmptyDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD9C2E93AF010002C9E5 /* NCEmptyDataSet.swift */; }; + B5BEBDC72E93AF7E0002C9E5 /* NCLoginWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDC62E93AF7E0002C9E5 /* NCLoginWeb.swift */; }; + B5BEBDC92E93AFF10002C9E5 /* NCSelectableNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDC82E93AFF10002C9E5 /* NCSelectableNavigationView.swift */; }; + B5BEBDCC2E93B0210002C9E5 /* NCSectionHeaderMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDCA2E93B0210002C9E5 /* NCSectionHeaderMenu.swift */; }; + B5BEBDCD2E93B0210002C9E5 /* NCSectionHeaderMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDCB2E93B0210002C9E5 /* NCSectionHeaderMenu.xib */; }; + B5BEBDCE2E93B0210002C9E5 /* NCSectionHeaderMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDCA2E93B0210002C9E5 /* NCSectionHeaderMenu.swift */; }; + B5BEBDCF2E93B0210002C9E5 /* NCSectionHeaderMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDCB2E93B0210002C9E5 /* NCSectionHeaderMenu.xib */; }; + B5BEBDD62E93B2450002C9E5 /* NCCreateFormUploadDocuments.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDD12E93B2450002C9E5 /* NCCreateFormUploadDocuments.swift */; }; + B5BEBDD72E93B2450002C9E5 /* TextTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDD42E93B2450002C9E5 /* TextTableViewCell.swift */; }; + B5BEBDD82E93B2450002C9E5 /* NCCreateFormUploadVoiceNote.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDD32E93B2450002C9E5 /* NCCreateFormUploadVoiceNote.swift */; }; + B5BEBDD92E93B2450002C9E5 /* TextTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDD52E93B2450002C9E5 /* TextTableViewCell.xib */; }; + B5BEBDDA2E93B2450002C9E5 /* NCCreateFormUploadDocuments.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDD02E93B2450002C9E5 /* NCCreateFormUploadDocuments.storyboard */; }; + B5BEBDDB2E93B2450002C9E5 /* NCCreateFormUploadVoiceNote.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDD22E93B2450002C9E5 /* NCCreateFormUploadVoiceNote.storyboard */; }; + B5BEBDDC2E93B2450002C9E5 /* NCCreateFormUploadDocuments.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDD12E93B2450002C9E5 /* NCCreateFormUploadDocuments.swift */; }; + B5BEBDDD2E93B2450002C9E5 /* TextTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDD42E93B2450002C9E5 /* TextTableViewCell.swift */; }; + B5BEBDDE2E93B2450002C9E5 /* NCCreateFormUploadVoiceNote.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDD32E93B2450002C9E5 /* NCCreateFormUploadVoiceNote.swift */; }; + B5BEBDDF2E93B2450002C9E5 /* TextTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDD52E93B2450002C9E5 /* TextTableViewCell.xib */; }; + B5BEBDE02E93B2450002C9E5 /* NCCreateFormUploadDocuments.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDD02E93B2450002C9E5 /* NCCreateFormUploadDocuments.storyboard */; }; + B5BEBDE12E93B2450002C9E5 /* NCCreateFormUploadVoiceNote.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDD22E93B2450002C9E5 /* NCCreateFormUploadVoiceNote.storyboard */; }; + B5BEBDE32E93BD6F0002C9E5 /* NCMediaCommandView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDE22E93BD6F0002C9E5 /* NCMediaCommandView.xib */; }; + B5BEBDE92E93BDB40002C9E5 /* FolderPathCustomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDE42E93BDB40002C9E5 /* FolderPathCustomCell.swift */; }; + B5BEBDEA2E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDE62E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift */; }; + B5BEBDEB2E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDE72E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib */; }; + B5BEBDEC2E93BDB40002C9E5 /* FolderPathCustomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDE52E93BDB40002C9E5 /* FolderPathCustomCell.xib */; }; + B5BEBDED2E93BDB40002C9E5 /* FolderPathCustomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDE42E93BDB40002C9E5 /* FolderPathCustomCell.swift */; }; + B5BEBDEE2E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDE62E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift */; }; + B5BEBDEF2E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDE72E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib */; }; + B5BEBDF02E93BDB40002C9E5 /* FolderPathCustomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDE52E93BDB40002C9E5 /* FolderPathCustomCell.xib */; }; + B5BEBDF12E93BDB40002C9E5 /* FolderPathCustomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDE42E93BDB40002C9E5 /* FolderPathCustomCell.swift */; }; + B5BEBDF22E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDE62E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift */; }; + B5BEBDF32E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDE72E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib */; }; + B5BEBDF42E93BDB40002C9E5 /* FolderPathCustomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDE52E93BDB40002C9E5 /* FolderPathCustomCell.xib */; }; + B5BEBDF52E93BDB40002C9E5 /* FolderPathCustomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDE42E93BDB40002C9E5 /* FolderPathCustomCell.swift */; }; + B5BEBDF62E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDE62E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift */; }; + B5BEBDF72E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDE72E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib */; }; + B5BEBDF82E93BDB40002C9E5 /* FolderPathCustomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDE52E93BDB40002C9E5 /* FolderPathCustomCell.xib */; }; + B5BEBDF92E93BDB40002C9E5 /* FolderPathCustomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDE42E93BDB40002C9E5 /* FolderPathCustomCell.swift */; }; + B5BEBDFA2E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDE62E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift */; }; + B5BEBDFB2E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDE72E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib */; }; + B5BEBDFC2E93BDB40002C9E5 /* FolderPathCustomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDE52E93BDB40002C9E5 /* FolderPathCustomCell.xib */; }; + B5BEBDFD2E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDE72E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib */; }; + B5BEBDFE2E93BDB40002C9E5 /* FolderPathCustomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDE52E93BDB40002C9E5 /* FolderPathCustomCell.xib */; }; + B5BEBDFF2E93BDB40002C9E5 /* FolderPathCustomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDE42E93BDB40002C9E5 /* FolderPathCustomCell.swift */; }; + B5BEBE002E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDE62E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift */; }; + B5BEBE012E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDE72E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib */; }; + B5BEBE022E93BDB40002C9E5 /* FolderPathCustomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBDE52E93BDB40002C9E5 /* FolderPathCustomCell.xib */; }; + B5BEBE032E93BDB40002C9E5 /* FolderPathCustomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDE42E93BDB40002C9E5 /* FolderPathCustomCell.swift */; }; + B5BEBE042E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBDE62E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift */; }; + B5BEBE062E93BE0C0002C9E5 /* NCCreateFormUploadScanDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBE052E93BE0C0002C9E5 /* NCCreateFormUploadScanDocument.swift */; }; + B5BEBE1A2E93BE200002C9E5 /* PNGImageSaveSwitchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBE112E93BE200002C9E5 /* PNGImageSaveSwitchView.swift */; }; + B5BEBE1B2E93BE200002C9E5 /* FileNameInputTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBE072E93BE200002C9E5 /* FileNameInputTextField.swift */; }; + B5BEBE1C2E93BE200002C9E5 /* PdfWithoutOcrSwitchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBE0F2E93BE200002C9E5 /* PdfWithoutOcrSwitchView.swift */; }; + B5BEBE1D2E93BE200002C9E5 /* TextFileWithOcrSwitchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBE172E93BE200002C9E5 /* TextFileWithOcrSwitchView.swift */; }; + B5BEBE1E2E93BE200002C9E5 /* ScanDocumentPathView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBE132E93BE200002C9E5 /* ScanDocumentPathView.swift */; }; + B5BEBE1F2E93BE200002C9E5 /* SetPDFPasswordSwitchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBE152E93BE200002C9E5 /* SetPDFPasswordSwitchView.swift */; }; + B5BEBE202E93BE200002C9E5 /* JPGImageSaveSwitchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBE092E93BE200002C9E5 /* JPGImageSaveSwitchView.swift */; }; + B5BEBE212E93BE200002C9E5 /* PasswordInputField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBE0B2E93BE200002C9E5 /* PasswordInputField.swift */; }; + B5BEBE222E93BE200002C9E5 /* PdfWithOcrSwitchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBE0D2E93BE200002C9E5 /* PdfWithOcrSwitchView.swift */; }; + B5BEBE232E93BE200002C9E5 /* PasswordInputField.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBE0C2E93BE200002C9E5 /* PasswordInputField.xib */; }; + B5BEBE242E93BE200002C9E5 /* ScanDocumentPathView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBE142E93BE200002C9E5 /* ScanDocumentPathView.xib */; }; + B5BEBE252E93BE200002C9E5 /* SetPDFPasswordSwitchView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBE162E93BE200002C9E5 /* SetPDFPasswordSwitchView.xib */; }; + B5BEBE262E93BE200002C9E5 /* PdfWithOcrSwitchView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBE0E2E93BE200002C9E5 /* PdfWithOcrSwitchView.xib */; }; + B5BEBE272E93BE200002C9E5 /* PNGImageSaveSwitchView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBE122E93BE200002C9E5 /* PNGImageSaveSwitchView.xib */; }; + B5BEBE282E93BE200002C9E5 /* FileNameInputTextField.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBE082E93BE200002C9E5 /* FileNameInputTextField.xib */; }; + B5BEBE292E93BE200002C9E5 /* TextFileWithOcrSwitchView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBE182E93BE200002C9E5 /* TextFileWithOcrSwitchView.xib */; }; + B5BEBE2A2E93BE200002C9E5 /* PdfWithoutOcrSwitchView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBE102E93BE200002C9E5 /* PdfWithoutOcrSwitchView.xib */; }; + B5BEBE2B2E93BE200002C9E5 /* JPGImageSaveSwitchView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5BEBE0A2E93BE200002C9E5 /* JPGImageSaveSwitchView.xib */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B5BEBD192E93A5260002C9E5 /* Shareable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD182E93A5260002C9E5 /* Shareable.swift */; }; + B5BEBD1E2E93A74C0002C9E5 /* CreateLinkFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD1A2E93A74C0002C9E5 /* CreateLinkFooterView.swift */; }; + B5BEBD1F2E93A74C0002C9E5 /* NCPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD1B2E93A74C0002C9E5 /* NCPermissions.swift */; }; + B5BEBD202E93A74C0002C9E5 /* NCShareEmailLinkHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD1C2E93A74C0002C9E5 /* NCShareEmailLinkHeaderView.swift */; }; + B5BEBD212E93A74C0002C9E5 /* NoSharesFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD1D2E93A74C0002C9E5 /* NoSharesFooterView.swift */; }; + B5BEBD222E93A74C0002C9E5 /* CreateLinkFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD1A2E93A74C0002C9E5 /* CreateLinkFooterView.swift */; }; + B5BEBD232E93A74C0002C9E5 /* NCPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD1B2E93A74C0002C9E5 /* NCPermissions.swift */; }; + B5BEBD242E93A74C0002C9E5 /* NCShareEmailLinkHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD1C2E93A74C0002C9E5 /* NCShareEmailLinkHeaderView.swift */; }; + B5BEBD252E93A74C0002C9E5 /* NoSharesFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BEBD1D2E93A74C0002C9E5 /* NoSharesFooterView.swift */; }; + B5E2E6D42DAE52B500AB2EDD /* SharingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E2E6D32DAE52B500AB2EDD /* SharingTest.swift */; }; + B5E2E6D72DAE571200AB2EDD /* PasswordInputField.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5E2E6D62DAE571200AB2EDD /* PasswordInputField.xib */; }; + B5E2E6D82DAE571200AB2EDD /* PasswordInputField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E2E6D52DAE571200AB2EDD /* PasswordInputField.swift */; }; + B5E2E6DD2DAE573B00AB2EDD /* NCFilePermissionEditCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5E2E6DC2DAE573B00AB2EDD /* NCFilePermissionEditCell.xib */; }; + B5E2E6DE2DAE573B00AB2EDD /* NCFilePermissionCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5E2E6DA2DAE573B00AB2EDD /* NCFilePermissionCell.xib */; }; + B5E2E6DF2DAE573B00AB2EDD /* NCFilePermissionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E2E6D92DAE573B00AB2EDD /* NCFilePermissionCell.swift */; }; + B5E2E6E02DAE573B00AB2EDD /* NCFilePermissionEditCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E2E6DB2DAE573B00AB2EDD /* NCFilePermissionEditCell.swift */; }; + B5E2E6E22DAE59CD00AB2EDD /* NCShareAdvancePermissionHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5E2E6E12DAE59CD00AB2EDD /* NCShareAdvancePermissionHeader.xib */; }; + B5E2E6E72DAE59F000AB2EDD /* NCShareHeaderCustomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5E2E6E42DAE59F000AB2EDD /* NCShareHeaderCustomCell.xib */; }; + B5E2E6E82DAE59F000AB2EDD /* NCShareTextInputCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5E2E6E62DAE59F000AB2EDD /* NCShareTextInputCell.xib */; }; + B5E2E6E92DAE59F000AB2EDD /* NCShareTextInputCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E2E6E52DAE59F000AB2EDD /* NCShareTextInputCell.swift */; }; + B5E2E6EA2DAE59F000AB2EDD /* NCShareHeaderCustomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E2E6E32DAE59F000AB2EDD /* NCShareHeaderCustomCell.swift */; }; + B5E2E6ED2DAE66AF00AB2EDD /* NCShareEmailFieldCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5E2E6EC2DAE66AF00AB2EDD /* NCShareEmailFieldCell.xib */; }; + B5E2E6EE2DAE66AF00AB2EDD /* NCShareEmailFieldCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E2E6EB2DAE66AF00AB2EDD /* NCShareEmailFieldCell.swift */; }; + B5E2E6F02DAE6E3F00AB2EDD /* ShareDownloadLimitNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E2E6EF2DAE6E3F00AB2EDD /* ShareDownloadLimitNetwork.swift */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B5C9801E2DACEB5A0041B146 /* NCCollectionViewCommon+SwipeCollectionViewCellDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C9801D2DACEB5A0041B146 /* NCCollectionViewCommon+SwipeCollectionViewCellDelegate.swift */; }; + B5C980202DAD201A0041B146 /* NCSortMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C9801F2DAD201A0041B146 /* NCSortMenu.swift */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B5C980182DACD51C0041B146 /* NCMediaCommandView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5C980172DACD51C0041B146 /* NCMediaCommandView.xib */; }; + B5C9801A2DACD56C0041B146 /* NCMedia+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C980192DACD56C0041B146 /* NCMedia+Menu.swift */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B52FAED52DA8F616001AB1BD /* NCSelectableNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FAED42DA8F616001AB1BD /* NCSelectableNavigationView.swift */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B52FAED32DA8F22F001AB1BD /* MoveAndCopyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FAED22DA8F22F001AB1BD /* MoveAndCopyTests.swift */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B52FAEAA2DA8EF0C001AB1BD /* ScanTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FAEA92DA8EF0C001AB1BD /* ScanTests.swift */; }; + B52FAEAC2DA8EF2C001AB1BD /* NCCreateFormUploadScanDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FAEAB2DA8EF2C001AB1BD /* NCCreateFormUploadScanDocument.swift */; }; + B52FAEC02DA8EF84001AB1BD /* FileNameInputTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FAEAD2DA8EF84001AB1BD /* FileNameInputTextField.swift */; }; + B52FAEC12DA8EF84001AB1BD /* ScanDocumentPathView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FAEB92DA8EF84001AB1BD /* ScanDocumentPathView.swift */; }; + B52FAEC22DA8EF84001AB1BD /* PNGImageSaveSwitchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FAEB72DA8EF84001AB1BD /* PNGImageSaveSwitchView.swift */; }; + B52FAEC32DA8EF84001AB1BD /* SetPDFPasswordSwitchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FAEBB2DA8EF84001AB1BD /* SetPDFPasswordSwitchView.swift */; }; + B52FAEC42DA8EF84001AB1BD /* PdfWithOcrSwitchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FAEB32DA8EF84001AB1BD /* PdfWithOcrSwitchView.swift */; }; + B52FAEC52DA8EF84001AB1BD /* PasswordInputField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FAEB12DA8EF84001AB1BD /* PasswordInputField.swift */; }; + B52FAEC62DA8EF84001AB1BD /* JPGImageSaveSwitchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FAEAF2DA8EF84001AB1BD /* JPGImageSaveSwitchView.swift */; }; + B52FAEC72DA8EF84001AB1BD /* PdfWithoutOcrSwitchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FAEB52DA8EF84001AB1BD /* PdfWithoutOcrSwitchView.swift */; }; + B52FAEC82DA8EF84001AB1BD /* TextFileWithOcrSwitchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FAEBD2DA8EF84001AB1BD /* TextFileWithOcrSwitchView.swift */; }; + B52FAEC92DA8EF84001AB1BD /* PdfWithOcrSwitchView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B52FAEB42DA8EF84001AB1BD /* PdfWithOcrSwitchView.xib */; }; + B52FAECA2DA8EF84001AB1BD /* PasswordInputField.xib in Resources */ = {isa = PBXBuildFile; fileRef = B52FAEB22DA8EF84001AB1BD /* PasswordInputField.xib */; }; + B52FAECB2DA8EF84001AB1BD /* ScanDocumentPathView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B52FAEBA2DA8EF84001AB1BD /* ScanDocumentPathView.xib */; }; + B52FAECC2DA8EF84001AB1BD /* SetPDFPasswordSwitchView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B52FAEBC2DA8EF84001AB1BD /* SetPDFPasswordSwitchView.xib */; }; + B52FAECD2DA8EF84001AB1BD /* PNGImageSaveSwitchView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B52FAEB82DA8EF84001AB1BD /* PNGImageSaveSwitchView.xib */; }; + B52FAECE2DA8EF84001AB1BD /* FileNameInputTextField.xib in Resources */ = {isa = PBXBuildFile; fileRef = B52FAEAE2DA8EF84001AB1BD /* FileNameInputTextField.xib */; }; + B52FAECF2DA8EF84001AB1BD /* TextFileWithOcrSwitchView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B52FAEBE2DA8EF84001AB1BD /* TextFileWithOcrSwitchView.xib */; }; + B52FAED02DA8EF84001AB1BD /* JPGImageSaveSwitchView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B52FAEB02DA8EF84001AB1BD /* JPGImageSaveSwitchView.xib */; }; + B52FAED12DA8EF84001AB1BD /* PdfWithoutOcrSwitchView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B52FAEB62DA8EF84001AB1BD /* PdfWithoutOcrSwitchView.xib */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B52FAEA12DA8ED40001AB1BD /* AudioUploadTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FAEA02DA8ED40001AB1BD /* AudioUploadTests.swift */; }; + B52FAEA42DA8EE60001AB1BD /* NCManageAutoUploadFileName.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FAEA32DA8EE60001AB1BD /* NCManageAutoUploadFileName.swift */; }; + B52FAEA82DA8EE99001AB1BD /* CCManageAutoUpload.m in Sources */ = {isa = PBXBuildFile; fileRef = B52FAEA72DA8EE99001AB1BD /* CCManageAutoUpload.m */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B52FAE902DA8D9E1001AB1BD /* CollaboraTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FAE8F2DA8D9E1001AB1BD /* CollaboraTestCase.swift */; }; + B52FAE932DA8DCB2001AB1BD /* NCCreateFormUploadDocuments.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B52FAE912DA8DCB2001AB1BD /* NCCreateFormUploadDocuments.storyboard */; }; + B52FAE942DA8DCB2001AB1BD /* NCCreateFormUploadDocuments.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FAE922DA8DCB2001AB1BD /* NCCreateFormUploadDocuments.swift */; }; + B52FAE9C2DA8DED9001AB1BD /* NCCreateDocumentCustomTextField.xib in Resources */ = {isa = PBXBuildFile; fileRef = B52FAE9A2DA8DED9001AB1BD /* NCCreateDocumentCustomTextField.xib */; }; + B52FAE9D2DA8DED9001AB1BD /* FolderPathCustomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B52FAE982DA8DED9001AB1BD /* FolderPathCustomCell.xib */; }; + B52FAE9E2DA8DED9001AB1BD /* NCCreateDocumentCustomTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FAE992DA8DED9001AB1BD /* NCCreateDocumentCustomTextField.swift */; }; + B52FAE9F2DA8DED9001AB1BD /* FolderPathCustomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FAE972DA8DED9001AB1BD /* FolderPathCustomCell.swift */; }; + C04E2F232A17BB4D001BAD85 /* FilesIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C04E2F222A17BB4D001BAD85 /* FilesIntegrationTests.swift */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B529E40D2E8D1F8B006D9131 /* NCManageE2EE.swift in Sources */ = {isa = PBXBuildFile; fileRef = B529E40C2E8D1F8B006D9131 /* NCManageE2EE.swift */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B568C2B72DA7B5060072FCB4 /* SettingsTestCases.swift in Sources */ = {isa = PBXBuildFile; fileRef = B568C2B62DA7B5060072FCB4 /* SettingsTestCases.swift */; }; + B568C2B92DA7CCC10072FCB4 /* CCAdvanced.m in Sources */ = {isa = PBXBuildFile; fileRef = B568C2B82DA7CCC10072FCB4 /* CCAdvanced.m */; }; + B568C2BE2DA7CCDB0072FCB4 /* MagentaCloudVersionView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B568C2BD2DA7CCDB0072FCB4 /* MagentaCloudVersionView.xib */; }; + B568C2BF2DA7CCDB0072FCB4 /* MagentaCloudVersionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B568C2BC2DA7CCDB0072FCB4 /* MagentaCloudVersionView.swift */; }; + B568C2C02DA7CCDB0072FCB4 /* ImprintViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B568C2BB2DA7CCDB0072FCB4 /* ImprintViewController.swift */; }; + B568C2C12DA7CCDB0072FCB4 /* HelpViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B568C2BA2DA7CCDB0072FCB4 /* HelpViewController.swift */; }; + B568C2C42DA7CCEA0072FCB4 /* OpenSourceSoftwareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B568C2C32DA7CCEA0072FCB4 /* OpenSourceSoftwareViewController.swift */; }; + B568C2C52DA7CCEA0072FCB4 /* NCSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = B568C2C22DA7CCEA0072FCB4 /* NCSettings.m */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B568C2B12DA7AA5F0072FCB4 /* MoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B568C2B02DA7AA5F0072FCB4 /* MoreTests.swift */; }; + B568C2B32DA7AAAE0072FCB4 /* NCMoreUserCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B568C2B22DA7AAAE0072FCB4 /* NCMoreUserCell.xib */; }; + B568C2B52DA7AADD0072FCB4 /* NCMoreUserCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B568C2B42DA7AADD0072FCB4 /* NCMoreUserCell.swift */; }; + C04E2F232A17BB4D001BAD85 /* FilesIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C04E2F222A17BB4D001BAD85 /* FilesIntegrationTests.swift */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B529E4072E8D1C3E006D9131 /* NCUploadAssets.swift in Sources */ = {isa = PBXBuildFile; fileRef = B529E4062E8D1C3E006D9131 /* NCUploadAssets.swift */; }; + B529E4082E8D1C3E006D9131 /* NCUploadAssets.swift in Sources */ = {isa = PBXBuildFile; fileRef = B529E4062E8D1C3E006D9131 /* NCUploadAssets.swift */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B543154E2DA6913C00981E7E /* AudioUploadTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B543154D2DA6913C00981E7E /* AudioUploadTests.swift */; }; + B54315552DA6929700981E7E /* NCCreateFormUploadVoiceNote.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54315522DA6929700981E7E /* NCCreateFormUploadVoiceNote.swift */; }; + B543155A2DA6929700981E7E /* NCCreateFormUploadVoiceNote.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B54315512DA6929700981E7E /* NCCreateFormUploadVoiceNote.storyboard */; }; + B543155B2DA6929700981E7E /* NCCreateFormUploadVoiceNote.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54315522DA6929700981E7E /* NCCreateFormUploadVoiceNote.swift */; }; + B543155C2DA6929700981E7E /* FolderPathCustomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B543154F2DA6929700981E7E /* FolderPathCustomCell.swift */; }; + B543155D2DA6929700981E7E /* TextTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54315532DA6929700981E7E /* TextTableViewCell.swift */; }; + B543155E2DA6929700981E7E /* TextTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B54315542DA6929700981E7E /* TextTableViewCell.xib */; }; + B543155F2DA6929700981E7E /* FolderPathCustomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B54315502DA6929700981E7E /* FolderPathCustomCell.xib */; }; + B54315602DA6929700981E7E /* NCCreateFormUploadVoiceNote.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B54315512DA6929700981E7E /* NCCreateFormUploadVoiceNote.storyboard */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B543154C2DA690B700981E7E /* NCNotificationText.swift in Sources */ = {isa = PBXBuildFile; fileRef = B543154B2DA690B700981E7E /* NCNotificationText.swift */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B54315362DA64EB100981E7E /* PrivacyPolicyTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54315352DA64EB100981E7E /* PrivacyPolicyTest.swift */; }; + B54315412DA669C700981E7E /* InitialPrivacySettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54315392DA669C700981E7E /* InitialPrivacySettingsViewController.swift */; }; + B54315422DA669C700981E7E /* RequiredDataCollectionSwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = B543153D2DA669C700981E7E /* RequiredDataCollectionSwitch.swift */; }; + B54315432DA669C700981E7E /* PrivacySettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B543153C2DA669C700981E7E /* PrivacySettingsViewController.swift */; }; + B54315442DA669C700981E7E /* AnalysisDataCollectionSwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54315372DA669C700981E7E /* AnalysisDataCollectionSwitch.swift */; }; + B54315452DA669C700981E7E /* PrivacyPolicyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B543153B2DA669C700981E7E /* PrivacyPolicyViewController.swift */; }; + B54315462DA669C700981E7E /* SaveSettingsCustomButtonCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B543153F2DA669C700981E7E /* SaveSettingsCustomButtonCell.swift */; }; + B54315472DA669C700981E7E /* AnalysisDataCollectionSwitch.xib in Resources */ = {isa = PBXBuildFile; fileRef = B54315382DA669C700981E7E /* AnalysisDataCollectionSwitch.xib */; }; + B54315482DA669C700981E7E /* NCSettings.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B543153A2DA669C700981E7E /* NCSettings.storyboard */; }; + B54315492DA669C700981E7E /* SaveSettingsCustomButtonCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B54315402DA669C700981E7E /* SaveSettingsCustomButtonCell.xib */; }; + B543154A2DA669C700981E7E /* RequiredDataCollectionSwitch.xib in Resources */ = {isa = PBXBuildFile; fileRef = B543153E2DA669C700981E7E /* RequiredDataCollectionSwitch.xib */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B54315322DA64BAF00981E7E /* OnboardingTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54315312DA64BAF00981E7E /* OnboardingTestCase.swift */; }; + B54315342DA64D6500981E7E /* AppUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54315332DA64D6500981E7E /* AppUtility.swift */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B54315302DA647A400981E7E /* NCLoginWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = B543152F2DA647A400981E7E /* NCLoginWeb.swift */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B5D45E732DA5172900773929 /* AppUpdater.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D45E712DA5172900773929 /* AppUpdater.swift */; }; + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */; }; + B5D45E6D2DA510E000773929 /* NCRenameFile.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B5D45E6A2DA510E000773929 /* NCRenameFile.storyboard */; }; + B5D45E6E2DA510E000773929 /* NCRenameFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D45E6B2DA510E000773929 /* NCRenameFile.swift */; }; + B5D45E702DA5119A00773929 /* RenameFileTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D45E6F2DA5119A00773929 /* RenameFileTests.swift */; }; + C04E2F232A17BB4D001BAD85 /* FilesIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C04E2F222A17BB4D001BAD85 /* FilesIntegrationTests.swift */; }; D575039F27146F93008DC9DC /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extension.swift */; }; D5B6AA7827200C7200D49C24 /* NCActivityTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */; }; F310B1EF2BA862F1001C42F5 /* NCViewerMedia+VisionKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = F310B1EE2BA862F1001C42F5 /* NCViewerMedia+VisionKit.swift */; }; @@ -156,9 +463,7 @@ F359D86B2A7D03420023F405 /* NCUtility+Exif.swift in Sources */ = {isa = PBXBuildFile; fileRef = F359D8662A7D03420023F405 /* NCUtility+Exif.swift */; }; F359D86C2A7D03420023F405 /* NCUtility+Exif.swift in Sources */ = {isa = PBXBuildFile; fileRef = F359D8662A7D03420023F405 /* NCUtility+Exif.swift */; }; F359D86D2A7D03420023F405 /* NCUtility+Exif.swift in Sources */ = {isa = PBXBuildFile; fileRef = F359D8662A7D03420023F405 /* NCUtility+Exif.swift */; }; - F36C514E2E89393C0097E5F7 /* UIView+BlurVibrancy.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36C514D2E89393C0097E5F7 /* UIView+BlurVibrancy.swift */; }; - F36C514F2E89393C0097E5F7 /* UIView+BlurVibrancy.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36C514D2E89393C0097E5F7 /* UIView+BlurVibrancy.swift */; }; - F36E64F72B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBarDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36E64F62B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBarDelegate.swift */; }; + F36E64F72B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36E64F62B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBar.swift */; }; F36E64FA2B96236C0085ABB5 /* UIView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E41315294A19B300839300 /* UIView+Extension.swift */; }; F36E64FB2B9733F10085ABB5 /* UIView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E41315294A19B300839300 /* UIView+Extension.swift */; }; F36E64FC2B9733F20085ABB5 /* UIView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E41315294A19B300839300 /* UIView+Extension.swift */; }; @@ -187,7 +492,6 @@ F37208C62BAB63F0006B5430 /* LRUCache in Frameworks */ = {isa = PBXBuildFile; productRef = F37208C52BAB63F0006B5430 /* LRUCache */; }; F37208C82BAB63F1006B5430 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = F37208C72BAB63F1006B5430 /* KeychainAccess */; }; F3754A7D2CF87D600009312E /* SetupPasscodeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3754A7C2CF87D600009312E /* SetupPasscodeView.swift */; }; - F376A3742E5CC6030067EE25 /* ContextMenuActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F376A3732E5CC5FF0067EE25 /* ContextMenuActions.swift */; }; F389C9F52CEE383300049762 /* SelectAlbumView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F389C9F42CEE383300049762 /* SelectAlbumView.swift */; }; F38F71252B6BBDC300473CDC /* NCCollectionViewCommonSelectTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = F38F71242B6BBDC300473CDC /* NCCollectionViewCommonSelectTabBar.swift */; }; F39170A92CB82024006127BC /* FileAutoRenamer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F39170A82CB8201B006127BC /* FileAutoRenamer+Extensions.swift */; }; @@ -221,13 +525,6 @@ F3F0419B2B9F7E6700D5155F /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = F3F0419A2B9F7E6700D5155F /* RealmSwift */; }; F3F0419D2B9F7E6E00D5155F /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = F3F0419C2B9F7E6E00D5155F /* RealmSwift */; }; F3F0419F2B9F7E7900D5155F /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = F3F0419E2B9F7E7900D5155F /* RealmSwift */; }; - F3F442EE2DDE292D00FD701F /* NCMetadataPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3F442ED2DDE292600FD701F /* NCMetadataPermissions.swift */; }; - F3F442EF2DDE2A7700FD701F /* NCMetadataPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3F442ED2DDE292600FD701F /* NCMetadataPermissions.swift */; }; - F3F442F02DDE2A7700FD701F /* NCMetadataPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3F442ED2DDE292600FD701F /* NCMetadataPermissions.swift */; }; - F3F442F12DDE2A7700FD701F /* NCMetadataPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3F442ED2DDE292600FD701F /* NCMetadataPermissions.swift */; }; - F3F442F22DDE2A7700FD701F /* NCMetadataPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3F442ED2DDE292600FD701F /* NCMetadataPermissions.swift */; }; - F3F442F32DDE2A7700FD701F /* NCMetadataPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3F442ED2DDE292600FD701F /* NCMetadataPermissions.swift */; }; - F3F442F42DDE2A7700FD701F /* NCMetadataPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3F442ED2DDE292600FD701F /* NCMetadataPermissions.swift */; }; F700222C1EC479840080073F /* Custom.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F700222B1EC479840080073F /* Custom.xcassets */; }; F700222D1EC479840080073F /* Custom.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F700222B1EC479840080073F /* Custom.xcassets */; }; F700510122DF63AC003A3356 /* NCShare.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F700510022DF63AC003A3356 /* NCShare.storyboard */; }; @@ -265,7 +562,7 @@ F70D7C3725FFBF82002B9E34 /* NCCollectionViewCommon.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70D7C3525FFBF81002B9E34 /* NCCollectionViewCommon.swift */; }; F70D8D8124A4A9BF000A5756 /* NCNetworkingProcess.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70D8D8024A4A9BF000A5756 /* NCNetworkingProcess.swift */; }; F710D1F52405770F00A6033D /* NCViewerPDF.swift in Sources */ = {isa = PBXBuildFile; fileRef = F710D1F42405770F00A6033D /* NCViewerPDF.swift */; }; - F710D2022405826100A6033D /* NCViewerContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F710D2012405826100A6033D /* NCViewerContextMenu.swift */; }; + F710D2022405826100A6033D /* NCViewer+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F710D2012405826100A6033D /* NCViewer+Menu.swift */; }; F710FC80277B7D2700AA9FBF /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = F710FC7F277B7D2700AA9FBF /* RealmSwift */; }; F710FC84277B7D3500AA9FBF /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = F710FC83277B7D3500AA9FBF /* RealmSwift */; }; F710FC88277B7D3F00AA9FBF /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = F710FC87277B7D3F00AA9FBF /* RealmSwift */; }; @@ -300,10 +597,6 @@ F717402E24F699A5000C87D5 /* NCFavorite.swift in Sources */ = {isa = PBXBuildFile; fileRef = F717402C24F699A5000C87D5 /* NCFavorite.swift */; }; F718C24E254D507B00C5C256 /* NCViewerMediaDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F718C24D254D507B00C5C256 /* NCViewerMediaDetailView.swift */; }; F718E25A2DF2D5D1004038AF /* NCBackgroundLocationUploadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F718E2572DF2D5C3004038AF /* NCBackgroundLocationUploadManager.swift */; }; - F71916112E2901FB00E13E96 /* NCNetworking+Upload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F71916102E2901E800E13E96 /* NCNetworking+Upload.swift */; }; - F71916122E2901FB00E13E96 /* NCNetworking+Upload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F71916102E2901E800E13E96 /* NCNetworking+Upload.swift */; }; - F71916132E2901FB00E13E96 /* NCNetworking+Upload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F71916102E2901E800E13E96 /* NCNetworking+Upload.swift */; }; - F71916142E2901FB00E13E96 /* NCNetworking+Upload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F71916102E2901E800E13E96 /* NCNetworking+Upload.swift */; }; F719D9E0288D37A300762E33 /* NCColorPicker.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F719D9DF288D37A300762E33 /* NCColorPicker.storyboard */; }; F719D9E2288D396100762E33 /* NCColorPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = F719D9E1288D396100762E33 /* NCColorPicker.swift */; }; F71CD6CA2930D7B1006C95C1 /* NCApplicationHandle.swift in Sources */ = {isa = PBXBuildFile; fileRef = F71CD6C92930D7B1006C95C1 /* NCApplicationHandle.swift */; }; @@ -324,13 +617,13 @@ F72429362AFE39860040AEF3 /* NCLivePhoto.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70968A324212C4E00ED60E5 /* NCLivePhoto.swift */; }; F72429372AFE39980040AEF3 /* NCLivePhoto.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70968A324212C4E00ED60E5 /* NCLivePhoto.swift */; }; F72429382AFE39A80040AEF3 /* NCLivePhoto.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70968A324212C4E00ED60E5 /* NCLivePhoto.swift */; }; - F724377B2C10B83E00C7C68D /* NCSharePermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F724377A2C10B83E00C7C68D /* NCSharePermissions.swift */; }; - F724377C2C10B92200C7C68D /* NCSharePermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F724377A2C10B83E00C7C68D /* NCSharePermissions.swift */; }; - F724377D2C10B92300C7C68D /* NCSharePermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F724377A2C10B83E00C7C68D /* NCSharePermissions.swift */; }; - F724377E2C10B92300C7C68D /* NCSharePermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F724377A2C10B83E00C7C68D /* NCSharePermissions.swift */; }; - F724377F2C10B92400C7C68D /* NCSharePermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F724377A2C10B83E00C7C68D /* NCSharePermissions.swift */; }; - F72437802C10B92400C7C68D /* NCSharePermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F724377A2C10B83E00C7C68D /* NCSharePermissions.swift */; }; - F72437812C10B92500C7C68D /* NCSharePermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F724377A2C10B83E00C7C68D /* NCSharePermissions.swift */; }; + F724377B2C10B83E00C7C68D /* NCPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F724377A2C10B83E00C7C68D /* NCPermissions.swift */; }; + F724377C2C10B92200C7C68D /* NCPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F724377A2C10B83E00C7C68D /* NCPermissions.swift */; }; + F724377D2C10B92300C7C68D /* NCPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F724377A2C10B83E00C7C68D /* NCPermissions.swift */; }; + F724377E2C10B92300C7C68D /* NCPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F724377A2C10B83E00C7C68D /* NCPermissions.swift */; }; + F724377F2C10B92400C7C68D /* NCPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F724377A2C10B83E00C7C68D /* NCPermissions.swift */; }; + F72437802C10B92400C7C68D /* NCPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F724377A2C10B83E00C7C68D /* NCPermissions.swift */; }; + F72437812C10B92500C7C68D /* NCPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F724377A2C10B83E00C7C68D /* NCPermissions.swift */; }; F7245924289BB50C00474787 /* ThreadSafeDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7245923289BB50B00474787 /* ThreadSafeDictionary.swift */; }; F7245925289BB59100474787 /* ThreadSafeDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7245923289BB50B00474787 /* ThreadSafeDictionary.swift */; }; F7245926289BB59300474787 /* ThreadSafeDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7245923289BB50B00474787 /* ThreadSafeDictionary.swift */; }; @@ -365,6 +658,10 @@ F7327E212B73A42F00A462C7 /* NCNetworking+Download.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7327E1F2B73A42F00A462C7 /* NCNetworking+Download.swift */; }; F7327E232B73A42F00A462C7 /* NCNetworking+Download.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7327E1F2B73A42F00A462C7 /* NCNetworking+Download.swift */; }; F7327E242B73A42F00A462C7 /* NCNetworking+Download.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7327E1F2B73A42F00A462C7 /* NCNetworking+Download.swift */; }; + F7327E282B73A53400A462C7 /* NCNetworking+Upload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7327E272B73A53400A462C7 /* NCNetworking+Upload.swift */; }; + F7327E292B73A53400A462C7 /* NCNetworking+Upload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7327E272B73A53400A462C7 /* NCNetworking+Upload.swift */; }; + F7327E2B2B73A53400A462C7 /* NCNetworking+Upload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7327E272B73A53400A462C7 /* NCNetworking+Upload.swift */; }; + F7327E2C2B73A53400A462C7 /* NCNetworking+Upload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7327E272B73A53400A462C7 /* NCNetworking+Upload.swift */; }; F7327E302B73A86700A462C7 /* NCNetworking+WebDAV.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7327E2F2B73A86700A462C7 /* NCNetworking+WebDAV.swift */; }; F7327E312B73A86700A462C7 /* NCNetworking+WebDAV.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7327E2F2B73A86700A462C7 /* NCNetworking+WebDAV.swift */; }; F7327E322B73A86700A462C7 /* NCNetworking+WebDAV.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7327E2F2B73A86700A462C7 /* NCNetworking+WebDAV.swift */; }; @@ -402,6 +699,8 @@ F73ADD2126554F8E0069EA0D /* SwiftEntryKit in Frameworks */ = {isa = PBXBuildFile; productRef = F73ADD2026554F8E0069EA0D /* SwiftEntryKit */; }; F73ADD2226554FD10069EA0D /* NCContentPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F765608E23BF813500765969 /* NCContentPresenter.swift */; }; F73ADD2426554FE20069EA0D /* SwiftEntryKit in Frameworks */ = {isa = PBXBuildFile; productRef = F73ADD2326554FE20069EA0D /* SwiftEntryKit */; }; + F73B422B2476764F00A30FD3 /* NCNotification.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F73B42292476764F00A30FD3 /* NCNotification.storyboard */; }; + F73B422C2476764F00A30FD3 /* NCNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73B422A2476764F00A30FD3 /* NCNotification.swift */; }; F73CB3B222E072A000AD728E /* NCShareHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F73CB3B122E072A000AD728E /* NCShareHeaderView.xib */; }; F73D11FA253C5F4800DF9BEC /* NCViewerNextcloudText.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F73D11F9253C5F4800DF9BEC /* NCViewerNextcloudText.storyboard */; }; F73EF7A32B021FAC0087E6E9 /* NCLivePhoto.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70968A324212C4E00ED60E5 /* NCLivePhoto.swift */; }; @@ -460,7 +759,6 @@ F74230F32C79B57200CA1ACA /* NCNetworking+Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = F74230F22C79B57200CA1ACA /* NCNetworking+Task.swift */; }; F7434B3620E23FE000417916 /* NCManageDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB51ED5A87C00B7EAD4 /* NCManageDatabase.swift */; }; F7434B3820E2400600417916 /* NCBrand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76B3CCD1EAE01BD00921AC9 /* NCBrand.swift */; }; - F743C89E2E5B25A1000173A9 /* UIScene+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F743C89D2E5B2595000173A9 /* UIScene+Extension.swift */; }; F745B253222D88AE00346520 /* NCLoginQRCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F745B252222D88AE00346520 /* NCLoginQRCode.swift */; }; F746EC51273906C40052598D /* NCViewCertificateDetails.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7BC287D26663F6C004D46C5 /* NCViewCertificateDetails.storyboard */; }; F746EC52273906C40052598D /* NCViewCertificateDetails.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7BC287D26663F6C004D46C5 /* NCViewCertificateDetails.storyboard */; }; @@ -526,11 +824,9 @@ F7501C332212E57500FB1415 /* NCMedia.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7501C312212E57400FB1415 /* NCMedia.swift */; }; F751247C2C42919C00E63DB8 /* NCPhotoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F751247A2C42919C00E63DB8 /* NCPhotoCell.swift */; }; F751247E2C42919C00E63DB8 /* NCPhotoCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F751247B2C42919C00E63DB8 /* NCPhotoCell.xib */; }; - F752BA052E58C05200616A26 /* Maintenance.swift in Sources */ = {isa = PBXBuildFile; fileRef = F752BA042E58C05200616A26 /* Maintenance.swift */; }; F75379202AE2AD9400C0250E /* JGProgressHUD in Frameworks */ = {isa = PBXBuildFile; productRef = F753791F2AE2AD9400C0250E /* JGProgressHUD */; }; F75379222AE2ADA100C0250E /* JGProgressHUD in Frameworks */ = {isa = PBXBuildFile; productRef = F75379212AE2ADA100C0250E /* JGProgressHUD */; }; F753BA93281FD8020015BFB6 /* EasyTipView in Frameworks */ = {isa = PBXBuildFile; productRef = F753BA92281FD8020015BFB6 /* EasyTipView */; }; - F753DBDF2E5D99C300A1AF91 /* NCFiles+SyncMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = F753DBDE2E5D99B700A1AF91 /* NCFiles+SyncMetadata.swift */; }; F755BD9B20594AC7008C5FBB /* NCService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F755BD9A20594AC7008C5FBB /* NCService.swift */; }; F755CB402B8CB13C00CE27E9 /* NCMediaLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = F755CB3F2B8CB13C00CE27E9 /* NCMediaLayout.swift */; }; F757CC8229E7F88B00F31428 /* NCManageDatabase+Groupfolders.swift in Sources */ = {isa = PBXBuildFile; fileRef = F757CC8129E7F88B00F31428 /* NCManageDatabase+Groupfolders.swift */; }; @@ -594,7 +890,7 @@ F76882282C0DD1E7001CF441 /* NCEndToEndInitialize.swift in Sources */ = {isa = PBXBuildFile; fileRef = F768820F2C0DD1E7001CF441 /* NCEndToEndInitialize.swift */; }; F76882292C0DD1E7001CF441 /* NCManageE2EEModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882102C0DD1E7001CF441 /* NCManageE2EEModel.swift */; }; F768822A2C0DD1E7001CF441 /* NCSettingsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882112C0DD1E7001CF441 /* NCSettingsModel.swift */; }; - F768822C2C0DD1E7001CF441 /* NCPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882132C0DD1E7001CF441 /* NCPreferences.swift */; }; + F768822C2C0DD1E7001CF441 /* NCKeychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882132C0DD1E7001CF441 /* NCKeychain.swift */; }; F768822D2C0DD1E7001CF441 /* Acknowledgements.rtf in Resources */ = {isa = PBXBuildFile; fileRef = F76882142C0DD1E7001CF441 /* Acknowledgements.rtf */; }; F768822E2C0DD1E7001CF441 /* NCSettingsBundleHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882152C0DD1E7001CF441 /* NCSettingsBundleHelper.swift */; }; F76882302C0DD1E7001CF441 /* NCFileNameModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882192C0DD1E7001CF441 /* NCFileNameModel.swift */; }; @@ -604,12 +900,12 @@ F76882342C0DD1E7001CF441 /* NCDisplayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F768821E2C0DD1E7001CF441 /* NCDisplayView.swift */; }; F76882352C0DD1E7001CF441 /* NCWebBrowserView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882202C0DD1E7001CF441 /* NCWebBrowserView.swift */; }; F76882362C0DD1E7001CF441 /* NCAcknowledgementsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882212C0DD1E7001CF441 /* NCAcknowledgementsView.swift */; }; - F76882372C0DD22F001CF441 /* NCPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882132C0DD1E7001CF441 /* NCPreferences.swift */; }; - F76882382C0DD22F001CF441 /* NCPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882132C0DD1E7001CF441 /* NCPreferences.swift */; }; - F76882392C0DD230001CF441 /* NCPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882132C0DD1E7001CF441 /* NCPreferences.swift */; }; - F768823A2C0DD230001CF441 /* NCPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882132C0DD1E7001CF441 /* NCPreferences.swift */; }; - F768823B2C0DD231001CF441 /* NCPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882132C0DD1E7001CF441 /* NCPreferences.swift */; }; - F768823C2C0DD231001CF441 /* NCPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882132C0DD1E7001CF441 /* NCPreferences.swift */; }; + F76882372C0DD22F001CF441 /* NCKeychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882132C0DD1E7001CF441 /* NCKeychain.swift */; }; + F76882382C0DD22F001CF441 /* NCKeychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882132C0DD1E7001CF441 /* NCKeychain.swift */; }; + F76882392C0DD230001CF441 /* NCKeychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882132C0DD1E7001CF441 /* NCKeychain.swift */; }; + F768823A2C0DD230001CF441 /* NCKeychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882132C0DD1E7001CF441 /* NCKeychain.swift */; }; + F768823B2C0DD231001CF441 /* NCKeychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882132C0DD1E7001CF441 /* NCKeychain.swift */; }; + F768823C2C0DD231001CF441 /* NCKeychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76882132C0DD1E7001CF441 /* NCKeychain.swift */; }; F768823E2C0DD305001CF441 /* LazyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F768823D2C0DD304001CF441 /* LazyView.swift */; }; F76882402C0DD30B001CF441 /* ViewOnAppear.swift in Sources */ = {isa = PBXBuildFile; fileRef = F768823F2C0DD30B001CF441 /* ViewOnAppear.swift */; }; F769453C22E9CFFF000A798A /* NCShareUserCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F769453B22E9CFFF000A798A /* NCShareUserCell.xib */; }; @@ -678,7 +974,6 @@ F77E8C202E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77E8C1E2E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift */; }; F77E8C212E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77E8C1E2E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift */; }; F77E8C222E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77E8C1E2E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift */; }; - F77E8C232E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77E8C1E2E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift */; }; F77E8C242E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77E8C1E2E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift */; }; F77E8C252E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77E8C1E2E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift */; }; F77ED59128C9CE9D00E24ED0 /* ToolbarData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77ED59028C9CE9D00E24ED0 /* ToolbarData.swift */; }; @@ -694,6 +989,9 @@ F7817CFD29801A3500FFBC65 /* Data+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7817CF729801A3500FFBC65 /* Data+Extension.swift */; }; F7817CFE29801A3500FFBC65 /* Data+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7817CF729801A3500FFBC65 /* Data+Extension.swift */; }; F7817CFF29802D1A00FFBC65 /* NCPushNotificationEncryption.m in Sources */ = {isa = PBXBuildFile; fileRef = F72D1005210B6882009C96B7 /* NCPushNotificationEncryption.m */; }; + F7817D0029802D3D00FFBC65 /* NCViewCertificateDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BC287F26663F85004D46C5 /* NCViewCertificateDetails.swift */; }; + F7817D0129802D5F00FFBC65 /* NCViewCertificateDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BC287F26663F85004D46C5 /* NCViewCertificateDetails.swift */; }; + F7817D0229802D7700FFBC65 /* NCViewCertificateDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BC287F26663F85004D46C5 /* NCViewCertificateDetails.swift */; }; F78295311F962EFA00A572F5 /* NCEndToEndEncryption.m in Sources */ = {isa = PBXBuildFile; fileRef = F70CAE391F8CF31A008125FD /* NCEndToEndEncryption.m */; }; F782FDC424E6933900666099 /* NCUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70BFC7320E0FA7C00C67599 /* NCUtility.swift */; }; F78302F728B4C3C900B84583 /* NCManageDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB51ED5A87C00B7EAD4 /* NCManageDatabase.swift */; }; @@ -763,7 +1061,6 @@ F793E5A128B76541005E4B02 /* NotificationCenter+MainThread.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70460512499061800BB98A7 /* NotificationCenter+MainThread.swift */; }; F794E13D2BBBFF2E003693D7 /* NCMainTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F794E13C2BBBFF2E003693D7 /* NCMainTabBarController.swift */; }; F794E13F2BBC0F70003693D7 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F794E13E2BBC0F70003693D7 /* SceneDelegate.swift */; }; - F79699E72E689F68000EC82A /* NCMediaNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F79699E62E689F68000EC82A /* NCMediaNavigationController.swift */; }; F798F0E225880608000DAFFD /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extension.swift */; }; F798F0E725880609000DAFFD /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extension.swift */; }; F798F0EC2588060A000DAFFD /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70CEF5523E9C7E50007035B /* UIColor+Extension.swift */; }; @@ -807,6 +1104,8 @@ F7A560462AE15D3D00BE8FD6 /* Queuer in Frameworks */ = {isa = PBXBuildFile; productRef = F7A560452AE15D3D00BE8FD6 /* Queuer */; }; F7A560482AE15D5000BE8FD6 /* Queuer in Frameworks */ = {isa = PBXBuildFile; productRef = F7A560472AE15D5000BE8FD6 /* Queuer */; }; F7A573692E190387009C9257 /* NCShareExtensionData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A573682E190377009C9257 /* NCShareExtensionData.swift */; }; + F7A60F86292D215000FCE1F2 /* NCShareAccounts.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A60F84292D215000FCE1F2 /* NCShareAccounts.swift */; }; + F7A60F87292D215000FCE1F2 /* NCShareAccounts.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7A60F85292D215000FCE1F2 /* NCShareAccounts.storyboard */; }; F7A76DC8256A71CD00119AB3 /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extension.swift */; }; F7A76DCD256A71CE00119AB3 /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extension.swift */; }; F7A7FDDD2C2DBD6200E9A93A /* NCDeepLinkHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A7FDDB2C2DBD6200E9A93A /* NCDeepLinkHandler.swift */; }; @@ -827,11 +1126,14 @@ F7A8D74228F18261008BBE1C /* NCUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70BFC7320E0FA7C00C67599 /* NCUtility.swift */; }; F7A8D74328F1826F008BBE1C /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extension.swift */; }; F7A8D74428F1827B008BBE1C /* ThreadSafeDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7245923289BB50B00474787 /* ThreadSafeDictionary.swift */; }; + F7A8FD522C5E2557006C9CF8 /* NCAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A8FD512C5E2557006C9CF8 /* NCAccount.swift */; }; F7AC1CB028AB94490032D99F /* Array+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7AC1CAF28AB94490032D99F /* Array+Extension.swift */; }; F7AC934A296193050002BC0F /* Reasons to use Nextcloud.pdf in Resources */ = {isa = PBXBuildFile; fileRef = F7AC9349296193050002BC0F /* Reasons to use Nextcloud.pdf */; }; F7AE00F5230D5F9E007ACF8A /* NCLoginProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7AE00F4230D5F9E007ACF8A /* NCLoginProvider.swift */; }; F7AE00F8230E81CB007ACF8A /* NCBrowserWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7AE00F7230E81CB007ACF8A /* NCBrowserWeb.swift */; }; F7AE00FA230E81EB007ACF8A /* NCBrowserWeb.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7AE00F9230E81EB007ACF8A /* NCBrowserWeb.storyboard */; }; + F7AEEAA62C11DBAF00011412 /* NCAccountSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7AEEAA52C11DBAF00011412 /* NCAccountSettingsView.swift */; }; + F7AEEAA82C11DBFD00011412 /* NCAccountSettingsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7AEEAA72C11DBFD00011412 /* NCAccountSettingsModel.swift */; }; F7B398422A6A91D5007538D6 /* NCSectionFirstHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7B398412A6A91D5007538D6 /* NCSectionFirstHeader.xib */; }; F7B398432A6A91D5007538D6 /* NCSectionFirstHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7B398412A6A91D5007538D6 /* NCSectionFirstHeader.xib */; }; F7B6B70427C4E7FA00A7F6EB /* NCScan+CollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B6B70327C4E7FA00A7F6EB /* NCScan+CollectionView.swift */; }; @@ -895,6 +1197,8 @@ F7C9B9212B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C9B91C2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift */; }; F7C9B9222B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C9B91C2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift */; }; F7C9B9232B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C9B91C2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift */; }; + F7CA212D25F1333300826ABB /* NCAccountRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CA212B25F1333200826ABB /* NCAccountRequest.swift */; }; + F7CA212E25F1333300826ABB /* NCAccountRequest.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7CA212C25F1333200826ABB /* NCAccountRequest.storyboard */; }; F7CB689A2541676B0050EC94 /* NCMore.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7CB68992541676B0050EC94 /* NCMore.storyboard */; }; F7CBC1232BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7CBC1212BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.xib */; }; F7CBC1242BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7CBC1212BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.xib */; }; @@ -902,7 +1206,13 @@ F7CBC1262BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CBC1222BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.swift */; }; F7CEE6002BA9A5C9003EFD89 /* NCTrashGridCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7CEE5FE2BA9A5C9003EFD89 /* NCTrashGridCell.xib */; }; F7CEE6012BA9A5C9003EFD89 /* NCTrashGridCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CEE5FF2BA9A5C9003EFD89 /* NCTrashGridCell.swift */; }; + F7CF067B2E0FF3990063AD04 /* NCAppStateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CF067A2E0FF38F0063AD04 /* NCAppStateManager.swift */; }; + F7CF067C2E0FF3990063AD04 /* NCAppStateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CF067A2E0FF38F0063AD04 /* NCAppStateManager.swift */; }; + F7CF067D2E0FF3990063AD04 /* NCAppStateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CF067A2E0FF38F0063AD04 /* NCAppStateManager.swift */; }; + F7CF067E2E0FF3990063AD04 /* NCAppStateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CF067A2E0FF38F0063AD04 /* NCAppStateManager.swift */; }; + F7CF067F2E0FF3990063AD04 /* NCAppStateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CF067A2E0FF38F0063AD04 /* NCAppStateManager.swift */; }; F7CF06802E0FF3990063AD04 /* NCAppStateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CF067A2E0FF38F0063AD04 /* NCAppStateManager.swift */; }; + F7CF06812E0FF3990063AD04 /* NCAppStateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CF067A2E0FF38F0063AD04 /* NCAppStateManager.swift */; }; F7CF06832E1127460063AD04 /* NCManageDatabase+Metadata+Create.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CF06822E11273F0063AD04 /* NCManageDatabase+Metadata+Create.swift */; }; F7CF06842E1127460063AD04 /* NCManageDatabase+Metadata+Create.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CF06822E11273F0063AD04 /* NCManageDatabase+Metadata+Create.swift */; }; F7CF06852E1127460063AD04 /* NCManageDatabase+Metadata+Create.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CF06822E11273F0063AD04 /* NCManageDatabase+Metadata+Create.swift */; }; @@ -950,6 +1260,8 @@ F7D4BF4D2CA2E8D800A5E746 /* TOPasscodeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F7D4BF2A2CA2E8D800A5E746 /* TOPasscodeViewController.m */; }; F7D4BF542CA2ED9D00A5E746 /* VLCKitSPM in Frameworks */ = {isa = PBXBuildFile; productRef = F7D4BF532CA2ED9D00A5E746 /* VLCKitSPM */; }; F7D56B1A2972405500FA46C4 /* Mantis in Frameworks */ = {isa = PBXBuildFile; productRef = F7D56B192972405500FA46C4 /* Mantis */; }; + F7D57C8626317BDA00DE301D /* NCAccountRequest.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7CA212C25F1333200826ABB /* NCAccountRequest.storyboard */; }; + F7D57C8B26317BDE00DE301D /* NCAccountRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CA212B25F1333200826ABB /* NCAccountRequest.swift */; }; F7D60CAF2C941ACB008FBFDD /* NCMediaPinchGesture.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D60CAE2C941ACB008FBFDD /* NCMediaPinchGesture.swift */; }; F7D68FCC28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D68FCB28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift */; }; F7D68FCD28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D68FCB28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift */; }; @@ -964,13 +1276,6 @@ F7D7A7712DCDD437003D2007 /* NCManageDatabase+AutoUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D7A76B2DCDD437003D2007 /* NCManageDatabase+AutoUpload.swift */; }; F7D7A7722DCDD437003D2007 /* NCManageDatabase+AutoUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D7A76B2DCDD437003D2007 /* NCManageDatabase+AutoUpload.swift */; }; F7D890752BD25C570050B8A6 /* NCCollectionViewCommon+DragDrop.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D890742BD25C570050B8A6 /* NCCollectionViewCommon+DragDrop.swift */; }; - F7DB7DE92E81731B0017AF90 /* NCStorageEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DB7DE82E8173160017AF90 /* NCStorageEstimator.swift */; }; - F7DB7DEA2E81731B0017AF90 /* NCStorageEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DB7DE82E8173160017AF90 /* NCStorageEstimator.swift */; }; - F7DB7DEB2E81731B0017AF90 /* NCStorageEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DB7DE82E8173160017AF90 /* NCStorageEstimator.swift */; }; - F7DB7DEC2E81731B0017AF90 /* NCStorageEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DB7DE82E8173160017AF90 /* NCStorageEstimator.swift */; }; - F7DB7DED2E81731B0017AF90 /* NCStorageEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DB7DE82E8173160017AF90 /* NCStorageEstimator.swift */; }; - F7DB7DEE2E81731B0017AF90 /* NCStorageEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DB7DE82E8173160017AF90 /* NCStorageEstimator.swift */; }; - F7DB7DEF2E81731B0017AF90 /* NCStorageEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DB7DE82E8173160017AF90 /* NCStorageEstimator.swift */; }; F7E0710128B13BB00001B882 /* DashboardData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E0710028B13BB00001B882 /* DashboardData.swift */; }; F7E0CDCF265CE8610044854E /* NCUserStatus.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7E0CDCE265CE8610044854E /* NCUserStatus.storyboard */; }; F7E2B64F2DDCC5C30075B4D0 /* NCMedia+TransferDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E2B64E2DDCC5C30075B4D0 /* NCMedia+TransferDelegate.swift */; }; @@ -1000,21 +1305,8 @@ F7EDE514262DC2CD00414FE6 /* NCSelectCommandViewSelect+CreateFolder.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7EDE513262DC2CD00414FE6 /* NCSelectCommandViewSelect+CreateFolder.xib */; }; F7EDE51B262DD0C400414FE6 /* NCSelectCommandViewCopyMove.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7EDE51A262DD0C400414FE6 /* NCSelectCommandViewCopyMove.xib */; }; F7EE66AD2A20B226009AE765 /* UILabel+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7EE66AC2A20B226009AE765 /* UILabel+Extension.swift */; }; - F7EF2AEB2E43157B0081B2C9 /* NCNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7EF2AE92E43157B0081B2C9 /* NCNotification.swift */; }; - F7EF2AEC2E43157B0081B2C9 /* NCNotification.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7EF2AE82E43157B0081B2C9 /* NCNotification.storyboard */; }; F7EFA47825ADBA500083159A /* NCViewerProviderContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7EFA47725ADBA500083159A /* NCViewerProviderContextMenu.swift */; }; F7EFC0CD256BF8DD00461AAD /* NCUserStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7EFC0CC256BF8DD00461AAD /* NCUserStatus.swift */; }; - F7F1FB9D2E27CE7200C79E20 /* NCNetworking.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75A9EE523796C6F0044CFCE /* NCNetworking.swift */; }; - F7F1FB9E2E27CE7200C79E20 /* NCNetworking.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75A9EE523796C6F0044CFCE /* NCNetworking.swift */; }; - F7F1FB9F2E27CE7200C79E20 /* NCNetworking.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75A9EE523796C6F0044CFCE /* NCNetworking.swift */; }; - F7F1FBA02E27CFBC00C79E20 /* NCContentPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F765608E23BF813500765969 /* NCContentPresenter.swift */; }; - F7F1FBA12E27CFBC00C79E20 /* NCContentPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F765608E23BF813500765969 /* NCContentPresenter.swift */; }; - F7F1FBA22E27CFBC00C79E20 /* NCContentPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F765608E23BF813500765969 /* NCContentPresenter.swift */; }; - F7F1FBA82E27D13700C79E20 /* Queuer in Frameworks */ = {isa = PBXBuildFile; productRef = F7F1FBA72E27D13700C79E20 /* Queuer */; }; - F7F1FBAA2E27D14000C79E20 /* SwiftEntryKit in Frameworks */ = {isa = PBXBuildFile; productRef = F7F1FBA92E27D14000C79E20 /* SwiftEntryKit */; }; - F7F1FBAC2E27D20400C79E20 /* Queuer in Frameworks */ = {isa = PBXBuildFile; productRef = F7F1FBAB2E27D20400C79E20 /* Queuer */; }; - F7F1FBAE2E27D3A400C79E20 /* SwiftEntryKit in Frameworks */ = {isa = PBXBuildFile; productRef = F7F1FBAD2E27D3A400C79E20 /* SwiftEntryKit */; }; - F7F1FBB02E27D3A800C79E20 /* Queuer in Frameworks */ = {isa = PBXBuildFile; productRef = F7F1FBAF2E27D3A800C79E20 /* Queuer */; }; F7F3E58B2D3BB65600A32B14 /* NCNetworking+Recommendations.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F3E58A2D3BB65000A32B14 /* NCNetworking+Recommendations.swift */; }; F7F3E58C2D3BB65600A32B14 /* NCNetworking+Recommendations.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F3E58A2D3BB65000A32B14 /* NCNetworking+Recommendations.swift */; }; F7F3E58D2D3BB65600A32B14 /* NCNetworking+Recommendations.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F3E58A2D3BB65000A32B14 /* NCNetworking+Recommendations.swift */; }; @@ -1028,13 +1320,6 @@ 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 */; }; F7F4F11227ECDC52008676F9 /* UIFont+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F4F11127ECDC52008676F9 /* UIFont+Extension.swift */; }; - F7F563002E15762B00631A11 /* MigrationMultiDomains.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F562FF2E15761500631A11 /* MigrationMultiDomains.swift */; }; - F7F563012E15762B00631A11 /* MigrationMultiDomains.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F562FF2E15761500631A11 /* MigrationMultiDomains.swift */; }; - F7F563022E15762B00631A11 /* MigrationMultiDomains.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F562FF2E15761500631A11 /* MigrationMultiDomains.swift */; }; - F7F563032E15762B00631A11 /* MigrationMultiDomains.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F562FF2E15761500631A11 /* MigrationMultiDomains.swift */; }; - F7F563042E15762B00631A11 /* MigrationMultiDomains.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F562FF2E15761500631A11 /* MigrationMultiDomains.swift */; }; - F7F563052E15762B00631A11 /* MigrationMultiDomains.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F562FF2E15761500631A11 /* MigrationMultiDomains.swift */; }; - F7F563062E15762B00631A11 /* MigrationMultiDomains.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F562FF2E15761500631A11 /* MigrationMultiDomains.swift */; }; F7F623B52A5EF4D30022D3D4 /* Gzip in Frameworks */ = {isa = PBXBuildFile; productRef = F7F623B42A5EF4D30022D3D4 /* Gzip */; }; F7F623B72A5EFA0C0022D3D4 /* Gzip in Frameworks */ = {isa = PBXBuildFile; productRef = F7F623B62A5EFA0C0022D3D4 /* Gzip */; }; F7F878AE1FB9E3B900599E4F /* NCEndToEndMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F878AD1FB9E3B900599E4F /* NCEndToEndMetadata.swift */; }; @@ -1044,15 +1329,6 @@ F7FA80002C0F4F3B0072FC60 /* NCUploadAssetsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7FA7FFE2C0F4F3B0072FC60 /* NCUploadAssetsModel.swift */; }; F7FA80012C0F4F3B0072FC60 /* NCUploadAssetsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7FA7FFF2C0F4F3B0072FC60 /* NCUploadAssetsView.swift */; }; F7FAFD3A28BFA948000777FE /* NCNotification+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7FAFD3928BFA947000777FE /* NCNotification+Menu.swift */; }; - F7FDFF692E437E55000D7688 /* NCAccountRequest.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7FDFF512E437E55000D7688 /* NCAccountRequest.storyboard */; }; - F7FDFF6A2E437E55000D7688 /* NCShareAccounts.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7FDFF532E437E55000D7688 /* NCShareAccounts.storyboard */; }; - F7FDFF6B2E437E55000D7688 /* NCAccountRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7FDFF522E437E55000D7688 /* NCAccountRequest.swift */; }; - F7FDFF6C2E437E55000D7688 /* NCShareAccounts.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7FDFF542E437E55000D7688 /* NCShareAccounts.swift */; }; - F7FDFF6D2E437E55000D7688 /* NCAccountSettingsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7FDFF562E437E55000D7688 /* NCAccountSettingsModel.swift */; }; - F7FDFF6E2E437E55000D7688 /* NCAccountSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7FDFF572E437E55000D7688 /* NCAccountSettingsView.swift */; }; - F7FDFF6F2E437E55000D7688 /* NCAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7FDFF592E437E55000D7688 /* NCAccount.swift */; }; - F7FDFF702E437E55000D7688 /* NCAccountRequest.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7FDFF512E437E55000D7688 /* NCAccountRequest.storyboard */; }; - F7FDFF722E437E55000D7688 /* NCAccountRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7FDFF522E437E55000D7688 /* NCAccountRequest.swift */; }; F7FF2CB12842159500EBB7A1 /* NCSectionHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7FF2CB02842159500EBB7A1 /* NCSectionHeader.xib */; }; /* End PBXBuildFile section */ @@ -1249,6 +1525,7 @@ 3704EB2923D5A58400455C5B /* NCMenu.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCMenu.storyboard; sourceTree = ""; }; 370D26AE248A3D7A00121797 /* NCCellProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCellProtocol.swift; sourceTree = ""; }; 371B5A2D23D0B04500FAFAE9 /* NCMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMenu.swift; sourceTree = ""; }; + 3781B9AF23DB2B7E006B4B1D /* AppDelegate+Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+Menu.swift"; sourceTree = ""; }; 8491B1CC273BBA82001C8C5B /* UIViewController+Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Menu.swift"; sourceTree = ""; }; AA3C85E72D36B08C00F74F12 /* UITestBackend.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestBackend.swift; sourceTree = ""; }; AA3C85EA2D36BBF400F74F12 /* OCSResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OCSResponse.swift; sourceTree = ""; }; @@ -1326,7 +1603,6 @@ AAA7BC2F2D3E3B83008F1A22 /* CapabilityResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CapabilityResponse.swift; sourceTree = ""; }; AABD0C862D5F58C400F009E6 /* Server.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = Server.sh; sourceTree = ""; }; AABD0C892D5F67A200F009E6 /* XCUIElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCUIElement.swift; sourceTree = ""; }; - AABD0C9A2D5F73FA00F009E6 /* Placeholder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Placeholder.swift; sourceTree = ""; }; AACCAB522CFE041F00DA1786 /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = sl.lproj/Intent.strings; sourceTree = ""; }; AACCAB532CFE041F00DA1786 /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = sl.lproj/Localizable.strings; sourceTree = ""; }; AACCAB542CFE041F00DA1786 /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = sl.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -1368,6 +1644,195 @@ AFCE353427E4ED5900FEA6C2 /* DateFormatter+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DateFormatter+Extension.swift"; sourceTree = ""; }; AFCE353627E4ED7B00FEA6C2 /* NCShareCells.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareCells.swift; sourceTree = ""; }; AFCE353827E5DE0400FEA6C2 /* Shareable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shareable.swift; sourceTree = ""; }; + B5BEBD272E93AD540002C9E5 /* File_Provider_Extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = File_Provider_Extension.entitlements; sourceTree = ""; }; + B5BEBD282E93AD540002C9E5 /* File_Provider_Extension.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = File_Provider_Extension.plist; sourceTree = ""; }; + B5BEBD292E93AD540002C9E5 /* iOSClient.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = iOSClient.entitlements; sourceTree = ""; }; + B5BEBD2A2E93AD540002C9E5 /* iOSClient.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = iOSClient.plist; sourceTree = ""; }; + B5BEBD2B2E93AD540002C9E5 /* Notification_Service_Extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Notification_Service_Extension.entitlements; sourceTree = ""; }; + B5BEBD2C2E93AD540002C9E5 /* Notification_Service_Extension.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Notification_Service_Extension.plist; sourceTree = ""; }; + B5BEBD2D2E93AD540002C9E5 /* Share.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Share.entitlements; sourceTree = ""; }; + B5BEBD2E2E93AD540002C9E5 /* Share.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Share.plist; sourceTree = ""; }; + B5BEBD4F2E93AE1C0002C9E5 /* BaseXCTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseXCTestCase.swift; sourceTree = ""; }; + B5BEBD502E93AE1C0002C9E5 /* TestConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestConstants.swift; sourceTree = ""; }; + B5BEBD582E93AE2F0002C9E5 /* BaseIntegrationXCTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseIntegrationXCTestCase.swift; sourceTree = ""; }; + B5BEBD592E93AE2F0002C9E5 /* FilesIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilesIntegrationTests.swift; sourceTree = ""; }; + B5BEBD5A2E93AE2F0002C9E5 /* LoginIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginIntegrationTests.swift; sourceTree = ""; }; + B5BEBD5E2E93AE4B0002C9E5 /* AssetUploadTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssetUploadTest.swift; sourceTree = ""; }; + B5BEBD5F2E93AE4B0002C9E5 /* AudioUploadTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioUploadTests.swift; sourceTree = ""; }; + B5BEBD602E93AE4B0002C9E5 /* CollaboraTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollaboraTestCase.swift; sourceTree = ""; }; + B5BEBD612E93AE4B0002C9E5 /* E2EETests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = E2EETests.swift; sourceTree = ""; }; + B5BEBD622E93AE4B0002C9E5 /* MoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoreTests.swift; sourceTree = ""; }; + B5BEBD632E93AE4B0002C9E5 /* MoveAndCopyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoveAndCopyTests.swift; sourceTree = ""; }; + B5BEBD642E93AE4B0002C9E5 /* NCNotificationText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCNotificationText.swift; sourceTree = ""; }; + B5BEBD652E93AE4B0002C9E5 /* OnboardingTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingTestCase.swift; sourceTree = ""; }; + B5BEBD662E93AE4B0002C9E5 /* PrivacyPolicyTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyPolicyTest.swift; sourceTree = ""; }; + B5BEBD672E93AE4B0002C9E5 /* RenameFileTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RenameFileTests.swift; sourceTree = ""; }; + B5BEBD682E93AE4B0002C9E5 /* ScanTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanTests.swift; sourceTree = ""; }; + B5BEBD692E93AE4B0002C9E5 /* SettingsTestCases.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsTestCases.swift; sourceTree = ""; }; + B5BEBD6A2E93AE4B0002C9E5 /* SharingTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharingTest.swift; sourceTree = ""; }; + B5BEBD782E93AEA30002C9E5 /* MoEngageAnalytics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoEngageAnalytics.swift; sourceTree = ""; }; + B5BEBD7A2E93AEA30002C9E5 /* AnalyticsHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsHelper.swift; sourceTree = ""; }; + B5BEBD7B2E93AEA30002C9E5 /* AnalyticsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsService.swift; sourceTree = ""; }; + B5BEBD922E93AED80002C9E5 /* AppUpdater.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppUpdater.swift; sourceTree = ""; }; + B5BEBD9B2E93AF010002C9E5 /* AppUtility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppUtility.swift; sourceTree = ""; }; + B5BEBD9C2E93AF010002C9E5 /* NCEmptyDataSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCEmptyDataSet.swift; sourceTree = ""; }; + B5BEBD9D2E93AF010002C9E5 /* NCEmptyView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCEmptyView.xib; sourceTree = ""; }; + B5BEBD9F2E93AF010002C9E5 /* AdjustHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AdjustHelper.h; sourceTree = ""; }; + B5BEBDA02E93AF010002C9E5 /* AdjustHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AdjustHelper.m; sourceTree = ""; }; + B5BEBDA12E93AF010002C9E5 /* TealiumHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TealiumHelper.swift; sourceTree = ""; }; + B5BEBDC62E93AF7E0002C9E5 /* NCLoginWeb.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCLoginWeb.swift; sourceTree = ""; }; + B5BEBDC82E93AFF10002C9E5 /* NCSelectableNavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSelectableNavigationView.swift; sourceTree = ""; }; + B5BEBDCA2E93B0210002C9E5 /* NCSectionHeaderMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSectionHeaderMenu.swift; sourceTree = ""; }; + B5BEBDCB2E93B0210002C9E5 /* NCSectionHeaderMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCSectionHeaderMenu.xib; sourceTree = ""; }; + B5BEBDD02E93B2450002C9E5 /* NCCreateFormUploadDocuments.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCCreateFormUploadDocuments.storyboard; sourceTree = ""; }; + B5BEBDD12E93B2450002C9E5 /* NCCreateFormUploadDocuments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateFormUploadDocuments.swift; sourceTree = ""; }; + B5BEBDD22E93B2450002C9E5 /* NCCreateFormUploadVoiceNote.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCCreateFormUploadVoiceNote.storyboard; sourceTree = ""; }; + B5BEBDD32E93B2450002C9E5 /* NCCreateFormUploadVoiceNote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateFormUploadVoiceNote.swift; sourceTree = ""; }; + B5BEBDD42E93B2450002C9E5 /* TextTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextTableViewCell.swift; sourceTree = ""; }; + B5BEBDD52E93B2450002C9E5 /* TextTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TextTableViewCell.xib; sourceTree = ""; }; + B5BEBDE22E93BD6F0002C9E5 /* NCMediaCommandView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCMediaCommandView.xib; sourceTree = ""; }; + B5BEBDE42E93BDB40002C9E5 /* FolderPathCustomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FolderPathCustomCell.swift; sourceTree = ""; }; + B5BEBDE52E93BDB40002C9E5 /* FolderPathCustomCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FolderPathCustomCell.xib; sourceTree = ""; }; + B5BEBDE62E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateDocumentCustomTextField.swift; sourceTree = ""; }; + B5BEBDE72E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCCreateDocumentCustomTextField.xib; sourceTree = ""; }; + B5BEBE052E93BE0C0002C9E5 /* NCCreateFormUploadScanDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateFormUploadScanDocument.swift; sourceTree = ""; }; + B5BEBE072E93BE200002C9E5 /* FileNameInputTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileNameInputTextField.swift; sourceTree = ""; }; + B5BEBE082E93BE200002C9E5 /* FileNameInputTextField.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FileNameInputTextField.xib; sourceTree = ""; }; + B5BEBE092E93BE200002C9E5 /* JPGImageSaveSwitchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JPGImageSaveSwitchView.swift; sourceTree = ""; }; + B5BEBE0A2E93BE200002C9E5 /* JPGImageSaveSwitchView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = JPGImageSaveSwitchView.xib; sourceTree = ""; }; + B5BEBE0B2E93BE200002C9E5 /* PasswordInputField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordInputField.swift; sourceTree = ""; }; + B5BEBE0C2E93BE200002C9E5 /* PasswordInputField.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PasswordInputField.xib; sourceTree = ""; }; + B5BEBE0D2E93BE200002C9E5 /* PdfWithOcrSwitchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PdfWithOcrSwitchView.swift; sourceTree = ""; }; + B5BEBE0E2E93BE200002C9E5 /* PdfWithOcrSwitchView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PdfWithOcrSwitchView.xib; sourceTree = ""; }; + B5BEBE0F2E93BE200002C9E5 /* PdfWithoutOcrSwitchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PdfWithoutOcrSwitchView.swift; sourceTree = ""; }; + B5BEBE102E93BE200002C9E5 /* PdfWithoutOcrSwitchView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PdfWithoutOcrSwitchView.xib; sourceTree = ""; }; + B5BEBE112E93BE200002C9E5 /* PNGImageSaveSwitchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PNGImageSaveSwitchView.swift; sourceTree = ""; }; + B5BEBE122E93BE200002C9E5 /* PNGImageSaveSwitchView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PNGImageSaveSwitchView.xib; sourceTree = ""; }; + B5BEBE132E93BE200002C9E5 /* ScanDocumentPathView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanDocumentPathView.swift; sourceTree = ""; }; + B5BEBE142E93BE200002C9E5 /* ScanDocumentPathView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ScanDocumentPathView.xib; sourceTree = ""; }; + B5BEBE152E93BE200002C9E5 /* SetPDFPasswordSwitchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetPDFPasswordSwitchView.swift; sourceTree = ""; }; + B5BEBE162E93BE200002C9E5 /* SetPDFPasswordSwitchView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SetPDFPasswordSwitchView.xib; sourceTree = ""; }; + B5BEBE172E93BE200002C9E5 /* TextFileWithOcrSwitchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFileWithOcrSwitchView.swift; sourceTree = ""; }; + B5BEBE182E93BE200002C9E5 /* TextFileWithOcrSwitchView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TextFileWithOcrSwitchView.xib; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B5BEBD182E93A5260002C9E5 /* Shareable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shareable.swift; sourceTree = ""; }; + B5BEBD1A2E93A74C0002C9E5 /* CreateLinkFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateLinkFooterView.swift; sourceTree = ""; }; + B5BEBD1B2E93A74C0002C9E5 /* NCPermissions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCPermissions.swift; sourceTree = ""; }; + B5BEBD1C2E93A74C0002C9E5 /* NCShareEmailLinkHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareEmailLinkHeaderView.swift; sourceTree = ""; }; + B5BEBD1D2E93A74C0002C9E5 /* NoSharesFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoSharesFooterView.swift; sourceTree = ""; }; + B5E2E6D32DAE52B500AB2EDD /* SharingTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharingTest.swift; sourceTree = ""; }; + B5E2E6D52DAE571200AB2EDD /* PasswordInputField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordInputField.swift; sourceTree = ""; }; + B5E2E6D62DAE571200AB2EDD /* PasswordInputField.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PasswordInputField.xib; sourceTree = ""; }; + B5E2E6D92DAE573B00AB2EDD /* NCFilePermissionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCFilePermissionCell.swift; sourceTree = ""; }; + B5E2E6DA2DAE573B00AB2EDD /* NCFilePermissionCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCFilePermissionCell.xib; sourceTree = ""; }; + B5E2E6DB2DAE573B00AB2EDD /* NCFilePermissionEditCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCFilePermissionEditCell.swift; sourceTree = ""; }; + B5E2E6DC2DAE573B00AB2EDD /* NCFilePermissionEditCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCFilePermissionEditCell.xib; sourceTree = ""; }; + B5E2E6E12DAE59CD00AB2EDD /* NCShareAdvancePermissionHeader.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCShareAdvancePermissionHeader.xib; sourceTree = ""; }; + B5E2E6E32DAE59F000AB2EDD /* NCShareHeaderCustomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareHeaderCustomCell.swift; sourceTree = ""; }; + B5E2E6E42DAE59F000AB2EDD /* NCShareHeaderCustomCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCShareHeaderCustomCell.xib; sourceTree = ""; }; + B5E2E6E52DAE59F000AB2EDD /* NCShareTextInputCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareTextInputCell.swift; sourceTree = ""; }; + B5E2E6E62DAE59F000AB2EDD /* NCShareTextInputCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCShareTextInputCell.xib; sourceTree = ""; }; + B5E2E6EB2DAE66AF00AB2EDD /* NCShareEmailFieldCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareEmailFieldCell.swift; sourceTree = ""; }; + B5E2E6EC2DAE66AF00AB2EDD /* NCShareEmailFieldCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCShareEmailFieldCell.xib; sourceTree = ""; }; + B5E2E6EF2DAE6E3F00AB2EDD /* ShareDownloadLimitNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareDownloadLimitNetwork.swift; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B5C9801D2DACEB5A0041B146 /* NCCollectionViewCommon+SwipeCollectionViewCellDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCCollectionViewCommon+SwipeCollectionViewCellDelegate.swift"; sourceTree = ""; }; + B5C9801F2DAD201A0041B146 /* NCSortMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSortMenu.swift; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B5C980172DACD51C0041B146 /* NCMediaCommandView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCMediaCommandView.xib; sourceTree = ""; }; + B5C980192DACD56C0041B146 /* NCMedia+Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCMedia+Menu.swift"; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B52FAED42DA8F616001AB1BD /* NCSelectableNavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSelectableNavigationView.swift; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B52FAED22DA8F22F001AB1BD /* MoveAndCopyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoveAndCopyTests.swift; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B52FAEA92DA8EF0C001AB1BD /* ScanTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanTests.swift; sourceTree = ""; }; + B52FAEAB2DA8EF2C001AB1BD /* NCCreateFormUploadScanDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateFormUploadScanDocument.swift; sourceTree = ""; }; + B52FAEAD2DA8EF84001AB1BD /* FileNameInputTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileNameInputTextField.swift; sourceTree = ""; }; + B52FAEAE2DA8EF84001AB1BD /* FileNameInputTextField.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FileNameInputTextField.xib; sourceTree = ""; }; + B52FAEAF2DA8EF84001AB1BD /* JPGImageSaveSwitchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JPGImageSaveSwitchView.swift; sourceTree = ""; }; + B52FAEB02DA8EF84001AB1BD /* JPGImageSaveSwitchView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = JPGImageSaveSwitchView.xib; sourceTree = ""; }; + B52FAEB12DA8EF84001AB1BD /* PasswordInputField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordInputField.swift; sourceTree = ""; }; + B52FAEB22DA8EF84001AB1BD /* PasswordInputField.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PasswordInputField.xib; sourceTree = ""; }; + B52FAEB32DA8EF84001AB1BD /* PdfWithOcrSwitchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PdfWithOcrSwitchView.swift; sourceTree = ""; }; + B52FAEB42DA8EF84001AB1BD /* PdfWithOcrSwitchView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PdfWithOcrSwitchView.xib; sourceTree = ""; }; + B52FAEB52DA8EF84001AB1BD /* PdfWithoutOcrSwitchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PdfWithoutOcrSwitchView.swift; sourceTree = ""; }; + B52FAEB62DA8EF84001AB1BD /* PdfWithoutOcrSwitchView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PdfWithoutOcrSwitchView.xib; sourceTree = ""; }; + B52FAEB72DA8EF84001AB1BD /* PNGImageSaveSwitchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PNGImageSaveSwitchView.swift; sourceTree = ""; }; + B52FAEB82DA8EF84001AB1BD /* PNGImageSaveSwitchView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PNGImageSaveSwitchView.xib; sourceTree = ""; }; + B52FAEB92DA8EF84001AB1BD /* ScanDocumentPathView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanDocumentPathView.swift; sourceTree = ""; }; + B52FAEBA2DA8EF84001AB1BD /* ScanDocumentPathView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ScanDocumentPathView.xib; sourceTree = ""; }; + B52FAEBB2DA8EF84001AB1BD /* SetPDFPasswordSwitchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetPDFPasswordSwitchView.swift; sourceTree = ""; }; + B52FAEBC2DA8EF84001AB1BD /* SetPDFPasswordSwitchView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SetPDFPasswordSwitchView.xib; sourceTree = ""; }; + B52FAEBD2DA8EF84001AB1BD /* TextFileWithOcrSwitchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFileWithOcrSwitchView.swift; sourceTree = ""; }; + B52FAEBE2DA8EF84001AB1BD /* TextFileWithOcrSwitchView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TextFileWithOcrSwitchView.xib; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B52FAEA02DA8ED40001AB1BD /* AudioUploadTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioUploadTests.swift; sourceTree = ""; }; + B52FAEA32DA8EE60001AB1BD /* NCManageAutoUploadFileName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCManageAutoUploadFileName.swift; sourceTree = ""; }; + B52FAEA62DA8EE99001AB1BD /* CCManageAutoUpload.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CCManageAutoUpload.h; sourceTree = ""; }; + B52FAEA72DA8EE99001AB1BD /* CCManageAutoUpload.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CCManageAutoUpload.m; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B52FAE8F2DA8D9E1001AB1BD /* CollaboraTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollaboraTestCase.swift; sourceTree = ""; }; + B52FAE912DA8DCB2001AB1BD /* NCCreateFormUploadDocuments.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCCreateFormUploadDocuments.storyboard; sourceTree = ""; }; + B52FAE922DA8DCB2001AB1BD /* NCCreateFormUploadDocuments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateFormUploadDocuments.swift; sourceTree = ""; }; + B52FAE972DA8DED9001AB1BD /* FolderPathCustomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FolderPathCustomCell.swift; sourceTree = ""; }; + B52FAE982DA8DED9001AB1BD /* FolderPathCustomCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FolderPathCustomCell.xib; sourceTree = ""; }; + B52FAE992DA8DED9001AB1BD /* NCCreateDocumentCustomTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateDocumentCustomTextField.swift; sourceTree = ""; }; + B52FAE9A2DA8DED9001AB1BD /* NCCreateDocumentCustomTextField.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCCreateDocumentCustomTextField.xib; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B529E40C2E8D1F8B006D9131 /* NCManageE2EE.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCManageE2EE.swift; sourceTree = ""; }; + B568C2C82DA7CE560072FCB4 /* E2EETests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = E2EETests.swift; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B568C2B62DA7B5060072FCB4 /* SettingsTestCases.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsTestCases.swift; sourceTree = ""; }; + B568C2B82DA7CCC10072FCB4 /* CCAdvanced.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CCAdvanced.m; sourceTree = ""; }; + B568C2BA2DA7CCDB0072FCB4 /* HelpViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpViewController.swift; sourceTree = ""; }; + B568C2BB2DA7CCDB0072FCB4 /* ImprintViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImprintViewController.swift; sourceTree = ""; }; + B568C2BC2DA7CCDB0072FCB4 /* MagentaCloudVersionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MagentaCloudVersionView.swift; sourceTree = ""; }; + B568C2BD2DA7CCDB0072FCB4 /* MagentaCloudVersionView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MagentaCloudVersionView.xib; sourceTree = ""; }; + B568C2C22DA7CCEA0072FCB4 /* NCSettings.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NCSettings.m; sourceTree = ""; }; + B568C2C32DA7CCEA0072FCB4 /* OpenSourceSoftwareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenSourceSoftwareViewController.swift; sourceTree = ""; }; + B568C2C62DA7CD930072FCB4 /* CCAdvanced.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CCAdvanced.h; sourceTree = ""; }; + B568C2C72DA7CD930072FCB4 /* NCSettings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NCSettings.h; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B568C2B02DA7AA5F0072FCB4 /* MoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoreTests.swift; sourceTree = ""; }; + B568C2B22DA7AAAE0072FCB4 /* NCMoreUserCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCMoreUserCell.xib; sourceTree = ""; }; + B568C2B42DA7AADD0072FCB4 /* NCMoreUserCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMoreUserCell.swift; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B529E4062E8D1C3E006D9131 /* NCUploadAssets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCUploadAssets.swift; sourceTree = ""; }; + B568C2AC2DA7A9000072FCB4 /* AssetUploadTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssetUploadTest.swift; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B543154D2DA6913C00981E7E /* AudioUploadTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioUploadTests.swift; sourceTree = ""; }; + B543154F2DA6929700981E7E /* FolderPathCustomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FolderPathCustomCell.swift; sourceTree = ""; }; + B54315502DA6929700981E7E /* FolderPathCustomCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FolderPathCustomCell.xib; sourceTree = ""; }; + B54315512DA6929700981E7E /* NCCreateFormUploadVoiceNote.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCCreateFormUploadVoiceNote.storyboard; sourceTree = ""; }; + B54315522DA6929700981E7E /* NCCreateFormUploadVoiceNote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateFormUploadVoiceNote.swift; sourceTree = ""; }; + B54315532DA6929700981E7E /* TextTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextTableViewCell.swift; sourceTree = ""; }; + B54315542DA6929700981E7E /* TextTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TextTableViewCell.xib; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B543154B2DA690B700981E7E /* NCNotificationText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCNotificationText.swift; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B54315352DA64EB100981E7E /* PrivacyPolicyTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyPolicyTest.swift; sourceTree = ""; }; + B54315372DA669C700981E7E /* AnalysisDataCollectionSwitch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalysisDataCollectionSwitch.swift; sourceTree = ""; }; + B54315382DA669C700981E7E /* AnalysisDataCollectionSwitch.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AnalysisDataCollectionSwitch.xib; sourceTree = ""; }; + B54315392DA669C700981E7E /* InitialPrivacySettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InitialPrivacySettingsViewController.swift; sourceTree = ""; }; + B543153A2DA669C700981E7E /* NCSettings.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCSettings.storyboard; sourceTree = ""; }; + B543153B2DA669C700981E7E /* PrivacyPolicyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyPolicyViewController.swift; sourceTree = ""; }; + B543153C2DA669C700981E7E /* PrivacySettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacySettingsViewController.swift; sourceTree = ""; }; + B543153D2DA669C700981E7E /* RequiredDataCollectionSwitch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequiredDataCollectionSwitch.swift; sourceTree = ""; }; + B543153E2DA669C700981E7E /* RequiredDataCollectionSwitch.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RequiredDataCollectionSwitch.xib; sourceTree = ""; }; + B543153F2DA669C700981E7E /* SaveSettingsCustomButtonCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SaveSettingsCustomButtonCell.swift; sourceTree = ""; }; + B54315402DA669C700981E7E /* SaveSettingsCustomButtonCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SaveSettingsCustomButtonCell.xib; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B54315312DA64BAF00981E7E /* OnboardingTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingTestCase.swift; sourceTree = ""; }; + B54315332DA64D6500981E7E /* AppUtility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppUtility.swift; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B543152F2DA647A400981E7E /* NCLoginWeb.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCLoginWeb.swift; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B5D45E712DA5172900773929 /* AppUpdater.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppUpdater.swift; sourceTree = ""; }; + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShare+Helper.swift"; sourceTree = ""; }; + B5D45E6A2DA510E000773929 /* NCRenameFile.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCRenameFile.storyboard; sourceTree = ""; }; + B5D45E6B2DA510E000773929 /* NCRenameFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCRenameFile.swift; sourceTree = ""; }; + B5D45E6F2DA5119A00773929 /* RenameFileTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RenameFileTests.swift; sourceTree = ""; }; C0046CDA2A17B98400D87C9D /* NextcloudUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NextcloudUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; C04E2F202A17BB4D001BAD85 /* NextcloudIntegrationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NextcloudIntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCActivityTableViewCell.swift; sourceTree = ""; }; @@ -1385,11 +1850,9 @@ F343A4BA2A1E734600DDA874 /* Optional+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optional+Extension.swift"; sourceTree = ""; }; F351D1A52D0AF24A00930F94 /* PHAssetCollection+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PHAssetCollection+Extension.swift"; sourceTree = ""; }; F359D8662A7D03420023F405 /* NCUtility+Exif.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCUtility+Exif.swift"; sourceTree = ""; }; - F36C514D2E89393C0097E5F7 /* UIView+BlurVibrancy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+BlurVibrancy.swift"; sourceTree = ""; }; - F36E64F62B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBarDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCCollectionViewCommon+SelectTabBarDelegate.swift"; sourceTree = ""; }; + F36E64F62B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCCollectionViewCommon+SelectTabBar.swift"; sourceTree = ""; }; F37208742BAB4AB0006B5430 /* TestConstants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestConstants.swift; sourceTree = ""; }; F3754A7C2CF87D600009312E /* SetupPasscodeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetupPasscodeView.swift; sourceTree = ""; }; - F376A3732E5CC5FF0067EE25 /* ContextMenuActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextMenuActions.swift; sourceTree = ""; }; F389C9F42CEE383300049762 /* SelectAlbumView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectAlbumView.swift; sourceTree = ""; }; F38F71242B6BBDC300473CDC /* NCCollectionViewCommonSelectTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCollectionViewCommonSelectTabBar.swift; sourceTree = ""; }; F39170A82CB8201B006127BC /* FileAutoRenamer+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileAutoRenamer+Extensions.swift"; sourceTree = ""; }; @@ -1407,7 +1870,6 @@ F3CA337C2D0B2B6A00672333 /* AlbumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumModel.swift; sourceTree = ""; }; F3E173AF2C9AF637006D177A /* ScreenAwakeManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenAwakeManager.swift; sourceTree = ""; }; F3E173BF2C9B1067006D177A /* AwakeMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AwakeMode.swift; sourceTree = ""; }; - F3F442ED2DDE292600FD701F /* NCMetadataPermissions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMetadataPermissions.swift; sourceTree = ""; }; F700222B1EC479840080073F /* Custom.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Custom.xcassets; sourceTree = ""; }; F700510022DF63AC003A3356 /* NCShare.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCShare.storyboard; sourceTree = ""; }; F700510422DF6A89003A3356 /* NCShare.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShare.swift; sourceTree = ""; }; @@ -1440,7 +1902,7 @@ F70D8D8024A4A9BF000A5756 /* NCNetworkingProcess.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCNetworkingProcess.swift; sourceTree = ""; }; F70F96AF2874394B006C8379 /* Nextcloud-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Nextcloud-Bridging-Header.h"; sourceTree = ""; }; F710D1F42405770F00A6033D /* NCViewerPDF.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCViewerPDF.swift; sourceTree = ""; }; - F710D2012405826100A6033D /* NCViewerContextMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCViewerContextMenu.swift; sourceTree = ""; }; + F710D2012405826100A6033D /* NCViewer+Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCViewer+Menu.swift"; sourceTree = ""; }; F711A4DB2AF92CAD00095DD8 /* NCUtility+Date.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCUtility+Date.swift"; sourceTree = ""; }; F7132C6B2D085AD200B42D6A /* NCTermOfServiceModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCTermOfServiceModel.swift; sourceTree = ""; }; F7132C6C2D085AD200B42D6A /* NCTermOfServiceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCTermOfServiceView.swift; sourceTree = ""; }; @@ -1457,7 +1919,6 @@ F717402C24F699A5000C87D5 /* NCFavorite.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCFavorite.swift; sourceTree = ""; }; F718C24D254D507B00C5C256 /* NCViewerMediaDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCViewerMediaDetailView.swift; sourceTree = ""; }; F718E2572DF2D5C3004038AF /* NCBackgroundLocationUploadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCBackgroundLocationUploadManager.swift; sourceTree = ""; }; - F71916102E2901E800E13E96 /* NCNetworking+Upload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCNetworking+Upload.swift"; sourceTree = ""; }; F719D9DF288D37A300762E33 /* NCColorPicker.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCColorPicker.storyboard; sourceTree = ""; }; F719D9E1288D396100762E33 /* NCColorPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCColorPicker.swift; sourceTree = ""; }; F71CD6C92930D7B1006C95C1 /* NCApplicationHandle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCApplicationHandle.swift; sourceTree = ""; }; @@ -1469,7 +1930,7 @@ F723985B253C95CE00257F49 /* NCViewerRichdocument.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCViewerRichdocument.storyboard; sourceTree = ""; }; F723B3DC22FC6D1C00301EFE /* NCShareCommentsCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCShareCommentsCell.xib; sourceTree = ""; }; F72408322B8A27C900F128E2 /* NCMedia+Command.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCMedia+Command.swift"; sourceTree = ""; }; - F724377A2C10B83E00C7C68D /* NCSharePermissions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSharePermissions.swift; sourceTree = ""; }; + F724377A2C10B83E00C7C68D /* NCPermissions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCPermissions.swift; sourceTree = ""; }; F7245923289BB50B00474787 /* ThreadSafeDictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreadSafeDictionary.swift; sourceTree = ""; }; F72685E827C78E490019EF5E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; F72944F12A84246400246839 /* NCEndToEndMetadataV20.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCEndToEndMetadataV20.swift; sourceTree = ""; }; @@ -1487,6 +1948,7 @@ F7320934201B812F008A0888 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = ""; }; F732093B201B81E4008A0888 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/Localizable.strings"; sourceTree = ""; }; F7327E1F2B73A42F00A462C7 /* NCNetworking+Download.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCNetworking+Download.swift"; sourceTree = ""; }; + F7327E272B73A53400A462C7 /* NCNetworking+Upload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCNetworking+Upload.swift"; sourceTree = ""; }; F7327E2F2B73A86700A462C7 /* NCNetworking+WebDAV.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCNetworking+WebDAV.swift"; sourceTree = ""; }; F7327E342B73AEDE00A462C7 /* NCNetworking+LivePhoto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCNetworking+LivePhoto.swift"; sourceTree = ""; }; F7327E3C2B73B92800A462C7 /* NCNetworking+Synchronization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCNetworking+Synchronization.swift"; sourceTree = ""; }; @@ -1501,6 +1963,8 @@ F7381EDA218218C9000B1560 /* NCOffline.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCOffline.swift; sourceTree = ""; }; F7381EDE218218C9000B1560 /* NCOffline.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCOffline.storyboard; sourceTree = ""; }; F7386E452DA90E02009A00F6 /* NCAppVersionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCAppVersionManager.swift; sourceTree = ""; }; + F73B42292476764F00A30FD3 /* NCNotification.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = NCNotification.storyboard; path = Notification/NCNotification.storyboard; sourceTree = ""; }; + F73B422A2476764F00A30FD3 /* NCNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NCNotification.swift; path = Notification/NCNotification.swift; sourceTree = ""; }; F73CB3B122E072A000AD728E /* NCShareHeaderView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCShareHeaderView.xib; sourceTree = ""; }; F73CB5771ED46807005F2A5A /* NCBridgeSwift.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NCBridgeSwift.h; sourceTree = ""; }; F73D11F9253C5F4800DF9BEC /* NCViewerNextcloudText.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCViewerNextcloudText.storyboard; sourceTree = ""; }; @@ -1515,7 +1979,6 @@ F7411C532D7B26C600F57358 /* NCNetworking+ServerError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCNetworking+ServerError.swift"; sourceTree = ""; }; F741C2232B6B9FD600E849BB /* NCMediaSelectTabBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCMediaSelectTabBar.swift; sourceTree = ""; }; F74230F22C79B57200CA1ACA /* NCNetworking+Task.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCNetworking+Task.swift"; sourceTree = ""; }; - F743C89D2E5B2595000173A9 /* UIScene+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIScene+Extension.swift"; sourceTree = ""; }; F745B252222D88AE00346520 /* NCLoginQRCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCLoginQRCode.swift; sourceTree = ""; }; F747EB0C2C4AC1FF00F959A8 /* NCCollectionViewCommon+CollectionViewDelegateFlowLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCCollectionViewCommon+CollectionViewDelegateFlowLayout.swift"; sourceTree = ""; }; F749B649297B0CBB00087535 /* NCManageDatabase+Share.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+Share.swift"; sourceTree = ""; }; @@ -1531,11 +1994,9 @@ F7501C312212E57400FB1415 /* NCMedia.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCMedia.swift; sourceTree = ""; }; F751247A2C42919C00E63DB8 /* NCPhotoCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCPhotoCell.swift; sourceTree = ""; }; F751247B2C42919C00E63DB8 /* NCPhotoCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCPhotoCell.xib; sourceTree = ""; }; - F752BA042E58C05200616A26 /* Maintenance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Maintenance.swift; sourceTree = ""; }; F753701822723D620041C76C /* gl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = gl; path = gl.lproj/Localizable.strings; sourceTree = ""; }; F753701922723E0D0041C76C /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/Localizable.strings; sourceTree = ""; }; F753701A22723EC80041C76C /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Localizable.strings; sourceTree = ""; }; - F753DBDE2E5D99B700A1AF91 /* NCFiles+SyncMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCFiles+SyncMetadata.swift"; sourceTree = ""; }; F755BD9A20594AC7008C5FBB /* NCService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCService.swift; sourceTree = ""; }; F755CB3F2B8CB13C00CE27E9 /* NCMediaLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCMediaLayout.swift; sourceTree = ""; }; F757CC8129E7F88B00F31428 /* NCManageDatabase+Groupfolders.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+Groupfolders.swift"; sourceTree = ""; }; @@ -1579,7 +2040,7 @@ F768820F2C0DD1E7001CF441 /* NCEndToEndInitialize.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCEndToEndInitialize.swift; sourceTree = ""; }; F76882102C0DD1E7001CF441 /* NCManageE2EEModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCManageE2EEModel.swift; sourceTree = ""; }; F76882112C0DD1E7001CF441 /* NCSettingsModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCSettingsModel.swift; sourceTree = ""; }; - F76882132C0DD1E7001CF441 /* NCPreferences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCPreferences.swift; sourceTree = ""; }; + F76882132C0DD1E7001CF441 /* NCKeychain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCKeychain.swift; sourceTree = ""; }; F76882142C0DD1E7001CF441 /* Acknowledgements.rtf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.rtf; path = Acknowledgements.rtf; sourceTree = ""; }; F76882152C0DD1E7001CF441 /* NCSettingsBundleHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCSettingsBundleHelper.swift; sourceTree = ""; }; F76882192C0DD1E7001CF441 /* NCFileNameModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCFileNameModel.swift; sourceTree = ""; }; @@ -1647,7 +2108,6 @@ F77C3F5A2D9BF8B500F3C471 /* UITabBar+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITabBar+Extension.swift"; sourceTree = ""; }; F77C97382953131000FDDD09 /* NCCameraRoll.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCameraRoll.swift; sourceTree = ""; }; F77DD6A72C5CC093009448FB /* NCSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSession.swift; sourceTree = ""; }; - F77E8C1E2E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+LivePhoto.swift"; sourceTree = ""; }; F77ED59028C9CE9D00E24ED0 /* ToolbarData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolbarData.swift; sourceTree = ""; }; F77ED59228C9CEA000E24ED0 /* ToolbarWidgetProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolbarWidgetProvider.swift; sourceTree = ""; }; F77ED59428C9CEA300E24ED0 /* ToolbarWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolbarWidgetView.swift; sourceTree = ""; }; @@ -1684,7 +2144,6 @@ F79131C728AFB86E00577277 /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/InfoPlist.strings; sourceTree = ""; }; F794E13C2BBBFF2E003693D7 /* NCMainTabBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMainTabBarController.swift; sourceTree = ""; }; F794E13E2BBC0F70003693D7 /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; - F79699E62E689F68000EC82A /* NCMediaNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMediaNavigationController.swift; sourceTree = ""; }; F799DF812C4B7DCC003410B5 /* NCSectionFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSectionFooter.swift; sourceTree = ""; }; F799DF842C4B7E56003410B5 /* NCSectionHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSectionHeader.swift; sourceTree = ""; }; F799DF872C4B83CC003410B5 /* NCCollectionViewCommon+EasyTipView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCCollectionViewCommon+EasyTipView.swift"; sourceTree = ""; }; @@ -1705,8 +2164,11 @@ F7A509242C26BD5D00326106 /* NCCreateDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateDocument.swift; sourceTree = ""; }; F7A560412AE1593700BE8FD6 /* NCOperationSaveLivePhoto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCOperationSaveLivePhoto.swift; sourceTree = ""; }; F7A573682E190377009C9257 /* NCShareExtensionData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareExtensionData.swift; sourceTree = ""; }; + F7A60F84292D215000FCE1F2 /* NCShareAccounts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCShareAccounts.swift; sourceTree = ""; }; + F7A60F85292D215000FCE1F2 /* NCShareAccounts.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCShareAccounts.storyboard; sourceTree = ""; }; F7A7FDDB2C2DBD6200E9A93A /* NCDeepLinkHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCDeepLinkHandler.swift; sourceTree = ""; }; F7A846DD2BB01ACB0024816F /* NCTrashCellProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCTrashCellProtocol.swift; sourceTree = ""; }; + F7A8FD512C5E2557006C9CF8 /* NCAccount.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCAccount.swift; sourceTree = ""; }; F7AA41B827C7CF4600494705 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/InfoPlist.strings; sourceTree = ""; }; F7AA41B927C7CF4B00494705 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = ""; }; F7AA41BA27C7CF5000494705 /* zh-Hant-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant-TW"; path = "zh-Hant-TW.lproj/InfoPlist.strings"; sourceTree = ""; }; @@ -1754,6 +2216,8 @@ F7AE00F4230D5F9E007ACF8A /* NCLoginProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCLoginProvider.swift; sourceTree = ""; }; F7AE00F7230E81CB007ACF8A /* NCBrowserWeb.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCBrowserWeb.swift; sourceTree = ""; }; F7AE00F9230E81EB007ACF8A /* NCBrowserWeb.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCBrowserWeb.storyboard; sourceTree = ""; }; + F7AEEAA52C11DBAF00011412 /* NCAccountSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCAccountSettingsView.swift; sourceTree = ""; }; + F7AEEAA72C11DBFD00011412 /* NCAccountSettingsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCAccountSettingsModel.swift; sourceTree = ""; }; F7B1A7761EBB3C8000BFB6D1 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; F7B398412A6A91D5007538D6 /* NCSectionFirstHeader.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCSectionFirstHeader.xib; sourceTree = ""; }; F7B6B70327C4E7FA00A7F6EB /* NCScan+CollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCScan+CollectionView.swift"; sourceTree = ""; }; @@ -1826,6 +2290,8 @@ F7C9739028F17131002C43E2 /* WidgetDashboardIntentHandler.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = WidgetDashboardIntentHandler.appex; sourceTree = BUILT_PRODUCTS_DIR; }; F7C9739428F17131002C43E2 /* IntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentHandler.swift; sourceTree = ""; }; F7C9B91C2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+SecurityGuard.swift"; sourceTree = ""; }; + F7CA212B25F1333200826ABB /* NCAccountRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCAccountRequest.swift; sourceTree = ""; }; + F7CA212C25F1333200826ABB /* NCAccountRequest.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCAccountRequest.storyboard; sourceTree = ""; }; F7CB68992541676B0050EC94 /* NCMore.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCMore.storyboard; sourceTree = ""; }; F7CBC1212BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCSectionFirstHeaderEmptyData.xib; sourceTree = ""; }; F7CBC1222BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCSectionFirstHeaderEmptyData.swift; sourceTree = ""; }; @@ -1884,7 +2350,6 @@ F7D68FCB28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+DashboardWidget.swift"; sourceTree = ""; }; F7D7A76B2DCDD437003D2007 /* NCManageDatabase+AutoUpload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+AutoUpload.swift"; sourceTree = ""; }; F7D890742BD25C570050B8A6 /* NCCollectionViewCommon+DragDrop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCCollectionViewCommon+DragDrop.swift"; sourceTree = ""; }; - F7DB7DE82E8173160017AF90 /* NCStorageEstimator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCStorageEstimator.swift; sourceTree = ""; }; F7DE9AB01F482FA5008DFE10 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = ""; }; F7E0710028B13BB00001B882 /* DashboardData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardData.swift; sourceTree = ""; }; F7E0CDCE265CE8610044854E /* NCUserStatus.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCUserStatus.storyboard; sourceTree = ""; }; @@ -1904,8 +2369,6 @@ F7EDE513262DC2CD00414FE6 /* NCSelectCommandViewSelect+CreateFolder.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "NCSelectCommandViewSelect+CreateFolder.xib"; sourceTree = ""; }; F7EDE51A262DD0C400414FE6 /* NCSelectCommandViewCopyMove.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCSelectCommandViewCopyMove.xib; sourceTree = ""; }; F7EE66AC2A20B226009AE765 /* UILabel+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILabel+Extension.swift"; sourceTree = ""; }; - F7EF2AE82E43157B0081B2C9 /* NCNotification.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCNotification.storyboard; sourceTree = ""; }; - F7EF2AE92E43157B0081B2C9 /* NCNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCNotification.swift; sourceTree = ""; }; F7EFA47725ADBA500083159A /* NCViewerProviderContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCViewerProviderContextMenu.swift; sourceTree = ""; }; F7EFC0CC256BF8DD00461AAD /* NCUserStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCUserStatus.swift; sourceTree = ""; }; F7F3E58A2D3BB65000A32B14 /* NCNetworking+Recommendations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCNetworking+Recommendations.swift"; sourceTree = ""; }; @@ -1918,7 +2381,6 @@ F7F4F10327ECDBDB008676F9 /* Inconsolata-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inconsolata-Light.ttf"; sourceTree = ""; }; F7F4F10427ECDBDB008676F9 /* Inconsolata-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inconsolata-Regular.ttf"; sourceTree = ""; }; F7F4F11127ECDC52008676F9 /* UIFont+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIFont+Extension.swift"; sourceTree = ""; }; - F7F562FF2E15761500631A11 /* MigrationMultiDomains.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationMultiDomains.swift; sourceTree = ""; }; F7F67BB81A24D27800EE80DA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; F7F878AD1FB9E3B900599E4F /* NCEndToEndMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCEndToEndMetadata.swift; sourceTree = ""; }; F7F9D1BA25397CE000D9BFF5 /* NCViewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCViewer.swift; sourceTree = ""; }; @@ -1926,13 +2388,6 @@ F7FA7FFE2C0F4F3B0072FC60 /* NCUploadAssetsModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCUploadAssetsModel.swift; sourceTree = ""; }; F7FA7FFF2C0F4F3B0072FC60 /* NCUploadAssetsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCUploadAssetsView.swift; sourceTree = ""; }; F7FAFD3928BFA947000777FE /* NCNotification+Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCNotification+Menu.swift"; sourceTree = ""; }; - F7FDFF512E437E55000D7688 /* NCAccountRequest.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCAccountRequest.storyboard; sourceTree = ""; }; - F7FDFF522E437E55000D7688 /* NCAccountRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCAccountRequest.swift; sourceTree = ""; }; - F7FDFF532E437E55000D7688 /* NCShareAccounts.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCShareAccounts.storyboard; sourceTree = ""; }; - F7FDFF542E437E55000D7688 /* NCShareAccounts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareAccounts.swift; sourceTree = ""; }; - F7FDFF562E437E55000D7688 /* NCAccountSettingsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCAccountSettingsModel.swift; sourceTree = ""; }; - F7FDFF572E437E55000D7688 /* NCAccountSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCAccountSettingsView.swift; sourceTree = ""; }; - F7FDFF592E437E55000D7688 /* NCAccount.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCAccount.swift; sourceTree = ""; }; F7FF2CB02842159500EBB7A1 /* NCSectionHeader.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCSectionHeader.xib; sourceTree = ""; }; /* End PBXFileReference section */ @@ -1946,9 +2401,7 @@ buildActionMask = 2147483647; files = ( F33EE6ED2BF4C03800CA1A51 /* NIOSSL in Frameworks */, - F7F1FBB02E27D3A800C79E20 /* Queuer in Frameworks */, F72AD71128C24BBB006CB92D /* NextcloudKit in Frameworks */, - F7F1FBAE2E27D3A400C79E20 /* SwiftEntryKit in Frameworks */, F710FC88277B7D3F00AA9FBF /* RealmSwift in Frameworks */, F760DE0F2AE66EE60027D78A /* KeychainAccess in Frameworks */, ); @@ -2008,7 +2461,6 @@ buildActionMask = 2147483647; files = ( F7490E8B29882CE4009DCE94 /* NextcloudKit in Frameworks */, - F7F1FBAC2E27D20400C79E20 /* Queuer in Frameworks */, F7490E8929882CC8009DCE94 /* SwiftEntryKit in Frameworks */, F33EE6EB2BF4C03200CA1A51 /* NIOSSL in Frameworks */, F7490E7229882BB4009DCE94 /* RealmSwift in Frameworks */, @@ -2108,9 +2560,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - F7F1FBA82E27D13700C79E20 /* Queuer in Frameworks */, F7A8D72828F17728008BBE1C /* RealmSwift in Frameworks */, - F7F1FBAA2E27D14000C79E20 /* SwiftEntryKit in Frameworks */, F7A8D72428F1771B008BBE1C /* NextcloudKit in Frameworks */, F33EE6E52BF4C02000CA1A51 /* NIOSSL in Frameworks */, F760DE072AE66EC70027D78A /* KeychainAccess in Frameworks */, @@ -2135,15 +2585,21 @@ F376A3732E5CC5FF0067EE25 /* ContextMenuActions.swift */, F77A697C250A0FBC00FF1708 /* NCCollectionViewCommon+Menu.swift */, F78C6FDD296D677300C952C3 /* NCContextMenu.swift */, + B5C9801F2DAD201A0041B146 /* NCSortMenu.swift */, + B5C980192DACD56C0041B146 /* NCMedia+Menu.swift */, 3704EB2923D5A58400455C5B /* NCMenu.storyboard */, 371B5A2D23D0B04500FAFAE9 /* NCMenu.swift */, - AF935066276B84E700BD078F /* NCMenu+FloatingPanel.swift */, AF68326927BE65A90010BF0B /* NCMenuAction.swift */, F7FAFD3928BFA947000777FE /* NCNotification+Menu.swift */, - AF93471127E2341B002537EE /* NCShare+Menu.swift */, - F75D19E225EFE09000D74598 /* NCTrash+Menu.swift */, - F710D2012405826100A6033D /* NCViewerContextMenu.swift */, + AF935066276B84E700BD078F /* NCMenu+FloatingPanel.swift */, + 3781B9AF23DB2B7E006B4B1D /* AppDelegate+Menu.swift */, 8491B1CC273BBA82001C8C5B /* UIViewController+Menu.swift */, + F77A697C250A0FBC00FF1708 /* NCCollectionViewCommon+Menu.swift */, + F75D19E225EFE09000D74598 /* NCTrash+Menu.swift */, + AF93471127E2341B002537EE /* NCShare+Menu.swift */, + F710D2012405826100A6033D /* NCViewer+Menu.swift */, + F78C6FDD296D677300C952C3 /* NCContextMenu.swift */, + F7A560412AE1593700BE8FD6 /* NCOperationSaveLivePhoto.swift */, ); path = Menu; sourceTree = ""; @@ -2172,7 +2628,37 @@ AA52EB442D42AC500089C348 /* NextcloudUnitTests */ = { isa = PBXGroup; children = ( + B5BEBD5E2E93AE4B0002C9E5 /* AssetUploadTest.swift */, + B5BEBD5F2E93AE4B0002C9E5 /* AudioUploadTests.swift */, + B5BEBD602E93AE4B0002C9E5 /* CollaboraTestCase.swift */, + B5BEBD612E93AE4B0002C9E5 /* E2EETests.swift */, + B5BEBD622E93AE4B0002C9E5 /* MoreTests.swift */, + B5BEBD632E93AE4B0002C9E5 /* MoveAndCopyTests.swift */, + B5BEBD642E93AE4B0002C9E5 /* NCNotificationText.swift */, + B5BEBD652E93AE4B0002C9E5 /* OnboardingTestCase.swift */, + B5BEBD662E93AE4B0002C9E5 /* PrivacyPolicyTest.swift */, + B5BEBD672E93AE4B0002C9E5 /* RenameFileTests.swift */, + B5BEBD682E93AE4B0002C9E5 /* ScanTests.swift */, + B5BEBD692E93AE4B0002C9E5 /* SettingsTestCases.swift */, + B5BEBD6A2E93AE4B0002C9E5 /* SharingTest.swift */, AA52EB452D42AC5A0089C348 /* Placeholder.swift */, + B5E2E6D32DAE52B500AB2EDD /* SharingTest.swift */, + B52FAED22DA8F22F001AB1BD /* MoveAndCopyTests.swift */, + B52FAEA92DA8EF0C001AB1BD /* ScanTests.swift */, + B52FAEA02DA8ED40001AB1BD /* AudioUploadTests.swift */, + B52FAE8F2DA8D9E1001AB1BD /* CollaboraTestCase.swift */, + AF8ED1FB2757821000B8DBC4 /* NextcloudUnitTests.swift */, + B568C2C82DA7CE560072FCB4 /* E2EETests.swift */, + B568C2B62DA7B5060072FCB4 /* SettingsTestCases.swift */, + B568C2B02DA7AA5F0072FCB4 /* MoreTests.swift */, + AF8ED1FB2757821000B8DBC4 /* NextcloudUnitTests.swift */, + B568C2AC2DA7A9000072FCB4 /* AssetUploadTest.swift */, + B543154D2DA6913C00981E7E /* AudioUploadTests.swift */, + B543154B2DA690B700981E7E /* NCNotificationText.swift */, + B54315352DA64EB100981E7E /* PrivacyPolicyTest.swift */, + B54315312DA64BAF00981E7E /* OnboardingTestCase.swift */, + B5D45E6F2DA5119A00773929 /* RenameFileTests.swift */, + AF8ED1FB2757821000B8DBC4 /* NextcloudUnitTests.swift */, ); path = NextcloudUnitTests; sourceTree = ""; @@ -2200,6 +2686,15 @@ isa = PBXGroup; children = ( AA8D316D2D4123B200FE2775 /* DownloadLimit */, + B5E2E6E32DAE59F000AB2EDD /* NCShareHeaderCustomCell.swift */, + B5E2E6E42DAE59F000AB2EDD /* NCShareHeaderCustomCell.xib */, + B5E2E6E52DAE59F000AB2EDD /* NCShareTextInputCell.swift */, + B5E2E6E62DAE59F000AB2EDD /* NCShareTextInputCell.xib */, + B5E2E6E12DAE59CD00AB2EDD /* NCShareAdvancePermissionHeader.xib */, + B5E2E6D92DAE573B00AB2EDD /* NCFilePermissionCell.swift */, + B5E2E6DA2DAE573B00AB2EDD /* NCFilePermissionCell.xib */, + B5E2E6DB2DAE573B00AB2EDD /* NCFilePermissionEditCell.swift */, + B5E2E6DC2DAE573B00AB2EDD /* NCFilePermissionEditCell.xib */, AF93471627E2361E002537EE /* NCShareAdvancePermission.swift */, AF93471827E2361E002537EE /* NCShareAdvancePermissionFooter.swift */, AF93471427E2361E002537EE /* NCShareAdvancePermissionFooter.xib */, @@ -2211,6 +2706,135 @@ path = Advanced; sourceTree = ""; }; + B5BEBD512E93AE1C0002C9E5 /* Common */ = { + isa = PBXGroup; + children = ( + B5BEBD4F2E93AE1C0002C9E5 /* BaseXCTestCase.swift */, + B5BEBD502E93AE1C0002C9E5 /* TestConstants.swift */, + ); + path = Common; + sourceTree = ""; + }; + B5BEBD792E93AEA30002C9E5 /* MoEngage */ = { + isa = PBXGroup; + children = ( + B5BEBD782E93AEA30002C9E5 /* MoEngageAnalytics.swift */, + ); + path = MoEngage; + sourceTree = ""; + }; + B5BEBD7C2E93AEA30002C9E5 /* Analytics */ = { + isa = PBXGroup; + children = ( + B5BEBD792E93AEA30002C9E5 /* MoEngage */, + B5BEBD7A2E93AEA30002C9E5 /* AnalyticsHelper.swift */, + B5BEBD7B2E93AEA30002C9E5 /* AnalyticsService.swift */, + ); + path = Analytics; + sourceTree = ""; + }; + B5BEBD932E93AED80002C9E5 /* AppUpdate */ = { + isa = PBXGroup; + children = ( + B5BEBD922E93AED80002C9E5 /* AppUpdater.swift */, + B5D45E722DA5172900773929 /* AppUpdate */ = { + isa = PBXGroup; + children = ( + B5D45E712DA5172900773929 /* AppUpdater.swift */, + ); + path = AppUpdate; + sourceTree = ""; + }; + B5BEBD9E2E93AF010002C9E5 /* EmptyView */ = { + isa = PBXGroup; + children = ( + B5BEBD9C2E93AF010002C9E5 /* NCEmptyDataSet.swift */, + B5BEBD9D2E93AF010002C9E5 /* NCEmptyView.xib */, + ); + path = EmptyView; + sourceTree = ""; + }; + B5BEBDA22E93AF010002C9E5 /* Helper */ = { + isa = PBXGroup; + children = ( + B5BEBD9F2E93AF010002C9E5 /* AdjustHelper.h */, + B5BEBDA02E93AF010002C9E5 /* AdjustHelper.m */, + B5BEBDA12E93AF010002C9E5 /* TealiumHelper.swift */, + ); + path = Helper; + sourceTree = ""; + }; + B5BEBDE82E93BDB40002C9E5 /* NMC Custom Views */ = { + isa = PBXGroup; + children = ( + B5BEBDE42E93BDB40002C9E5 /* FolderPathCustomCell.swift */, + B5BEBDE52E93BDB40002C9E5 /* FolderPathCustomCell.xib */, + B5BEBDE62E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift */, + B5BEBDE72E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib */, + B52FAE9B2DA8DED9001AB1BD /* NMC Custom Views */ = { + isa = PBXGroup; + children = ( + B52FAE972DA8DED9001AB1BD /* FolderPathCustomCell.swift */, + B52FAE982DA8DED9001AB1BD /* FolderPathCustomCell.xib */, + B52FAE992DA8DED9001AB1BD /* NCCreateDocumentCustomTextField.swift */, + B52FAE9A2DA8DED9001AB1BD /* NCCreateDocumentCustomTextField.xib */, + ); + path = "NMC Custom Views"; + sourceTree = ""; + }; + B5BEBE192E93BE200002C9E5 /* NMC Views */ = { + isa = PBXGroup; + children = ( + B5BEBE072E93BE200002C9E5 /* FileNameInputTextField.swift */, + B5BEBE082E93BE200002C9E5 /* FileNameInputTextField.xib */, + B5BEBE092E93BE200002C9E5 /* JPGImageSaveSwitchView.swift */, + B5BEBE0A2E93BE200002C9E5 /* JPGImageSaveSwitchView.xib */, + B5BEBE0B2E93BE200002C9E5 /* PasswordInputField.swift */, + B5BEBE0C2E93BE200002C9E5 /* PasswordInputField.xib */, + B5BEBE0D2E93BE200002C9E5 /* PdfWithOcrSwitchView.swift */, + B5BEBE0E2E93BE200002C9E5 /* PdfWithOcrSwitchView.xib */, + B5BEBE0F2E93BE200002C9E5 /* PdfWithoutOcrSwitchView.swift */, + B5BEBE102E93BE200002C9E5 /* PdfWithoutOcrSwitchView.xib */, + B5BEBE112E93BE200002C9E5 /* PNGImageSaveSwitchView.swift */, + B5BEBE122E93BE200002C9E5 /* PNGImageSaveSwitchView.xib */, + B5BEBE132E93BE200002C9E5 /* ScanDocumentPathView.swift */, + B5BEBE142E93BE200002C9E5 /* ScanDocumentPathView.xib */, + B5BEBE152E93BE200002C9E5 /* SetPDFPasswordSwitchView.swift */, + B5BEBE162E93BE200002C9E5 /* SetPDFPasswordSwitchView.xib */, + B5BEBE172E93BE200002C9E5 /* TextFileWithOcrSwitchView.swift */, + B5BEBE182E93BE200002C9E5 /* TextFileWithOcrSwitchView.xib */, + B52FAEBF2DA8EF84001AB1BD /* NMC Views */ = { + isa = PBXGroup; + children = ( + B52FAEAD2DA8EF84001AB1BD /* FileNameInputTextField.swift */, + B52FAEAE2DA8EF84001AB1BD /* FileNameInputTextField.xib */, + B52FAEAF2DA8EF84001AB1BD /* JPGImageSaveSwitchView.swift */, + B52FAEB02DA8EF84001AB1BD /* JPGImageSaveSwitchView.xib */, + B52FAEB12DA8EF84001AB1BD /* PasswordInputField.swift */, + B52FAEB22DA8EF84001AB1BD /* PasswordInputField.xib */, + B52FAEB32DA8EF84001AB1BD /* PdfWithOcrSwitchView.swift */, + B52FAEB42DA8EF84001AB1BD /* PdfWithOcrSwitchView.xib */, + B52FAEB52DA8EF84001AB1BD /* PdfWithoutOcrSwitchView.swift */, + B52FAEB62DA8EF84001AB1BD /* PdfWithoutOcrSwitchView.xib */, + B52FAEB72DA8EF84001AB1BD /* PNGImageSaveSwitchView.swift */, + B52FAEB82DA8EF84001AB1BD /* PNGImageSaveSwitchView.xib */, + B52FAEB92DA8EF84001AB1BD /* ScanDocumentPathView.swift */, + B52FAEBA2DA8EF84001AB1BD /* ScanDocumentPathView.xib */, + B52FAEBB2DA8EF84001AB1BD /* SetPDFPasswordSwitchView.swift */, + B52FAEBC2DA8EF84001AB1BD /* SetPDFPasswordSwitchView.xib */, + B52FAEBD2DA8EF84001AB1BD /* TextFileWithOcrSwitchView.swift */, + B52FAEBE2DA8EF84001AB1BD /* TextFileWithOcrSwitchView.xib */, + ); + path = "NMC Views"; + B5D45E6C2DA510E000773929 /* Rename file */ = { + isa = PBXGroup; + children = ( + B5D45E6A2DA510E000773929 /* NCRenameFile.storyboard */, + B5D45E6B2DA510E000773929 /* NCRenameFile.swift */, + ); + path = "Rename file"; + sourceTree = ""; + }; C0046CDB2A17B98400D87C9D /* NextcloudUITests */ = { isa = PBXGroup; children = ( @@ -2228,7 +2852,9 @@ C04E2F212A17BB4D001BAD85 /* NextcloudIntegrationTests */ = { isa = PBXGroup; children = ( - AABD0C9A2D5F73FA00F009E6 /* Placeholder.swift */, + B5BEBD582E93AE2F0002C9E5 /* BaseIntegrationXCTestCase.swift */, + B5BEBD592E93AE2F0002C9E5 /* FilesIntegrationTests.swift */, + B5BEBD5A2E93AE2F0002C9E5 /* LoginIntegrationTests.swift */, ); path = NextcloudIntegrationTests; sourceTree = ""; @@ -2236,6 +2862,7 @@ F30A962A2A27A9C800D7BCFE /* Tests */ = { isa = PBXGroup; children = ( + B5BEBD512E93AE1C0002C9E5 /* Common */, C04E2F212A17BB4D001BAD85 /* NextcloudIntegrationTests */, AA52EB442D42AC500089C348 /* NextcloudUnitTests */, C0046CDB2A17B98400D87C9D /* NextcloudUITests */, @@ -2304,6 +2931,8 @@ F3BB46502A39EC2D00461F6E /* Cells */ = { isa = PBXGroup; children = ( + B568C2B42DA7AADD0072FCB4 /* NCMoreUserCell.swift */, + B568C2B22DA7AAAE0072FCB4 /* NCMoreUserCell.xib */, F3BB464C2A39ADCC00461F6E /* NCMoreAppSuggestionsCell.xib */, F3BB46512A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift */, F3BB46532A3A1E9D00461F6E /* CCCellMore.swift */, @@ -2430,9 +3059,16 @@ F728CE741BF6322C00E69702 /* Share */ = { isa = PBXGroup; children = ( + B5BEBD1A2E93A74C0002C9E5 /* CreateLinkFooterView.swift */, + B5BEBD1B2E93A74C0002C9E5 /* NCPermissions.swift */, + B5BEBD1C2E93A74C0002C9E5 /* NCShareEmailLinkHeaderView.swift */, + B5BEBD1D2E93A74C0002C9E5 /* NoSharesFooterView.swift */, + B5BEBD182E93A5260002C9E5 /* Shareable.swift */, + B5E2E6EF2DAE6E3F00AB2EDD /* ShareDownloadLimitNetwork.swift */, + B5E2E6EB2DAE66AF00AB2EDD /* NCShareEmailFieldCell.swift */, + B5E2E6EC2DAE66AF00AB2EDD /* NCShareEmailFieldCell.xib */, AF93471327E235EB002537EE /* Advanced */, - F724377A2C10B83E00C7C68D /* NCSharePermissions.swift */, - F3F442ED2DDE292600FD701F /* NCMetadataPermissions.swift */, + F724377A2C10B83E00C7C68D /* NCPermissions.swift */, F700510022DF63AC003A3356 /* NCShare.storyboard */, F700510422DF6A89003A3356 /* NCShare.swift */, AF730AF727834B1400B7520E /* NCShare+NCCellDelegate.swift */, @@ -2451,7 +3087,7 @@ AF2D7C7D2742559100ADF566 /* NCShareUserCell.swift */, AF93471727E2361E002537EE /* NCShareHeader.xib */, AF93471527E2361E002537EE /* NCShareHeader.swift */, - AFCE353827E5DE0400FEA6C2 /* Shareable.swift */, + AFCE353827E5DE0400FEA6C2 /* NCShare+Helper.swift */, AA8E03D92D2ED83300E7E89C /* TransientShare.swift */, ); path = Share; @@ -2536,7 +3172,7 @@ F7327E3C2B73B92800A462C7 /* NCNetworking+Synchronization.swift */, F74230F22C79B57200CA1ACA /* NCNetworking+Task.swift */, F785129A2D79899E0087DDD0 /* NCNetworking+TermsOfService.swift */, - F71916102E2901E800E13E96 /* NCNetworking+Upload.swift */, + F7327E272B73A53400A462C7 /* NCNetworking+Upload.swift */, F7327E2F2B73A86700A462C7 /* NCNetworking+WebDAV.swift */, F70D8D8024A4A9BF000A5756 /* NCNetworkingProcess.swift */, F755BD9A20594AC7008C5FBB /* NCService.swift */, @@ -2558,6 +3194,12 @@ F758B41E212C516300515F55 /* Scan document */ = { isa = PBXGroup; children = ( + B5BEBE192E93BE200002C9E5 /* NMC Views */, + B5BEBE052E93BE0C0002C9E5 /* NCCreateFormUploadScanDocument.swift */, + B5E2E6D52DAE571200AB2EDD /* PasswordInputField.swift */, + B5E2E6D62DAE571200AB2EDD /* PasswordInputField.xib */, + B52FAEBF2DA8EF84001AB1BD /* NMC Views */, + B52FAEAB2DA8EF2C001AB1BD /* NCCreateFormUploadScanDocument.swift */, F758B457212C564000515F55 /* NCScan.storyboard */, F758B45D212C569C00515F55 /* NCScanCell.swift */, F758B45F212C56A400515F55 /* NCScan.swift */, @@ -2588,7 +3230,6 @@ F751247B2C42919C00E63DB8 /* NCPhotoCell.xib */, F75D901E2D2BE12E003E740B /* NCRecommendationsCell.xib */, F75D90202D2BE26C003E740B /* NCRecommendationsCell.swift */, - F36C514D2E89393C0097E5F7 /* UIView+BlurVibrancy.swift */, ); path = Cell; sourceTree = ""; @@ -2596,6 +3237,9 @@ F7603298252F0E550015A421 /* Collection Common */ = { isa = PBXGroup; children = ( + B5BEBDC82E93AFF10002C9E5 /* NCSelectableNavigationView.swift */, + B5C9801D2DACEB5A0041B146 /* NCCollectionViewCommon+SwipeCollectionViewCellDelegate.swift */, + B52FAED42DA8F616001AB1BD /* NCSelectableNavigationView.swift */, F75FE06B2BB01D0D00A0EFEF /* Cell */, F78ACD50219046AC0088454D /* Section Header Footer */, F70D7C3525FFBF81002B9E34 /* NCCollectionViewCommon.swift */, @@ -2607,7 +3251,7 @@ F799DF872C4B83CC003410B5 /* NCCollectionViewCommon+EasyTipView.swift */, F799DF8A2C4B84EB003410B5 /* NCCollectionViewCommon+EndToEndInitialize.swift */, F778231D2C42C07C001BB94F /* NCCollectionViewCommon+MediaLayout.swift */, - F36E64F62B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBarDelegate.swift */, + F36E64F62B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBar.swift */, F7D4BF002CA1831600A5E746 /* NCCollectionViewCommonPinchGesture.swift */, F38F71242B6BBDC300473CDC /* NCCollectionViewCommonSelectTabBar.swift */, F7C1EEA425053A9C00866ACC /* NCCollectionViewDataSource.swift */, @@ -2649,6 +3293,29 @@ F76882042C0DD1E7001CF441 /* Settings */ = { isa = PBXGroup; children = ( + B52FAEA62DA8EE99001AB1BD /* CCManageAutoUpload.h */, + B52FAEA72DA8EE99001AB1BD /* CCManageAutoUpload.m */, + B52FAEA32DA8EE60001AB1BD /* NCManageAutoUploadFileName.swift */, + B529E40C2E8D1F8B006D9131 /* NCManageE2EE.swift */, + B568C2C62DA7CD930072FCB4 /* CCAdvanced.h */, + B568C2C72DA7CD930072FCB4 /* NCSettings.h */, + B568C2C22DA7CCEA0072FCB4 /* NCSettings.m */, + B568C2C32DA7CCEA0072FCB4 /* OpenSourceSoftwareViewController.swift */, + B568C2BA2DA7CCDB0072FCB4 /* HelpViewController.swift */, + B568C2BB2DA7CCDB0072FCB4 /* ImprintViewController.swift */, + B568C2BC2DA7CCDB0072FCB4 /* MagentaCloudVersionView.swift */, + B568C2BD2DA7CCDB0072FCB4 /* MagentaCloudVersionView.xib */, + B568C2B82DA7CCC10072FCB4 /* CCAdvanced.m */, + B54315372DA669C700981E7E /* AnalysisDataCollectionSwitch.swift */, + B54315382DA669C700981E7E /* AnalysisDataCollectionSwitch.xib */, + B54315392DA669C700981E7E /* InitialPrivacySettingsViewController.swift */, + B543153A2DA669C700981E7E /* NCSettings.storyboard */, + B543153B2DA669C700981E7E /* PrivacyPolicyViewController.swift */, + B543153C2DA669C700981E7E /* PrivacySettingsViewController.swift */, + B543153D2DA669C700981E7E /* RequiredDataCollectionSwitch.swift */, + B543153E2DA669C700981E7E /* RequiredDataCollectionSwitch.xib */, + B543153F2DA669C700981E7E /* SaveSettingsCustomButtonCell.swift */, + B54315402DA669C700981E7E /* SaveSettingsCustomButtonCell.xib */, F768820B2C0DD1E7001CF441 /* Settings */, F76882162C0DD1E7001CF441 /* AutoUpload */, F389C9F32CEE381E00049762 /* SelectAlbum */, @@ -2656,7 +3323,7 @@ F76882052C0DD1E7001CF441 /* Advanced */, F768821F2C0DD1E7001CF441 /* Helpers */, F76882142C0DD1E7001CF441 /* Acknowledgements.rtf */, - F76882132C0DD1E7001CF441 /* NCPreferences.swift */, + F76882132C0DD1E7001CF441 /* NCKeychain.swift */, F76882152C0DD1E7001CF441 /* NCSettingsBundleHelper.swift */, F768820D2C0DD1E7001CF441 /* E2EE */, ); @@ -2793,7 +3460,6 @@ children = ( F7725A5F251F33BB00D125E0 /* NCFiles.storyboard */, F7725A5E251F33BB00D125E0 /* NCFiles.swift */, - F753DBDE2E5D99B700A1AF91 /* NCFiles+SyncMetadata.swift */, F73EFF9A2DB11EB900FD434C /* NCFiles+UIScrollViewDelegate.swift */, F722133A2D40EF8C002F7438 /* NCFilesNavigationController.swift */, ); @@ -2825,6 +3491,8 @@ F78ACD50219046AC0088454D /* Section Header Footer */ = { isa = PBXGroup; children = ( + B5BEBDCA2E93B0210002C9E5 /* NCSectionHeaderMenu.swift */, + B5BEBDCB2E93B0210002C9E5 /* NCSectionHeaderMenu.xib */, F78ACD51219046DC0088454D /* NCSectionFirstHeader.swift */, F7B398412A6A91D5007538D6 /* NCSectionFirstHeader.xib */, F7CBC1222BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.swift */, @@ -2854,11 +3522,11 @@ F79018B1240962C7007C9B6D /* NCViewerMedia */ = { isa = PBXGroup; children = ( - F70753EA2542A99800972D44 /* NCViewerMediaPage.swift */, F718C24D254D507B00C5C256 /* NCViewerMediaDetailView.swift */, + F70753F62542A9C000972D44 /* NCViewerMediaPage.storyboard */, + F70753EA2542A99800972D44 /* NCViewerMediaPage.swift */, F70753F02542A9A200972D44 /* NCViewerMedia.swift */, F310B1EE2BA862F1001C42F5 /* NCViewerMedia+VisionKit.swift */, - F70753F62542A9C000972D44 /* NCViewerMediaPage.storyboard */, F79EDA9E26B004980007D134 /* NCPlayer */, ); path = NCViewerMedia; @@ -2933,7 +3601,6 @@ F7EE66AC2A20B226009AE765 /* UILabel+Extension.swift */, F77BB7492899857B0090FC19 /* UINavigationController+Extension.swift */, F77BB747289985270090FC19 /* UITabBarController+Extension.swift */, - F743C89D2E5B2595000173A9 /* UIScene+Extension.swift */, F77C3F5A2D9BF8B500F3C471 /* UITabBar+Extension.swift */, AFCE353227E4ED1900FEA6C2 /* UIToolbar+Extension.swift */, F7E41315294A19B300839300 /* UIView+Extension.swift */, @@ -2983,6 +3650,15 @@ path = BrowserWeb; sourceTree = ""; }; + F7AEEAA92C11DC0600011412 /* Account Settings */ = { + isa = PBXGroup; + children = ( + F7AEEAA52C11DBAF00011412 /* NCAccountSettingsView.swift */, + F7AEEAA72C11DBFD00011412 /* NCAccountSettingsModel.swift */, + ); + path = "Account Settings"; + sourceTree = ""; + }; F7BAAD951ED5A63D00B7EAD4 /* Data */ = { isa = PBXGroup; children = ( @@ -3002,7 +3678,6 @@ F73EF7BE2B02250B0087E6E9 /* NCManageDatabase+GPS.swift */, F757CC8129E7F88B00F31428 /* NCManageDatabase+Groupfolders.swift */, F7BF9D812934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift */, - F77E8C1E2E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift */, F7864ACB2A78FE73004870E0 /* NCManageDatabase+LocalFile.swift */, AF4BF61827562A4B0081CEEF /* NCManageDatabase+Metadata.swift */, F7B769A72B7A0B2000C1AAEB /* NCManageDatabase+Metadata+Session.swift */, @@ -3021,6 +3696,9 @@ F7BFFA621A24D7300044ED85 /* Login */ = { isa = PBXGroup; children = ( + B5BEBDC62E93AF7E0002C9E5 /* NCLoginWeb.swift */, + B543152F2DA647A400981E7E /* NCLoginWeb.swift */, + F3CA33802D106FF900672333 /* Poll */, F702F2F025EE5CDA008F8E80 /* NCLogin.storyboard */, F702F2F625EE5CEC008F8E80 /* NCLogin.swift */, F745B252222D88AE00346520 /* NCLoginQRCode.swift */, @@ -3038,15 +3716,11 @@ F702F2FC25EE5D2C008F8E80 /* NYMnemonic */, F7D4BF2B2CA2E8D800A5E746 /* TOPasscodeViewController */, F76D364528A4F8BF00214537 /* NCActivityIndicator.swift */, - F752BA042E58C05200616A26 /* Maintenance.swift */, - F7F562FF2E15761500631A11 /* MigrationMultiDomains.swift */, F733598025C1C188002ABA72 /* NCAskAuthorization.swift */, F77C97382953131000FDDD09 /* NCCameraRoll.swift */, F765608E23BF813500765969 /* NCContentPresenter.swift */, F70968A324212C4E00ED60E5 /* NCLivePhoto.swift */, - F7DB7DE82E8173160017AF90 /* NCStorageEstimator.swift */, F7386E452DA90E02009A00F6 /* NCAppVersionManager.swift */, - F7A560412AE1593700BE8FD6 /* NCOperationSaveLivePhoto.swift */, F702F30725EE5D47008F8E80 /* NCPopupViewController.swift */, F707C26421A2DC5200F6181E /* NCStoreReview.swift */, F70BFC7320E0FA7C00C67599 /* NCUtility.swift */, @@ -3082,6 +3756,14 @@ F7C1CDD91E6DFC6F005D92BE /* Brand */ = { isa = PBXGroup; children = ( + B5BEBD272E93AD540002C9E5 /* File_Provider_Extension.entitlements */, + B5BEBD282E93AD540002C9E5 /* File_Provider_Extension.plist */, + B5BEBD292E93AD540002C9E5 /* iOSClient.entitlements */, + B5BEBD2A2E93AD540002C9E5 /* iOSClient.plist */, + B5BEBD2B2E93AD540002C9E5 /* Notification_Service_Extension.entitlements */, + B5BEBD2C2E93AD540002C9E5 /* Notification_Service_Extension.plist */, + B5BEBD2D2E93AD540002C9E5 /* Share.entitlements */, + B5BEBD2E2E93AD540002C9E5 /* Share.plist */, F761856529E98543006EB3B0 /* Intro */, F700222B1EC479840080073F /* Custom.xcassets */, F7362A1E220C853A005101B5 /* LaunchScreen.storyboard */, @@ -3109,6 +3791,15 @@ path = E2EE; sourceTree = ""; }; + F7C5259A1E3B441D00FFE02C /* Notification */ = { + isa = PBXGroup; + children = ( + F73B42292476764F00A30FD3 /* NCNotification.storyboard */, + F73B422A2476764F00A30FD3 /* NCNotification.swift */, + ); + name = Notification; + sourceTree = ""; + }; F7C9739328F17131002C43E2 /* WidgetDashboardIntentHandler */ = { isa = PBXGroup; children = ( @@ -3117,6 +3808,17 @@ path = WidgetDashboardIntentHandler; sourceTree = ""; }; + F7CA213725F1372B00826ABB /* Account Request */ = { + isa = PBXGroup; + children = ( + F7CA212C25F1333200826ABB /* NCAccountRequest.storyboard */, + F7CA212B25F1333200826ABB /* NCAccountRequest.swift */, + F7A60F85292D215000FCE1F2 /* NCShareAccounts.storyboard */, + F7A60F84292D215000FCE1F2 /* NCShareAccounts.swift */, + ); + path = "Account Request"; + sourceTree = ""; + }; F7CADB3D23CCDDA1000EEC78 /* RichWorkspace */ = { isa = PBXGroup; children = ( @@ -3232,6 +3934,21 @@ F7DFB7E9219C5A0500680748 /* Create cloud */ = { isa = PBXGroup; children = ( + B5BEBDD02E93B2450002C9E5 /* NCCreateFormUploadDocuments.storyboard */, + B5BEBDD12E93B2450002C9E5 /* NCCreateFormUploadDocuments.swift */, + B5BEBDD22E93B2450002C9E5 /* NCCreateFormUploadVoiceNote.storyboard */, + B5BEBDD32E93B2450002C9E5 /* NCCreateFormUploadVoiceNote.swift */, + B5BEBDD42E93B2450002C9E5 /* TextTableViewCell.swift */, + B5BEBDD52E93B2450002C9E5 /* TextTableViewCell.xib */, + B52FAE912DA8DCB2001AB1BD /* NCCreateFormUploadDocuments.storyboard */, + B52FAE922DA8DCB2001AB1BD /* NCCreateFormUploadDocuments.swift */, + B529E4062E8D1C3E006D9131 /* NCUploadAssets.swift */, + B543154F2DA6929700981E7E /* FolderPathCustomCell.swift */, + B54315502DA6929700981E7E /* FolderPathCustomCell.xib */, + B54315512DA6929700981E7E /* NCCreateFormUploadVoiceNote.storyboard */, + B54315522DA6929700981E7E /* NCCreateFormUploadVoiceNote.swift */, + B54315532DA6929700981E7E /* TextTableViewCell.swift */, + B54315542DA6929700981E7E /* TextTableViewCell.xib */, F7FA7FFD2C0F4F3B0072FC60 /* Upload Assets */, F7A509242C26BD5D00326106 /* NCCreateDocument.swift */, F704B5E22430AA6F00632F5F /* NCCreateFormUploadConflict.storyboard */, @@ -3256,6 +3973,8 @@ F7EC9CB921185F2000F1C5CE /* Media */ = { isa = PBXGroup; children = ( + B5BEBDE22E93BD6F0002C9E5 /* NCMediaCommandView.xib */, + B5C980172DACD51C0041B146 /* NCMediaCommandView.xib */, F720B5B72507B9A5008C94E5 /* Cell */, F7501C302212E57400FB1415 /* NCMedia.storyboard */, F7501C312212E57400FB1415 /* NCMedia.swift */, @@ -3267,7 +3986,6 @@ F7BD0A032C4689E9003A4A6D /* NCMedia+MediaLayout.swift */, F7E2B64E2DDCC5C30075B4D0 /* NCMedia+TransferDelegate.swift */, F78B87E62B62527100C65ADC /* NCMediaDataSource.swift */, - F79699E62E689F68000EC82A /* NCMediaNavigationController.swift */, F7D60CAE2C941ACB008FBFDD /* NCMediaPinchGesture.swift */, F78B87E82B62550800C65ADC /* NCMediaDownloadThumbnail.swift */, F755CB3F2B8CB13C00CE27E9 /* NCMediaLayout.swift */, @@ -3276,15 +3994,6 @@ path = Media; sourceTree = ""; }; - F7EF2AEA2E43157B0081B2C9 /* Notification */ = { - isa = PBXGroup; - children = ( - F7EF2AE82E43157B0081B2C9 /* NCNotification.storyboard */, - F7EF2AE92E43157B0081B2C9 /* NCNotification.swift */, - ); - path = Notification; - sourceTree = ""; - }; F7EFC0CB256BF89300461AAD /* UserStatus */ = { isa = PBXGroup; children = ( @@ -3294,13 +4003,6 @@ path = UserStatus; sourceTree = ""; }; - F7F1FBA62E27D13700C79E20 /* Frameworks */ = { - isa = PBXGroup; - children = ( - ); - name = Frameworks; - sourceTree = ""; - }; F7F4F0FB27ECDBDA008676F9 /* Font */ = { isa = PBXGroup; children = ( @@ -3349,18 +4051,27 @@ F70716E32987F81500E72C1D /* File Provider Extension UI.appex */, C04E2F202A17BB4D001BAD85 /* NextcloudIntegrationTests.xctest */, C0046CDA2A17B98400D87C9D /* NextcloudUITests.xctest */, - F7F1FBA62E27D13700C79E20 /* Frameworks */, ); sourceTree = ""; }; F7F67BAA1A24D27800EE80DA /* iOSClient */ = { isa = PBXGroup; children = ( + B5BEBDE82E93BDB40002C9E5 /* NMC Custom Views */, + B5BEBD9B2E93AF010002C9E5 /* AppUtility.swift */, + B5BEBD9E2E93AF010002C9E5 /* EmptyView */, + B5BEBDA22E93AF010002C9E5 /* Helper */, + B5BEBD932E93AED80002C9E5 /* AppUpdate */, + B5BEBD7C2E93AEA30002C9E5 /* Analytics */, AA517BB42D66149900F8D37C /* .tx */, + B52FAE9B2DA8DED9001AB1BD /* NMC Custom Views */, + B54315332DA64D6500981E7E /* AppUtility.swift */, + B5D45E722DA5172900773929 /* AppUpdate */, F702F2CC25EE5B4F008F8E80 /* AppDelegate.swift */, F794E13E2BBC0F70003693D7 /* SceneDelegate.swift */, F7CF067A2E0FF38F0063AD04 /* NCAppStateManager.swift */, F77DD6A72C5CC093009448FB /* NCSession.swift */, + F7A8FD512C5E2557006C9CF8 /* NCAccount.swift */, F76B649B2ADFFAED00014640 /* NCImageCache.swift */, F702F2CE25EE5B5C008F8E80 /* NCGlobal.swift */, F7E402282BA85D1D007E5609 /* PrivacyInfo.xcprivacy */, @@ -3369,7 +4080,8 @@ F7F67BB81A24D27800EE80DA /* Images.xcassets */, F769CA1B2966EF4F00039397 /* GUI */, F70211F31BAC56E9003FC03E /* Main */, - F7FDFF5A2E437E55000D7688 /* Account */, + F7CA213725F1372B00826ABB /* Account Request */, + F7AEEAA92C11DC0600011412 /* Account Settings */, F7A321621E9E37960069AD1B /* Activity */, F76687042B7D067400779E3F /* AudioRecorder */, F3A0478E2BD2668800658E7B /* Assistant */, @@ -3386,10 +4098,11 @@ 371B5A2F23D0B04B00FAFAE9 /* Menu */, F7CB68942541670D0050EC94 /* More */, F74D3DB81BAC1941000BAE4B /* Networking */, - F7EF2AEA2E43157B0081B2C9 /* Notification */, + F7C5259A1E3B441D00FFE02C /* Notification */, F7381ED9218218A4000B1560 /* Offline */, F713418B2597513800768D21 /* PushNotification */, F765F72E25237E3F00391DBE /* Recent */, + B5D45E6C2DA510E000773929 /* Rename file */, F7CADB3D23CCDDA1000EEC78 /* RichWorkspace */, F76882042C0DD1E7001CF441 /* Settings */, F758B41E212C516300515F55 /* Scan document */, @@ -3436,36 +4149,6 @@ name = Products; sourceTree = ""; }; - F7FDFF552E437E55000D7688 /* Account Request */ = { - isa = PBXGroup; - children = ( - F7FDFF512E437E55000D7688 /* NCAccountRequest.storyboard */, - F7FDFF522E437E55000D7688 /* NCAccountRequest.swift */, - F7FDFF532E437E55000D7688 /* NCShareAccounts.storyboard */, - F7FDFF542E437E55000D7688 /* NCShareAccounts.swift */, - ); - path = "Account Request"; - sourceTree = ""; - }; - F7FDFF582E437E55000D7688 /* Account Settings */ = { - isa = PBXGroup; - children = ( - F7FDFF562E437E55000D7688 /* NCAccountSettingsModel.swift */, - F7FDFF572E437E55000D7688 /* NCAccountSettingsView.swift */, - ); - path = "Account Settings"; - sourceTree = ""; - }; - F7FDFF5A2E437E55000D7688 /* Account */ = { - isa = PBXGroup; - children = ( - F7FDFF552E437E55000D7688 /* Account Request */, - F7FDFF582E437E55000D7688 /* Account Settings */, - F7FDFF592E437E55000D7688 /* NCAccount.swift */, - ); - path = Account; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -3488,8 +4171,6 @@ F72AD71028C24BBB006CB92D /* NextcloudKit */, F760DE0E2AE66EE60027D78A /* KeychainAccess */, F33EE6EC2BF4C03800CA1A51 /* NIOSSL */, - F7F1FBAD2E27D3A400C79E20 /* SwiftEntryKit */, - F7F1FBAF2E27D3A800C79E20 /* Queuer */, ); productName = "Notification Service Extension"; productReference = 2C33C47F23E2C475005F963B /* Notification Service Extension.appex */; @@ -3606,7 +4287,6 @@ F7490E8A29882CE4009DCE94 /* NextcloudKit */, F760DE0C2AE66EDF0027D78A /* KeychainAccess */, F33EE6EA2BF4C03200CA1A51 /* NIOSSL */, - F7F1FBAB2E27D20400C79E20 /* Queuer */, ); productName = "File Provider Extension UI"; productReference = F70716E32987F81500E72C1D /* File Provider Extension UI.appex */; @@ -3779,8 +4459,6 @@ F7A8D72728F17728008BBE1C /* RealmSwift */, F760DE062AE66EC70027D78A /* KeychainAccess */, F33EE6E42BF4C02000CA1A51 /* NIOSSL */, - F7F1FBA72E27D13700C79E20 /* Queuer */, - F7F1FBA92E27D14000C79E20 /* SwiftEntryKit */, ); productName = WidgetDashboardIntentHandler; productReference = F7C9739028F17131002C43E2 /* WidgetDashboardIntentHandler.appex */; @@ -3794,7 +4472,7 @@ attributes = { BuildIndependentTargetsInParallel = YES; LastSwiftUpdateCheck = 1430; - LastUpgradeCheck = 1630; + LastUpgradeCheck = 1620; ORGANIZATIONNAME = "Marino Faggiana"; TargetAttributes = { 2C33C47E23E2C475005F963B = { @@ -3962,6 +4640,13 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + B5BEBDBB2E93AF010002C9E5 /* NCEmptyView.xib in Resources */, + B5BEBDF72E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib in Resources */, + B5BEBDF82E93BDB40002C9E5 /* FolderPathCustomCell.xib in Resources */, + B5BEBD3F2E93AD540002C9E5 /* iOSClient.plist in Resources */, + B5BEBD402E93AD540002C9E5 /* Share.plist in Resources */, + B5BEBD412E93AD540002C9E5 /* Notification_Service_Extension.plist in Resources */, + B5BEBD422E93AD540002C9E5 /* File_Provider_Extension.plist in Resources */, F7E4022F2BA85D1D007E5609 /* PrivacyInfo.xcprivacy in Resources */, F746EC53273906C50052598D /* NCViewCertificateDetails.storyboard in Resources */, ); @@ -3971,6 +4656,10 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + B5BEBD472E93AD540002C9E5 /* iOSClient.plist in Resources */, + B5BEBD482E93AD540002C9E5 /* Share.plist in Resources */, + B5BEBD492E93AD540002C9E5 /* Notification_Service_Extension.plist in Resources */, + B5BEBD4A2E93AD540002C9E5 /* File_Provider_Extension.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3993,8 +4682,15 @@ buildActionMask = 2147483647; files = ( F7490E8D29882F5B009DCE94 /* Custom.xcassets in Resources */, + B5BEBDEF2E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib in Resources */, + B5BEBDF02E93BDB40002C9E5 /* FolderPathCustomCell.xib in Resources */, + B5BEBDB12E93AF010002C9E5 /* NCEmptyView.xib in Resources */, F7490E8E2988334A009DCE94 /* Localizable.strings in Resources */, F7E4022E2BA85D1D007E5609 /* PrivacyInfo.xcprivacy in Resources */, + B5BEBD432E93AD540002C9E5 /* iOSClient.plist in Resources */, + B5BEBD442E93AD540002C9E5 /* Share.plist in Resources */, + B5BEBD452E93AD540002C9E5 /* Notification_Service_Extension.plist in Resources */, + B5BEBD462E93AD540002C9E5 /* File_Provider_Extension.plist in Resources */, AA517B812D660EFE00F8D37C /* Localizable.stringsdict in Resources */, F722F0112CFF569500065FB5 /* MainInterface.storyboard in Resources */, ); @@ -4004,20 +4700,32 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + B543155A2DA6929700981E7E /* NCCreateFormUploadVoiceNote.storyboard in Resources */, F714803B262EBE3900693E51 /* MainInterface.storyboard in Resources */, F7148054262ED51000693E51 /* NCListCell.xib in Resources */, + F7D57C8626317BDA00DE301D /* NCAccountRequest.storyboard in Resources */, F7E4022C2BA85D1D007E5609 /* PrivacyInfo.xcprivacy in Resources */, AF22B209277B4E4C00DAB0CC /* NCCreateFormUploadConflictCell.xib in Resources */, F7CBC1242BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.xib in Resources */, F7B398432A6A91D5007538D6 /* NCSectionFirstHeader.xib in Resources */, AF22B207277B4E4C00DAB0CC /* NCCreateFormUploadConflict.storyboard in Resources */, AA517B822D660EFE00F8D37C /* Localizable.stringsdict in Resources */, + B5BEBD2F2E93AD540002C9E5 /* iOSClient.plist in Resources */, + B5BEBDD92E93B2450002C9E5 /* TextTableViewCell.xib in Resources */, + B5BEBDDA2E93B2450002C9E5 /* NCCreateFormUploadDocuments.storyboard in Resources */, + B5BEBDDB2E93B2450002C9E5 /* NCCreateFormUploadVoiceNote.storyboard in Resources */, + B5BEBD302E93AD540002C9E5 /* Share.plist in Resources */, + B5BEBDB62E93AF010002C9E5 /* NCEmptyView.xib in Resources */, + B5BEBD312E93AD540002C9E5 /* Notification_Service_Extension.plist in Resources */, + B5BEBD322E93AD540002C9E5 /* File_Provider_Extension.plist in Resources */, + B5BEBDCD2E93B0210002C9E5 /* NCSectionHeaderMenu.xib in Resources */, F7145A231D12E3B700CAFEEC /* Localizable.strings in Resources */, F746EC51273906C40052598D /* NCViewCertificateDetails.storyboard in Resources */, F76C26A62850D3A500E42BDF /* Images.xcassets in Resources */, F714805E262ED52900693E51 /* NCSectionFooter.xib in Resources */, + B5BEBDFB2E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib in Resources */, + B5BEBDFC2E93BDB40002C9E5 /* FolderPathCustomCell.xib in Resources */, F700222D1EC479840080073F /* Custom.xcassets in Resources */, - F7FDFF702E437E55000D7688 /* NCAccountRequest.storyboard in Resources */, F79ED0F22D2FCA6A00A389D9 /* NCRecommendationsCell.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -4027,8 +4735,15 @@ buildActionMask = 2147483647; files = ( F7C7B25128B8B0C400E7115D /* Images.xcassets in Resources */, + B5BEBDFD2E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib in Resources */, + B5BEBDFE2E93BDB40002C9E5 /* FolderPathCustomCell.xib in Resources */, + B5BEBDA82E93AF010002C9E5 /* NCEmptyView.xib in Resources */, F7C7B25028B8AD4500E7115D /* Localizable.strings in Resources */, F7E4022A2BA85D1D007E5609 /* PrivacyInfo.xcprivacy in Resources */, + B5BEBD372E93AD540002C9E5 /* iOSClient.plist in Resources */, + B5BEBD382E93AD540002C9E5 /* Share.plist in Resources */, + B5BEBD392E93AD540002C9E5 /* Notification_Service_Extension.plist in Resources */, + B5BEBD3A2E93AD540002C9E5 /* File_Provider_Extension.plist in Resources */, AA517B832D660EFE00F8D37C /* Localizable.stringsdict in Resources */, F7346E2328B0FEBA006CE2D2 /* Assets.xcassets in Resources */, ); @@ -4038,6 +4753,13 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + B5BEBDC12E93AF010002C9E5 /* NCEmptyView.xib in Resources */, + B5BEBE012E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib in Resources */, + B5BEBE022E93BDB40002C9E5 /* FolderPathCustomCell.xib in Resources */, + B5BEBD4B2E93AD540002C9E5 /* iOSClient.plist in Resources */, + B5BEBD4C2E93AD540002C9E5 /* Share.plist in Resources */, + B5BEBD4D2E93AD540002C9E5 /* Notification_Service_Extension.plist in Resources */, + B5BEBD4E2E93AD540002C9E5 /* File_Provider_Extension.plist in Resources */, F7E4022D2BA85D1D007E5609 /* PrivacyInfo.xcprivacy in Resources */, F746EC52273906C40052598D /* NCViewCertificateDetails.storyboard in Resources */, ); @@ -4051,6 +4773,7 @@ F77444F622281649000D5EB0 /* NCMediaCell.xib in Resources */, F78ACD4421903CF20088454D /* NCListCell.xib in Resources */, F3BB464D2A39ADCC00461F6E /* NCMoreAppSuggestionsCell.xib in Resources */, + B5BEBDE32E93BD6F0002C9E5 /* NCMediaCommandView.xib in Resources */, F7F4F10727ECDBDB008676F9 /* Inconsolata-Black.ttf in Resources */, F761856D29E98543006EB3B0 /* NCIntroCollectionViewCell.xib in Resources */, F78ACD4621903D010088454D /* NCGridCell.xib in Resources */, @@ -4061,62 +4784,113 @@ F76D3CF52428D0C1005DFA87 /* NCViewerPDF.storyboard in Resources */, F700222C1EC479840080073F /* Custom.xcassets in Resources */, F702F2F125EE5CDB008F8E80 /* NCLogin.storyboard in Resources */, + B5BEBDF32E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib in Resources */, + B5BEBDF42E93BDB40002C9E5 /* FolderPathCustomCell.xib in Resources */, F723985C253C95CE00257F49 /* NCViewerRichdocument.storyboard in Resources */, F758B45A212C564000515F55 /* NCScan.storyboard in Resources */, F765F73225237E3F00391DBE /* NCRecent.storyboard in Resources */, F78F74342163757000C2ADAD /* NCTrash.storyboard in Resources */, + B5E2E6E72DAE59F000AB2EDD /* NCShareHeaderCustomCell.xib in Resources */, + B5E2E6E82DAE59F000AB2EDD /* NCShareTextInputCell.xib in Resources */, F702F30225EE5D2C008F8E80 /* english.txt in Resources */, F757CC8C29E82D0500F31428 /* NCGroupfolders.storyboard in Resources */, F79A65C32191D90F00FF6DCC /* NCSelect.storyboard in Resources */, + B5E2E6DD2DAE573B00AB2EDD /* NCFilePermissionEditCell.xib in Resources */, + B5E2E6ED2DAE66AF00AB2EDD /* NCShareEmailFieldCell.xib in Resources */, + B5E2E6DE2DAE573B00AB2EDD /* NCFilePermissionCell.xib in Resources */, F7226EDC1EE4089300EBECB1 /* Main.storyboard in Resources */, AF56C1DC2784856200D8BAE2 /* NCActivityCommentView.xib in Resources */, F7F4F10B27ECDBDB008676F9 /* Inconsolata-Light.ttf in Resources */, - F7EF2AEC2E43157B0081B2C9 /* NCNotification.storyboard in Resources */, F7CEE6002BA9A5C9003EFD89 /* NCTrashGridCell.xib in Resources */, 3704EB2A23D5A58400455C5B /* NCMenu.storyboard in Resources */, AF93471C27E2361E002537EE /* NCShareHeader.xib in Resources */, F75D901F2D2BE12E003E740B /* NCRecommendationsCell.xib in Resources */, + B54315472DA669C700981E7E /* AnalysisDataCollectionSwitch.xib in Resources */, + B54315482DA669C700981E7E /* NCSettings.storyboard in Resources */, + B54315492DA669C700981E7E /* SaveSettingsCustomButtonCell.xib in Resources */, + B543154A2DA669C700981E7E /* RequiredDataCollectionSwitch.xib in Resources */, F76032A0252F0F8E0015A421 /* NCTransferCell.xib in Resources */, F7F4F10527ECDBDB008676F9 /* Inconsolata-SemiBold.ttf in Resources */, F7A48415297028FC00BD1B49 /* Nextcloud Hub.png in Resources */, F74C0437253F1CDC009762AB /* NCShares.storyboard in Resources */, F7F4F10C27ECDBDB008676F9 /* Inconsolata-Regular.ttf in Resources */, + B568C2BE2DA7CCDB0072FCB4 /* MagentaCloudVersionView.xib in Resources */, F7B8B83025681C3400967775 /* GoogleService-Info.plist in Resources */, + B5C980182DACD51C0041B146 /* NCMediaCommandView.xib in Resources */, F7381EE5218218C9000B1560 /* NCOffline.storyboard in Resources */, F768822D2C0DD1E7001CF441 /* Acknowledgements.rtf in Resources */, F7E0CDCF265CE8610044854E /* NCUserStatus.storyboard in Resources */, F76D3CF32428B94E005DFA87 /* NCViewerPDFSearchCell.xib in Resources */, + B5BEBDCF2E93B0210002C9E5 /* NCSectionHeaderMenu.xib in Resources */, + B568C2B32DA7AAAE0072FCB4 /* NCMoreUserCell.xib in Resources */, + F7CA212E25F1333300826ABB /* NCAccountRequest.storyboard in Resources */, + F7CA212E25F1333300826ABB /* NCAccountRequest.storyboard in Resources */, + B5D45E6D2DA510E000773929 /* NCRenameFile.storyboard in Resources */, F717402D24F699A5000C87D5 /* NCFavorite.storyboard in Resources */, F723B3DD22FC6D1D00301EFE /* NCShareCommentsCell.xib in Resources */, F78ACD4B21903F850088454D /* NCTrashListCell.xib in Resources */, + B52FAE9C2DA8DED9001AB1BD /* NCCreateDocumentCustomTextField.xib in Resources */, + B52FAE9D2DA8DED9001AB1BD /* FolderPathCustomCell.xib in Resources */, AF93471927E2361E002537EE /* NCShareAdvancePermissionFooter.xib in Resources */, + B5E2E6E22DAE59CD00AB2EDD /* NCShareAdvancePermissionHeader.xib in Resources */, F7725A61251F33BB00D125E0 /* NCFiles.storyboard in Resources */, F7CBC1232BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.xib in Resources */, F700510122DF63AC003A3356 /* NCShare.storyboard in Resources */, + B5E2E6D72DAE571200AB2EDD /* PasswordInputField.xib in Resources */, F787704F22E7019900F287A9 /* NCShareLinkCell.xib in Resources */, F70753F72542A9C000972D44 /* NCViewerMediaPage.storyboard in Resources */, + B52FAEC92DA8EF84001AB1BD /* PdfWithOcrSwitchView.xib in Resources */, + B52FAECA2DA8EF84001AB1BD /* PasswordInputField.xib in Resources */, + B52FAECB2DA8EF84001AB1BD /* ScanDocumentPathView.xib in Resources */, + B52FAECC2DA8EF84001AB1BD /* SetPDFPasswordSwitchView.xib in Resources */, + B52FAECD2DA8EF84001AB1BD /* PNGImageSaveSwitchView.xib in Resources */, + B52FAECE2DA8EF84001AB1BD /* FileNameInputTextField.xib in Resources */, + B52FAECF2DA8EF84001AB1BD /* TextFileWithOcrSwitchView.xib in Resources */, + B52FAED02DA8EF84001AB1BD /* JPGImageSaveSwitchView.xib in Resources */, + B52FAED12DA8EF84001AB1BD /* PdfWithoutOcrSwitchView.xib in Resources */, F7F4F10627ECDBDB008676F9 /* Inconsolata-Medium.ttf in Resources */, F7AC934A296193050002BC0F /* Reasons to use Nextcloud.pdf in Resources */, + B543155E2DA6929700981E7E /* TextTableViewCell.xib in Resources */, + B543155F2DA6929700981E7E /* FolderPathCustomCell.xib in Resources */, + B54315602DA6929700981E7E /* NCCreateFormUploadVoiceNote.storyboard in Resources */, + F7A60F87292D215000FCE1F2 /* NCShareAccounts.storyboard in Resources */, F761856A29E98543006EB3B0 /* NCIntro.storyboard in Resources */, F719D9E0288D37A300762E33 /* NCColorPicker.storyboard in Resources */, AA517B802D660EFE00F8D37C /* Localizable.stringsdict in Resources */, + B5BEBE232E93BE200002C9E5 /* PasswordInputField.xib in Resources */, + B5BEBE242E93BE200002C9E5 /* ScanDocumentPathView.xib in Resources */, + B5BEBE252E93BE200002C9E5 /* SetPDFPasswordSwitchView.xib in Resources */, + B5BEBE262E93BE200002C9E5 /* PdfWithOcrSwitchView.xib in Resources */, + B5BEBE272E93BE200002C9E5 /* PNGImageSaveSwitchView.xib in Resources */, + B5BEBE282E93BE200002C9E5 /* FileNameInputTextField.xib in Resources */, + B5BEBE292E93BE200002C9E5 /* TextFileWithOcrSwitchView.xib in Resources */, + B5BEBE2A2E93BE200002C9E5 /* PdfWithoutOcrSwitchView.xib in Resources */, + B5BEBE2B2E93BE200002C9E5 /* JPGImageSaveSwitchView.xib in Resources */, F7F4F10A27ECDBDB008676F9 /* Inconsolata-ExtraBold.ttf in Resources */, F704B5E72430C06700632F5F /* NCCreateFormUploadConflictCell.xib in Resources */, + B5BEBDDF2E93B2450002C9E5 /* TextTableViewCell.xib in Resources */, + B5BEBDE02E93B2450002C9E5 /* NCCreateFormUploadDocuments.storyboard in Resources */, + B5BEBDE12E93B2450002C9E5 /* NCCreateFormUploadVoiceNote.storyboard in Resources */, + B5BEBDA72E93AF010002C9E5 /* NCEmptyView.xib in Resources */, F7E402292BA85D1D007E5609 /* PrivacyInfo.xcprivacy in Resources */, F7C9555321F0C4CA0024296E /* NCActivity.storyboard in Resources */, F7BC287E26663F6C004D46C5 /* NCViewCertificateDetails.storyboard in Resources */, F78ACD54219047D40088454D /* NCSectionFooter.xib in Resources */, F751247E2C42919C00E63DB8 /* NCPhotoCell.xib in Resources */, F704B5E32430AA6F00632F5F /* NCCreateFormUploadConflict.storyboard in Resources */, + B52FAE932DA8DCB2001AB1BD /* NCCreateFormUploadDocuments.storyboard 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 */, F7FF2CB12842159500EBB7A1 /* NCSectionHeader.xib in Resources */, F7D1612023CF19E30039EBBF /* NCViewerRichWorkspace.storyboard in Resources */, + B5BEBD332E93AD540002C9E5 /* iOSClient.plist in Resources */, + B5BEBD342E93AD540002C9E5 /* Share.plist in Resources */, + B5BEBD352E93AD540002C9E5 /* Notification_Service_Extension.plist in Resources */, + B5BEBD362E93AD540002C9E5 /* File_Provider_Extension.plist in Resources */, F77B0F631D118A16002130FE /* Localizable.strings in Resources */, - F7FDFF692E437E55000D7688 /* NCAccountRequest.storyboard in Resources */, - F7FDFF6A2E437E55000D7688 /* NCShareAccounts.storyboard in Resources */, F774264A22EB4D0000B23912 /* NCSearchUserDropDownCell.xib in Resources */, F7CB689A2541676B0050EC94 /* NCMore.storyboard in Resources */, F77B0F7D1D118A16002130FE /* Images.xcassets in Resources */, @@ -4135,6 +4909,13 @@ buildActionMask = 2147483647; files = ( F7E4022B2BA85D1D007E5609 /* PrivacyInfo.xcprivacy in Resources */, + B5BEBDEB2E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.xib in Resources */, + B5BEBDEC2E93BDB40002C9E5 /* FolderPathCustomCell.xib in Resources */, + B5BEBDC02E93AF010002C9E5 /* NCEmptyView.xib in Resources */, + B5BEBD3B2E93AD540002C9E5 /* iOSClient.plist in Resources */, + B5BEBD3C2E93AD540002C9E5 /* Share.plist in Resources */, + B5BEBD3D2E93AD540002C9E5 /* Notification_Service_Extension.plist in Resources */, + B5BEBD3E2E93AD540002C9E5 /* File_Provider_Extension.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4167,6 +4948,7 @@ buildActionMask = 2147483647; files = ( F73EF7BD2B0224AB0087E6E9 /* NCManageDatabase+ExternalSites.swift in Sources */, + F7CF067B2E0FF3990063AD04 /* NCAppStateManager.swift in Sources */, F71433E72C778FFB00E20B5A /* NotificationCenter+MainThread.swift in Sources */, F39170AA2CB82024006127BC /* FileAutoRenamer+Extensions.swift in Sources */, F73EF7C52B02250B0087E6E9 /* NCManageDatabase+GPS.swift in Sources */, @@ -4174,8 +4956,6 @@ F770768A263A8A2500A1BA94 /* NCUtilityFileSystem.swift in Sources */, F76D364928A4F8BF00214537 /* NCActivityIndicator.swift in Sources */, F7817CFD29801A3500FFBC65 /* Data+Extension.swift in Sources */, - F77E8C1F2E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift in Sources */, - F7DB7DED2E81731B0017AF90 /* NCStorageEstimator.swift in Sources */, F7D7A7712DCDD437003D2007 /* NCManageDatabase+AutoUpload.swift in Sources */, AF4BF62127562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */, F702F2D225EE5B5C008F8E80 /* NCGlobal.swift in Sources */, @@ -4183,18 +4963,18 @@ F72FD3BA297ED49A00075D28 /* NCManageDatabase+E2EE.swift in Sources */, F3E173C62C9B1067006D177A /* AwakeMode.swift in Sources */, F73EF7DD2B0226080087E6E9 /* NCManageDatabase+Tip.swift in Sources */, - F7F1FBA22E27CFBC00C79E20 /* NCContentPresenter.swift in Sources */, F7E98C1927E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */, 2C1D5D7623E2DE3300334ABB /* NCManageDatabase.swift in Sources */, F7864AD22A78FE73004870E0 /* NCManageDatabase+LocalFile.swift in Sources */, F314F1142A30E2DE00BC7FAB /* View+Extension.swift in Sources */, - F724377D2C10B92300C7C68D /* NCSharePermissions.swift in Sources */, + F724377D2C10B92300C7C68D /* NCPermissions.swift in Sources */, F7D68FD028CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */, F343A4C12A1E734600DDA874 /* Optional+Extension.swift in Sources */, F7245927289BB59300474787 /* ThreadSafeDictionary.swift in Sources */, 2C33C48223E2C475005F963B /* NotificationService.swift in Sources */, F73EF7A52B021FAE0087E6E9 /* NCLivePhoto.swift in Sources */, F33EE6F82BF4C9B200CA1A51 /* PKCS12.swift in Sources */, + B5BEBD952E93AED80002C9E5 /* AppUpdater.swift in Sources */, AF4BF617275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */, F7BF9D872934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */, AA8D31592D41052900FE2775 /* NCManageDatabase+DownloadLimit.swift in Sources */, @@ -4203,14 +4983,17 @@ F73EF7AD2B0223900087E6E9 /* NCManageDatabase+Comments.swift in Sources */, F7C9B9232B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */, F7386E462DA90E0F009A00F6 /* NCAppVersionManager.swift in Sources */, + B5BEBDF52E93BDB40002C9E5 /* FolderPathCustomCell.swift in Sources */, + B5BEBDF62E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift in Sources */, F33918CA2C7CD8F2002D9AA1 /* FileNameValidator+Extensions.swift in Sources */, D575039F27146F93008DC9DC /* String+Extension.swift in Sources */, F7CF06832E1127460063AD04 /* NCManageDatabase+Metadata+Create.swift in Sources */, - F7F1FB9F2E27CE7200C79E20 /* NCNetworking.swift in Sources */, F757CC8829E7F88B00F31428 /* NCManageDatabase+Groupfolders.swift in Sources */, + B5BEBD8C2E93AEA30002C9E5 /* AnalyticsService.swift in Sources */, + B5BEBD8D2E93AEA30002C9E5 /* MoEngageAnalytics.swift in Sources */, + B5BEBD8E2E93AEA30002C9E5 /* AnalyticsHelper.swift in Sources */, F79B646326CA661600838ACA /* UIControl+Extension.swift in Sources */, F7C687EF2D22BDE5004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */, - F3F442F42DDE2A7700FD701F /* NCMetadataPermissions.swift in Sources */, F77DD6AE2C5CC093009448FB /* NCSession.swift in Sources */, F78A10C429322E8A008499B8 /* NCManageDatabase+Directory.swift in Sources */, F7B769AE2B7A0B2000C1AAEB /* NCManageDatabase+Metadata+Session.swift in Sources */, @@ -4220,14 +5003,17 @@ F7817CFF29802D1A00FFBC65 /* NCPushNotificationEncryption.m in Sources */, F798F0EC2588060A000DAFFD /* UIColor+Extension.swift in Sources */, F343A4B92A1E084400DDA874 /* PHAsset+Extension.swift in Sources */, - F76882372C0DD22F001CF441 /* NCPreferences.swift in Sources */, + F76882372C0DD22F001CF441 /* NCKeychain.swift in Sources */, F73EF7E52B02266D0087E6E9 /* NCManageDatabase+Trash.swift in Sources */, - F7F563032E15762B00631A11 /* MigrationMultiDomains.swift in Sources */, F73EF7D52B0225BA0087E6E9 /* NCManageDatabase+Tag.swift in Sources */, F71F6D0D2B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */, F763D2A32A249C4500A3C901 /* NCManageDatabase+Capabilities.swift in Sources */, F749B656297B0F2400087535 /* NCManageDatabase+Avatar.swift in Sources */, F782FDC424E6933900666099 /* NCUtility.swift in Sources */, + B5BEBDB72E93AF010002C9E5 /* AppUtility.swift in Sources */, + B5BEBDB82E93AF010002C9E5 /* AdjustHelper.m in Sources */, + B5BEBDB92E93AF010002C9E5 /* TealiumHelper.swift in Sources */, + B5BEBDBA2E93AF010002C9E5 /* NCEmptyDataSet.swift in Sources */, F74B6D9B2A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -4237,9 +5023,30 @@ buildActionMask = 2147483647; files = ( AA52EB472D42AC9E0089C348 /* Placeholder.swift in Sources */, + B5BEBD542E93AE1C0002C9E5 /* TestConstants.swift in Sources */, + B5BEBD552E93AE1C0002C9E5 /* BaseXCTestCase.swift in Sources */, F372087D2BAB4C0F006B5430 /* TestConstants.swift in Sources */, + B52FAEA12DA8ED40001AB1BD /* AudioUploadTests.swift in Sources */, + B543154E2DA6913C00981E7E /* AudioUploadTests.swift in Sources */, + B5D45E702DA5119A00773929 /* RenameFileTests.swift in Sources */, F78E2D6C29AF02DB0024D4F3 /* Database.swift in Sources */, + B5BEBD6B2E93AE4B0002C9E5 /* SharingTest.swift in Sources */, + B5BEBD6C2E93AE4B0002C9E5 /* AssetUploadTest.swift in Sources */, + B5BEBD6D2E93AE4B0002C9E5 /* NCNotificationText.swift in Sources */, + B5BEBD6E2E93AE4B0002C9E5 /* SettingsTestCases.swift in Sources */, + B5BEBD6F2E93AE4B0002C9E5 /* CollaboraTestCase.swift in Sources */, + B5BEBD702E93AE4B0002C9E5 /* MoveAndCopyTests.swift in Sources */, + B5BEBD712E93AE4B0002C9E5 /* MoreTests.swift in Sources */, + B5BEBD722E93AE4B0002C9E5 /* RenameFileTests.swift in Sources */, + B5BEBD732E93AE4B0002C9E5 /* AudioUploadTests.swift in Sources */, + B5BEBD742E93AE4B0002C9E5 /* OnboardingTestCase.swift in Sources */, + B5BEBD752E93AE4B0002C9E5 /* E2EETests.swift in Sources */, + B5BEBD762E93AE4B0002C9E5 /* ScanTests.swift in Sources */, + B5BEBD772E93AE4B0002C9E5 /* PrivacyPolicyTest.swift in Sources */, + B5E2E6D42DAE52B500AB2EDD /* SharingTest.swift in Sources */, + B543154C2DA690B700981E7E /* NCNotificationText.swift in Sources */, F7817CFE29801A3500FFBC65 /* Data+Extension.swift in Sources */, + B52FAED32DA8F22F001AB1BD /* MoveAndCopyTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4253,6 +5060,11 @@ AA74AA972D3172D100BE3458 /* UITestError.swift in Sources */, AA3C85E82D36B08C00F74F12 /* UITestBackend.swift in Sources */, AA8E03DC2D2FBAC200E7E89C /* DownloadLimitUITests.swift in Sources */, + B5BEBD562E93AE1C0002C9E5 /* TestConstants.swift in Sources */, + B5BEBD572E93AE1C0002C9E5 /* BaseXCTestCase.swift in Sources */, + B5BEBD5B2E93AE2F0002C9E5 /* LoginIntegrationTests.swift in Sources */, + B5BEBD5C2E93AE2F0002C9E5 /* BaseIntegrationXCTestCase.swift in Sources */, + B5BEBD5D2E93AE2F0002C9E5 /* FilesIntegrationTests.swift in Sources */, AABD0C8A2D5F67A400F009E6 /* XCUIElement.swift in Sources */, AA3C85EE2D36BCCE00F74F12 /* SharesResponse.swift in Sources */, AAA7BC2E2D3E39F1008F1A22 /* CapabilitiesResponse.swift in Sources */, @@ -4260,7 +5072,6 @@ F3374A962D6744A4002A38F9 /* BaseUIXCTestCase.swift in Sources */, F37208812BAB5979006B5430 /* TestConstants.swift in Sources */, F33D303E2D8B129600531D64 /* AutoUploadUITests.swift in Sources */, - AABD0C9B2D5F73FC00F009E6 /* Placeholder.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4268,6 +5079,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + B5BEBD522E93AE1C0002C9E5 /* TestConstants.swift in Sources */, + B5BEBD532E93AE1C0002C9E5 /* BaseXCTestCase.swift in Sources */, F372087E2BAB4C0F006B5430 /* TestConstants.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -4279,42 +5092,41 @@ F74B6D9A2A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */, F7490E8329882C84009DCE94 /* NCManageDatabase+LayoutForView.swift in Sources */, AA8D31582D41052300FE2775 /* NCManageDatabase+DownloadLimit.swift in Sources */, - F77E8C222E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift in Sources */, - F7DB7DE92E81731B0017AF90 /* NCStorageEstimator.swift in Sources */, F73EF7DC2B0226080087E6E9 /* NCManageDatabase+Tip.swift in Sources */, F7490E8029882C76009DCE94 /* NCManageDatabase+Avatar.swift in Sources */, F343A4B82A1E084300DDA874 /* PHAsset+Extension.swift in Sources */, F78E2D6A29AF02DB0024D4F3 /* Database.swift in Sources */, F7C687EE2D22BDE5004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */, F7490E7429882BCC009DCE94 /* NCManageDatabase.swift in Sources */, + F7CF067E2E0FF3990063AD04 /* NCAppStateManager.swift in Sources */, F7490E6E29882B56009DCE94 /* NCBrand.swift in Sources */, F7490E8129882C79009DCE94 /* NCManageDatabase+DashboardWidget.swift in Sources */, F73EF7D42B0225BA0087E6E9 /* NCManageDatabase+Tag.swift in Sources */, F71F6D0C2B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */, F7490E8629882C99009DCE94 /* NCUtilityFileSystem.swift in Sources */, - F7F1FBA12E27CFBC00C79E20 /* NCContentPresenter.swift in Sources */, F763D2A22A249C4500A3C901 /* NCManageDatabase+Capabilities.swift in Sources */, + B5BEBDAD2E93AF010002C9E5 /* AppUtility.swift in Sources */, + B5BEBDAE2E93AF010002C9E5 /* AdjustHelper.m in Sources */, + B5BEBDAF2E93AF010002C9E5 /* TealiumHelper.swift in Sources */, + B5BEBDB02E93AF010002C9E5 /* NCEmptyDataSet.swift in Sources */, F73EF7E42B02266D0087E6E9 /* NCManageDatabase+Trash.swift in Sources */, F343A4C02A1E734600DDA874 /* Optional+Extension.swift in Sources */, F7D7A76D2DCDD437003D2007 /* NCManageDatabase+AutoUpload.swift in Sources */, F711A4E12AF92CAE00095DD8 /* NCUtility+Date.swift in Sources */, - F76882382C0DD22F001CF441 /* NCPreferences.swift in Sources */, + F76882382C0DD22F001CF441 /* NCKeychain.swift in Sources */, F7C9B9222B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */, F7490E8529882C8C009DCE94 /* NCManageDatabase+Video.swift in Sources */, F7CF06892E1127460063AD04 /* NCManageDatabase+Metadata+Create.swift in Sources */, F7386E4A2DA90E0F009A00F6 /* NCAppVersionManager.swift in Sources */, - F3F442F32DDE2A7700FD701F /* NCMetadataPermissions.swift in Sources */, F7490E7729882C10009DCE94 /* UIColor+Extension.swift in Sources */, F70716E62987F81500E72C1D /* DocumentActionViewController.swift in Sources */, F359D86C2A7D03420023F405 /* NCUtility+Exif.swift in Sources */, - F7F1FB9E2E27CE7200C79E20 /* NCNetworking.swift in Sources */, F7490E8429882C89009DCE94 /* NCManageDatabase+Share.swift in Sources */, F7490E6F29882B67009DCE94 /* UIImage+Extension.swift in Sources */, F7490E7E29882C6E009DCE94 /* NCManageDatabase+Account.swift in Sources */, F7490E7029882B9B009DCE94 /* NCManageDatabase+Metadata.swift in Sources */, F73EF7AC2B0223900087E6E9 /* NCManageDatabase+Comments.swift in Sources */, F73EF7C42B02250B0087E6E9 /* NCManageDatabase+GPS.swift in Sources */, - F7F563012E15762B00631A11 /* MigrationMultiDomains.swift in Sources */, F77DD6AD2C5CC093009448FB /* NCSession.swift in Sources */, F7490E6C29882AEA009DCE94 /* String+Extension.swift in Sources */, F7490E6B29882A92009DCE94 /* NCGlobal.swift in Sources */, @@ -4324,16 +5136,22 @@ F73EF7A42B021FAD0087E6E9 /* NCLivePhoto.swift in Sources */, F757CC8729E7F88B00F31428 /* NCManageDatabase+Groupfolders.swift in Sources */, F33EE6F72BF4C9B200CA1A51 /* PKCS12.swift in Sources */, + B5BEBDED2E93BDB40002C9E5 /* FolderPathCustomCell.swift in Sources */, + B5BEBDEE2E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift in Sources */, F7B769AD2B7A0B2000C1AAEB /* NCManageDatabase+Metadata+Session.swift in Sources */, F39170AC2CB82024006127BC /* FileAutoRenamer+Extensions.swift in Sources */, F73EF7BC2B0224AB0087E6E9 /* NCManageDatabase+ExternalSites.swift in Sources */, - F724377E2C10B92300C7C68D /* NCSharePermissions.swift in Sources */, + F724377E2C10B92300C7C68D /* NCPermissions.swift in Sources */, F7490E8229882C80009DCE94 /* NCManageDatabase+E2EE.swift in Sources */, F7490E7829882C28009DCE94 /* NCUtility.swift in Sources */, F3E173C52C9B1067006D177A /* AwakeMode.swift in Sources */, F71433E62C778FFB00E20B5A /* NotificationCenter+MainThread.swift in Sources */, F33918C92C7CD8F2002D9AA1 /* FileNameValidator+Extensions.swift in Sources */, F7490E7F29882C73009DCE94 /* NCManageDatabase+Activity.swift in Sources */, + B5BEBD962E93AED80002C9E5 /* AppUpdater.swift in Sources */, + B5BEBD832E93AEA30002C9E5 /* AnalyticsService.swift in Sources */, + B5BEBD842E93AEA30002C9E5 /* MoEngageAnalytics.swift in Sources */, + B5BEBD852E93AEA30002C9E5 /* AnalyticsHelper.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4359,10 +5177,8 @@ F7327E372B73AEDE00A462C7 /* NCNetworking+LivePhoto.swift in Sources */, F7F3E58D2D3BB65600A32B14 /* NCNetworking+Recommendations.swift in Sources */, F73EF7D22B0225BA0087E6E9 /* NCManageDatabase+Tag.swift in Sources */, - F7F563052E15762B00631A11 /* MigrationMultiDomains.swift in Sources */, F74B6D982A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */, F7CF06872E1127460063AD04 /* NCManageDatabase+Metadata+Create.swift in Sources */, - F7FDFF722E437E55000D7688 /* NCAccountRequest.swift in Sources */, F7707687263A853700A1BA94 /* NCContentPresenter.swift in Sources */, F343A4B62A1E084200DDA874 /* PHAsset+Extension.swift in Sources */, F70460532499095400BB98A7 /* NotificationCenter+MainThread.swift in Sources */, @@ -4374,13 +5190,18 @@ F79ED0F12D2FCA5B00A389D9 /* NCSectionFirstHeader.swift in Sources */, F79B646126CA661600838ACA /* UIControl+Extension.swift in Sources */, F77C973A2953143A00FDDD09 /* NCCameraRoll.swift in Sources */, + B5BEBDD62E93B2450002C9E5 /* NCCreateFormUploadDocuments.swift in Sources */, + B5BEBDD72E93B2450002C9E5 /* TextTableViewCell.swift in Sources */, + B5BEBDD82E93B2450002C9E5 /* NCCreateFormUploadVoiceNote.swift in Sources */, F740BEF02A35C2AD00E9B6D5 /* UILabel+Extension.swift in Sources */, F7C30E01291BD2610017149B /* NCNetworkingE2EERename.swift in Sources */, AF4BF61A27562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */, AF4BF615275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */, F798F0E225880608000DAFFD /* UIColor+Extension.swift in Sources */, F7327E3F2B73B92800A462C7 /* NCNetworking+Synchronization.swift in Sources */, + F7CF067F2E0FF3990063AD04 /* NCAppStateManager.swift in Sources */, F7C9B9202B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */, + B5BEBD942E93AED80002C9E5 /* AppUpdater.swift in Sources */, F78E2D6829AF02DB0024D4F3 /* Database.swift in Sources */, AA8D31562D41052300FE2775 /* NCManageDatabase+DownloadLimit.swift in Sources */, F711A4DF2AF92CAE00095DD8 /* NCUtility+Date.swift in Sources */, @@ -4392,10 +5213,8 @@ F7D4BF2F2CA2E8D800A5E746 /* TOPasscodeButtonLabel.m in Sources */, F7D4BF302CA2E8D800A5E746 /* TOPasscodeViewControllerAnimatedTransitioning.m in Sources */, F7D4BF312CA2E8D800A5E746 /* TOPasscodeSettingsViewController.m in Sources */, - F71916122E2901FB00E13E96 /* NCNetworking+Upload.swift in Sources */, F7D4BF322CA2E8D800A5E746 /* TOPasscodeCircleImage.m in Sources */, F7D4BF332CA2E8D800A5E746 /* TOPasscodeView.m in Sources */, - F77E8C252E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift in Sources */, F7D4BF342CA2E8D800A5E746 /* TOPasscodeCircleButton.m in Sources */, F7D4BF352CA2E8D800A5E746 /* TOPasscodeInputField.m in Sources */, F7D4BF362CA2E8D800A5E746 /* TOSettingsKeypadImage.m in Sources */, @@ -4411,19 +5230,20 @@ AF22B206277B4E4C00DAB0CC /* NCCreateFormUploadConflict.swift in Sources */, F74D50362C9856D300BBBF4C /* NCCollectionViewDataSource.swift in Sources */, F7A573692E190387009C9257 /* NCShareExtensionData.swift in Sources */, + B5BEBD862E93AEA30002C9E5 /* AnalyticsService.swift in Sources */, + B5BEBD872E93AEA30002C9E5 /* MoEngageAnalytics.swift in Sources */, + B5BEBD882E93AEA30002C9E5 /* AnalyticsHelper.swift in Sources */, F7BD71E62636EAFC00643C34 /* NCNetworkingE2EE.swift in Sources */, F7F878AF1FB9E3B900599E4F /* NCEndToEndMetadata.swift in Sources */, F7327E3B2B73B8D600A462C7 /* Array+Extension.swift in Sources */, F7D7A76C2DCDD437003D2007 /* NCManageDatabase+AutoUpload.swift in Sources */, F39170AF2CB82024006127BC /* FileAutoRenamer+Extensions.swift in Sources */, - F7DB7DEF2E81731B0017AF90 /* NCStorageEstimator.swift in Sources */, F799DF832C4B7DCC003410B5 /* NCSectionFooter.swift in Sources */, AF22B218277D196700DAB0CC /* NCShareExtension+Files.swift in Sources */, F799DF862C4B7E56003410B5 /* NCSectionHeader.swift in Sources */, - F36C514E2E89393C0097E5F7 /* UIView+BlurVibrancy.swift in Sources */, F702F2D025EE5B5C008F8E80 /* NCGlobal.swift in Sources */, F343A4BE2A1E734600DDA874 /* Optional+Extension.swift in Sources */, - F72437802C10B92400C7C68D /* NCSharePermissions.swift in Sources */, + F72437802C10B92400C7C68D /* NCPermissions.swift in Sources */, F7EDE4DB262D7BA200414FE6 /* NCCellProtocol.swift in Sources */, F72944F62A8424F800246839 /* NCEndToEndMetadataV1.swift in Sources */, F73EF7BA2B0224AB0087E6E9 /* NCManageDatabase+ExternalSites.swift in Sources */, @@ -4434,36 +5254,52 @@ F7327E232B73A42F00A462C7 /* NCNetworking+Download.swift in Sources */, F749B64D297B0CBB00087535 /* NCManageDatabase+Share.swift in Sources */, F72FD3B8297ED49A00075D28 /* NCManageDatabase+E2EE.swift in Sources */, + B5BEBDCC2E93B0210002C9E5 /* NCSectionHeaderMenu.swift in Sources */, F7A76DC8256A71CD00119AB3 /* UIImage+Extension.swift in Sources */, F3E173C32C9B1067006D177A /* AwakeMode.swift in Sources */, F711A4E52AF9310500095DD8 /* NCUtility+Image.swift in Sources */, F73EF7AA2B0223900087E6E9 /* NCManageDatabase+Comments.swift in Sources */, F763D2A02A249C4500A3C901 /* NCManageDatabase+Capabilities.swift in Sources */, F757CC8529E7F88B00F31428 /* NCManageDatabase+Groupfolders.swift in Sources */, - F768823A2C0DD230001CF441 /* NCPreferences.swift in Sources */, + F768823A2C0DD230001CF441 /* NCKeychain.swift in Sources */, + B5BEBDF92E93BDB40002C9E5 /* FolderPathCustomCell.swift in Sources */, + B5BEBDFA2E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift in Sources */, F7386E472DA90E0F009A00F6 /* NCAppVersionManager.swift in Sources */, F737DA9E2B7B893C0063BAFC /* NCPasscode.swift in Sources */, + F7817D0129802D5F00FFBC65 /* NCViewCertificateDetails.swift in Sources */, + F7D57C8B26317BDE00DE301D /* NCAccountRequest.swift in Sources */, F7C30DF7291BC0D30017149B /* NCNetworkingE2EEUpload.swift in Sources */, F7C687EC2D22BDE5004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */, F33918C72C7CD8F2002D9AA1 /* FileNameValidator+Extensions.swift in Sources */, F78A10C229322E8A008499B8 /* NCManageDatabase+Directory.swift in Sources */, F79FFB272A97C24A0055EEA4 /* NCNetworkingE2EEMarkFolder.swift in Sources */, F7D68FCE28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */, - F3F442F12DDE2A7700FD701F /* NCMetadataPermissions.swift in Sources */, AF22B217277D196700DAB0CC /* NCShareExtension+DataSource.swift in Sources */, F73EF7E22B02266D0087E6E9 /* NCManageDatabase+Trash.swift in Sources */, F33EE6F52BF4C9B200CA1A51 /* PKCS12.swift in Sources */, F77DD6AB2C5CC093009448FB /* NCSession.swift in Sources */, F76D364728A4F8BF00214537 /* NCActivityIndicator.swift in Sources */, + F73EF7CA2B0225610087E6E9 /* NCManageDatabase+PhotoLibrary.swift in Sources */, + B54315552DA6929700981E7E /* NCCreateFormUploadVoiceNote.swift in Sources */, F7BFFD2A2C8854200029A201 /* NCHud.swift in Sources */, F749B654297B0F2400087535 /* NCManageDatabase+Avatar.swift in Sources */, AF22B208277B4E4C00DAB0CC /* NCCreateFormUploadConflictCell.swift in Sources */, F74C86382AEFBE64009A1D4A /* NCImageCache.swift in Sources */, F73EF7C22B02250B0087E6E9 /* NCManageDatabase+GPS.swift in Sources */, + F7327E2B2B73A53400A462C7 /* NCNetworking+Upload.swift in Sources */, + B529E4072E8D1C3E006D9131 /* NCUploadAssets.swift in Sources */, F7148041262EBE4000693E51 /* NCShareExtension.swift in Sources */, F76B3CCF1EAE01BD00921AC9 /* NCBrand.swift in Sources */, F72944F32A84246400246839 /* NCEndToEndMetadataV20.swift in Sources */, F7BAADCC1ED5A87C00B7EAD4 /* NCManageDatabase.swift in Sources */, + B5BEBDB22E93AF010002C9E5 /* AppUtility.swift in Sources */, + B5BEBDB32E93AF010002C9E5 /* AdjustHelper.m in Sources */, + B5BEBDB42E93AF010002C9E5 /* TealiumHelper.swift in Sources */, + B5BEBDB52E93AF010002C9E5 /* NCEmptyDataSet.swift in Sources */, + B5BEBD1E2E93A74C0002C9E5 /* CreateLinkFooterView.swift in Sources */, + B5BEBD1F2E93A74C0002C9E5 /* NCPermissions.swift in Sources */, + B5BEBD202E93A74C0002C9E5 /* NCShareEmailLinkHeaderView.swift in Sources */, + B5BEBD212E93A74C0002C9E5 /* NoSharesFooterView.swift in Sources */, F7327E322B73A86700A462C7 /* NCNetworking+WebDAV.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -4473,7 +5309,10 @@ buildActionMask = 2147483647; files = ( F793E5A128B76541005E4B02 /* NotificationCenter+MainThread.swift in Sources */, + B5BEBDFF2E93BDB40002C9E5 /* FolderPathCustomCell.swift in Sources */, + B5BEBE002E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift in Sources */, F76DEE9928F808AF0041B1C9 /* LockscreenWidgetView.swift in Sources */, + F7817D0029802D3D00FFBC65 /* NCViewCertificateDetails.swift in Sources */, F78302F928B4C3E600B84583 /* NCManageDatabase+Account.swift in Sources */, F7E0710128B13BB00001B882 /* DashboardData.swift in Sources */, F783030328B4C4DD00B84583 /* ThreadSafeDictionary.swift in Sources */, @@ -4490,7 +5329,8 @@ F39170AE2CB82024006127BC /* FileAutoRenamer+Extensions.swift in Sources */, F76DEE9728F808AF0041B1C9 /* LockscreenData.swift in Sources */, F72EA95A28B7BD0D00C88F0C /* FilesWidgetView.swift in Sources */, - F768823C2C0DD231001CF441 /* NCPreferences.swift in Sources */, + F7CF067C2E0FF3990063AD04 /* NCAppStateManager.swift in Sources */, + F768823C2C0DD231001CF441 /* NCKeychain.swift in Sources */, F71F6D082B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */, F78302FE28B4C44700B84583 /* NCBrand.swift in Sources */, F749B64B297B0CBB00087535 /* NCManageDatabase+Share.swift in Sources */, @@ -4498,25 +5338,29 @@ F7817CF929801A3500FFBC65 /* Data+Extension.swift in Sources */, F7864ACD2A78FE73004870E0 /* NCManageDatabase+LocalFile.swift in Sources */, F343A4B42A1E084100DDA874 /* PHAsset+Extension.swift in Sources */, - F71916112E2901FB00E13E96 /* NCNetworking+Upload.swift in Sources */, F793E59F28B764F6005E4B02 /* NCContentPresenter.swift in Sources */, F76DEE9828F808AF0041B1C9 /* LockscreenWidgetProvider.swift in Sources */, F33EE6F32BF4C9B200CA1A51 /* PKCS12.swift in Sources */, F78A10C029322E8A008499B8 /* NCManageDatabase+Directory.swift in Sources */, F78302FA28B4C3EA00B84583 /* NCManageDatabase+Metadata.swift in Sources */, + B5BEBDA92E93AF010002C9E5 /* AppUtility.swift in Sources */, + B5BEBDAA2E93AF010002C9E5 /* AdjustHelper.m in Sources */, + B5BEBDAB2E93AF010002C9E5 /* TealiumHelper.swift in Sources */, + B5BEBDAC2E93AF010002C9E5 /* NCEmptyDataSet.swift in Sources */, F7B769A92B7A0B2000C1AAEB /* NCManageDatabase+Metadata+Session.swift in Sources */, F78E2D6629AF02DB0024D4F3 /* Database.swift in Sources */, F7327E3E2B73B92800A462C7 /* NCNetworking+Synchronization.swift in Sources */, F77DD6A92C5CC093009448FB /* NCSession.swift in Sources */, - F7F563022E15762B00631A11 /* MigrationMultiDomains.swift in Sources */, F783030728B4C52800B84583 /* UIColor+Extension.swift in Sources */, - F7DB7DEE2E81731B0017AF90 /* NCStorageEstimator.swift in Sources */, F783030028B4C45800B84583 /* NCGlobal.swift in Sources */, F793E59D28B761E7005E4B02 /* NCNetworking.swift in Sources */, F7BF9D832934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */, F757CC8329E7F88B00F31428 /* NCManageDatabase+Groupfolders.swift in Sources */, F73EF7A82B0223900087E6E9 /* NCManageDatabase+Comments.swift in Sources */, F7327E212B73A42F00A462C7 /* NCNetworking+Download.swift in Sources */, + B5BEBD7D2E93AEA30002C9E5 /* AnalyticsService.swift in Sources */, + B5BEBD7E2E93AEA30002C9E5 /* MoEngageAnalytics.swift in Sources */, + B5BEBD7F2E93AEA30002C9E5 /* AnalyticsHelper.swift in Sources */, F7BFFD2B2C8854430029A201 /* NCHud.swift in Sources */, F7386E492DA90E0F009A00F6 /* NCAppVersionManager.swift in Sources */, F7327E3A2B73B8D500A462C7 /* Array+Extension.swift in Sources */, @@ -4526,7 +5370,7 @@ F783030628B4C51E00B84583 /* String+Extension.swift in Sources */, F763D29E2A249C4500A3C901 /* NCManageDatabase+Capabilities.swift in Sources */, F711A4DD2AF92CAE00095DD8 /* NCUtility+Date.swift in Sources */, - F724377C2C10B92200C7C68D /* NCSharePermissions.swift in Sources */, + F724377C2C10B92200C7C68D /* NCPermissions.swift in Sources */, F36E64FB2B9733F10085ABB5 /* UIView+Extension.swift in Sources */, F77ED59328C9CEA000E24ED0 /* ToolbarWidgetProvider.swift in Sources */, F72A17D828B221E300F3F159 /* DashboardWidgetView.swift in Sources */, @@ -4536,8 +5380,8 @@ F7C687EA2D22BDE5004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */, F7CF06862E1127460063AD04 /* NCManageDatabase+Metadata+Create.swift in Sources */, F72EA95228B7BA2A00C88F0C /* DashboardWidgetProvider.swift in Sources */, - F77E8C242E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift in Sources */, F33918C52C7CD8F2002D9AA1 /* FileNameValidator+Extensions.swift in Sources */, + F7327E292B73A53400A462C7 /* NCNetworking+Upload.swift in Sources */, F7D7A7702DCDD437003D2007 /* NCManageDatabase+AutoUpload.swift in Sources */, F343A4BC2A1E734600DDA874 /* Optional+Extension.swift in Sources */, F7411C562D7B26D700F57358 /* NCNetworking+ServerError.swift in Sources */, @@ -4549,7 +5393,6 @@ F78302FF28B4C45000B84583 /* NCUtilityFileSystem.swift in Sources */, F73EF7B82B0224AB0087E6E9 /* NCManageDatabase+ExternalSites.swift in Sources */, F73EF7C02B02250B0087E6E9 /* NCManageDatabase+GPS.swift in Sources */, - F3F442EF2DDE2A7700FD701F /* NCMetadataPermissions.swift in Sources */, F3E173C12C9B1067006D177A /* AwakeMode.swift in Sources */, F75DD766290ABB25002EB562 /* Intent.intentdefinition in Sources */, F7D68FCD28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */, @@ -4560,6 +5403,7 @@ F36E64FD2B9735900085ABB5 /* NCCellProtocol.swift in Sources */, F783030128B4C49700B84583 /* UIImage+Extension.swift in Sources */, F72EA95428B7BABA00C88F0C /* FilesWidgetProvider.swift in Sources */, + B5BEBD992E93AED80002C9E5 /* AppUpdater.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4577,15 +5421,14 @@ F702F2D125EE5B5C008F8E80 /* NCGlobal.swift in Sources */, F711A4E02AF92CAE00095DD8 /* NCUtility+Date.swift in Sources */, F76D364828A4F8BF00214537 /* NCActivityIndicator.swift in Sources */, - F7F563002E15762B00631A11 /* MigrationMultiDomains.swift in Sources */, F7327E242B73A42F00A462C7 /* NCNetworking+Download.swift in Sources */, - F71916132E2901FB00E13E96 /* NCNetworking+Upload.swift in Sources */, F7C687ED2D22BDE5004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */, + F7817D0229802D7700FFBC65 /* NCViewCertificateDetails.swift in Sources */, F7CF06842E1127460063AD04 /* NCManageDatabase+Metadata+Create.swift in Sources */, F7434B3820E2400600417916 /* NCBrand.swift in Sources */, F7327E332B73A86700A462C7 /* NCNetworking+WebDAV.swift in Sources */, F7411C572D7B26D700F57358 /* NCNetworking+ServerError.swift in Sources */, - F724377F2C10B92400C7C68D /* NCSharePermissions.swift in Sources */, + F724377F2C10B92400C7C68D /* NCPermissions.swift in Sources */, F785EE9E2461A09900B3F945 /* NCNetworking.swift in Sources */, F749B655297B0F2400087535 /* NCManageDatabase+Avatar.swift in Sources */, F7327E382B73AEDE00A462C7 /* NCNetworking+LivePhoto.swift in Sources */, @@ -4595,17 +5438,19 @@ F7D7A76F2DCDD437003D2007 /* NCManageDatabase+AutoUpload.swift in Sources */, AF4BF616275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */, F343A4B72A1E084300DDA874 /* PHAsset+Extension.swift in Sources */, + B5BEBD972E93AED80002C9E5 /* AppUpdater.swift in Sources */, F7434B3620E23FE000417916 /* NCManageDatabase.swift in Sources */, F798F0E725880609000DAFFD /* UIColor+Extension.swift in Sources */, F74B6D992A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */, + F7327E2C2B73A53400A462C7 /* NCNetworking+Upload.swift in Sources */, + B5BEBE032E93BDB40002C9E5 /* FolderPathCustomCell.swift in Sources */, + B5BEBE042E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift in Sources */, F7D68FCF28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */, F33EE6F62BF4C9B200CA1A51 /* PKCS12.swift in Sources */, - F77E8C212E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift in Sources */, F7A3DB922DDE23B5008F7EC8 /* NCDebouncer.swift in Sources */, F7F3E58B2D3BB65600A32B14 /* NCNetworking+Recommendations.swift in Sources */, F73EF7C32B02250B0087E6E9 /* NCManageDatabase+GPS.swift in Sources */, F7C9B9212B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */, - F3F442F22DDE2A7700FD701F /* NCMetadataPermissions.swift in Sources */, F359D86B2A7D03420023F405 /* NCUtility+Exif.swift in Sources */, F7864AD02A78FE73004870E0 /* NCManageDatabase+LocalFile.swift in Sources */, F7327E402B73B92800A462C7 /* NCNetworking+Synchronization.swift in Sources */, @@ -4613,12 +5458,18 @@ F70460542499095400BB98A7 /* NotificationCenter+MainThread.swift in Sources */, F78A10C329322E8A008499B8 /* NCManageDatabase+Directory.swift in Sources */, F36E64FE2B9735920085ABB5 /* NCCellProtocol.swift in Sources */, - F7DB7DEC2E81731B0017AF90 /* NCStorageEstimator.swift in Sources */, F7BF9D862934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */, F7E98C1827E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */, F785EEA42461A4A600B3F945 /* NCUtility.swift in Sources */, F79B646226CA661600838ACA /* UIControl+Extension.swift in Sources */, F7C1DAEF2C3D1DF4000BDC69 /* FileProviderDomain.swift in Sources */, + B5BEBDC22E93AF010002C9E5 /* AppUtility.swift in Sources */, + B5BEBDC32E93AF010002C9E5 /* AdjustHelper.m in Sources */, + B5BEBDC42E93AF010002C9E5 /* TealiumHelper.swift in Sources */, + B5BEBDC52E93AF010002C9E5 /* NCEmptyDataSet.swift in Sources */, + B5BEBD8F2E93AEA30002C9E5 /* AnalyticsService.swift in Sources */, + B5BEBD902E93AEA30002C9E5 /* MoEngageAnalytics.swift in Sources */, + B5BEBD912E93AEA30002C9E5 /* AnalyticsHelper.swift in Sources */, F73EF7AB2B0223900087E6E9 /* NCManageDatabase+Comments.swift in Sources */, F7327E392B73B8D400A462C7 /* Array+Extension.swift in Sources */, F78E2D6929AF02DB0024D4F3 /* Database.swift in Sources */, @@ -4640,8 +5491,9 @@ F7BFFD2C2C8854690029A201 /* NCHud.swift in Sources */, F7386E4C2DA90E0F009A00F6 /* NCAppVersionManager.swift in Sources */, F771E3F820E239B500AFB62D /* FileProviderExtension+Thumbnail.swift in Sources */, - F76882392C0DD230001CF441 /* NCPreferences.swift in Sources */, + F76882392C0DD230001CF441 /* NCKeychain.swift in Sources */, F39170AB2CB82024006127BC /* FileAutoRenamer+Extensions.swift in Sources */, + F7CF067D2E0FF3990063AD04 /* NCAppStateManager.swift in Sources */, F343A4BF2A1E734600DDA874 /* Optional+Extension.swift in Sources */, AF4BF62027562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */, F73ADD2226554FD10069EA0D /* NCContentPresenter.swift in Sources */, @@ -4660,6 +5512,16 @@ F7E7AEA72BA32D0000512E52 /* NCCollectionViewUnifiedSearch.swift in Sources */, F73EF7A72B0223900087E6E9 /* NCManageDatabase+Comments.swift in Sources */, F33918C42C7CD8F2002D9AA1 /* FileNameValidator+Extensions.swift in Sources */, + B52FAEC02DA8EF84001AB1BD /* FileNameInputTextField.swift in Sources */, + B52FAEC12DA8EF84001AB1BD /* ScanDocumentPathView.swift in Sources */, + B52FAEC22DA8EF84001AB1BD /* PNGImageSaveSwitchView.swift in Sources */, + B52FAEC32DA8EF84001AB1BD /* SetPDFPasswordSwitchView.swift in Sources */, + B52FAEC42DA8EF84001AB1BD /* PdfWithOcrSwitchView.swift in Sources */, + B52FAEC52DA8EF84001AB1BD /* PasswordInputField.swift in Sources */, + B52FAEC62DA8EF84001AB1BD /* JPGImageSaveSwitchView.swift in Sources */, + B52FAEC72DA8EF84001AB1BD /* PdfWithoutOcrSwitchView.swift in Sources */, + B52FAEC82DA8EF84001AB1BD /* TextFileWithOcrSwitchView.swift in Sources */, + B52FAE942DA8DCB2001AB1BD /* NCCreateFormUploadDocuments.swift in Sources */, F39170AD2CB82024006127BC /* FileAutoRenamer+Extensions.swift in Sources */, F799DF882C4B83CC003410B5 /* NCCollectionViewCommon+EasyTipView.swift in Sources */, F7AE00F8230E81CB007ACF8A /* NCBrowserWeb.swift in Sources */, @@ -4668,14 +5530,21 @@ F733598125C1C188002ABA72 /* NCAskAuthorization.swift in Sources */, 370D26AF248A3D7A00121797 /* NCCellProtocol.swift in Sources */, F32FADA92D1176E3007035E2 /* UIButton+Extension.swift in Sources */, + F768822C2C0DD1E7001CF441 /* NCKeychain.swift in Sources */, F768822C2C0DD1E7001CF441 /* NCPreferences.swift in Sources */, + B5E2E6EE2DAE66AF00AB2EDD /* NCShareEmailFieldCell.swift in Sources */, F7BFFD282C8846020029A201 /* NCHud.swift in Sources */, F71CD6CA2930D7B1006C95C1 /* NCApplicationHandle.swift in Sources */, + B568C2BF2DA7CCDB0072FCB4 /* MagentaCloudVersionView.swift in Sources */, + B568C2C02DA7CCDB0072FCB4 /* ImprintViewController.swift in Sources */, + B568C2C12DA7CCDB0072FCB4 /* HelpViewController.swift in Sources */, F3754A7D2CF87D600009312E /* SetupPasscodeView.swift in Sources */, F73EF7D72B0226080087E6E9 /* NCManageDatabase+Tip.swift in Sources */, F3374A842D64AC31002A38F9 /* AssistantLabelStyle.swift in Sources */, F74BAE172C7E2F4E0028D4FA /* FileProviderDomain.swift in Sources */, F76882402C0DD30B001CF441 /* ViewOnAppear.swift in Sources */, + B5E2E6E92DAE59F000AB2EDD /* NCShareTextInputCell.swift in Sources */, + B5E2E6EA2DAE59F000AB2EDD /* NCShareHeaderCustomCell.swift in Sources */, F790110E21415BF600D7B136 /* NCViewerRichDocument.swift in Sources */, F78ACD4021903CC20088454D /* NCGridCell.swift in Sources */, F7D890752BD25C570050B8A6 /* NCCollectionViewCommon+DragDrop.swift in Sources */, @@ -4698,13 +5567,25 @@ F76D3CF12428B40E005DFA87 /* NCViewerPDFSearch.swift in Sources */, F7245924289BB50C00474787 /* ThreadSafeDictionary.swift in Sources */, F73F537F1E929C8500F8678D /* NCMore.swift in Sources */, + B5BEBE1A2E93BE200002C9E5 /* PNGImageSaveSwitchView.swift in Sources */, + B5BEBE1B2E93BE200002C9E5 /* FileNameInputTextField.swift in Sources */, + B5BEBE1C2E93BE200002C9E5 /* PdfWithoutOcrSwitchView.swift in Sources */, + B5BEBE1D2E93BE200002C9E5 /* TextFileWithOcrSwitchView.swift in Sources */, + B5BEBE1E2E93BE200002C9E5 /* ScanDocumentPathView.swift in Sources */, + B5BEBE1F2E93BE200002C9E5 /* SetPDFPasswordSwitchView.swift in Sources */, + B5BEBE202E93BE200002C9E5 /* JPGImageSaveSwitchView.swift in Sources */, + B5BEBE212E93BE200002C9E5 /* PasswordInputField.swift in Sources */, + B5BEBE222E93BE200002C9E5 /* PdfWithOcrSwitchView.swift in Sources */, + B5BEBD192E93A5260002C9E5 /* Shareable.swift in Sources */, F702F2CF25EE5B5C008F8E80 /* NCGlobal.swift in Sources */, F794E13F2BBC0F70003693D7 /* SceneDelegate.swift in Sources */, F7A3DB932DDE23B5008F7EC8 /* NCDebouncer.swift in Sources */, F72CD63A25C19EBF00F46F9A /* NCAutoUpload.swift in Sources */, AF93471D27E2361E002537EE /* NCShareAdvancePermissionFooter.swift in Sources */, + B568C2B92DA7CCC10072FCB4 /* CCAdvanced.m in Sources */, F786891D2E93A9DF000E39B3 /* NCTransferStore.swift in Sources */, AF1A9B6427D0CA1E00F17A9E /* UIAlertController+Extension.swift in Sources */, + F73B422C2476764F00A30FD3 /* NCNotification.swift in Sources */, F7FA80012C0F4F3B0072FC60 /* NCUploadAssetsView.swift in Sources */, 371B5A2E23D0B04500FAFAE9 /* NCMenu.swift in Sources */, F74230F32C79B57200CA1ACA /* NCNetworking+Task.swift in Sources */, @@ -4714,15 +5595,25 @@ F7B934FE2BDCFE1E002B2FC9 /* NCDragDrop.swift in Sources */, F77444F8222816D5000D5EB0 /* NCPickerViewController.swift in Sources */, F77BB74A2899857B0090FC19 /* UINavigationController+Extension.swift in Sources */, + F7327E282B73A53400A462C7 /* NCNetworking+Upload.swift in Sources */, F769454622E9F1B0000A798A /* NCShareCommon.swift in Sources */, + B5BEBDC92E93AFF10002C9E5 /* NCSelectableNavigationView.swift in Sources */, F70753F12542A9A200972D44 /* NCViewerMedia.swift in Sources */, F799DF822C4B7DCC003410B5 /* NCSectionFooter.swift in Sources */, F76B649C2ADFFAED00014640 /* NCImageCache.swift in Sources */, F78A18B823CDE2B300F681F3 /* NCViewerRichWorkspace.swift in Sources */, F768822E2C0DD1E7001CF441 /* NCSettingsBundleHelper.swift in Sources */, + F7A60F86292D215000FCE1F2 /* NCShareAccounts.swift in Sources */, F72408332B8A27C900F128E2 /* NCMedia+Command.swift in Sources */, F755CB402B8CB13C00CE27E9 /* NCMediaLayout.swift in Sources */, + B5BEBDCE2E93B0210002C9E5 /* NCSectionHeaderMenu.swift in Sources */, F73EF7B72B0224AB0087E6E9 /* NCManageDatabase+ExternalSites.swift in Sources */, + B54315412DA669C700981E7E /* InitialPrivacySettingsViewController.swift in Sources */, + B54315422DA669C700981E7E /* RequiredDataCollectionSwitch.swift in Sources */, + B54315432DA669C700981E7E /* PrivacySettingsViewController.swift in Sources */, + B54315442DA669C700981E7E /* AnalysisDataCollectionSwitch.swift in Sources */, + B54315452DA669C700981E7E /* PrivacyPolicyViewController.swift in Sources */, + B54315462DA669C700981E7E /* SaveSettingsCustomButtonCell.swift in Sources */, AF4BF61927562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */, F78A18B623CDD07D00F681F3 /* NCViewerRichWorkspaceWebView.swift in Sources */, AFA2AC8527849604008E1EA7 /* NCActivityCommentView.swift in Sources */, @@ -4733,15 +5624,14 @@ F758B460212C56A400515F55 /* NCScan.swift in Sources */, F76882262C0DD1E7001CF441 /* NCSettingsView.swift in Sources */, F78ACD52219046DC0088454D /* NCSectionFirstHeader.swift in Sources */, - F743C89E2E5B25A1000173A9 /* UIScene+Extension.swift in Sources */, F72944F52A8424F800246839 /* NCEndToEndMetadataV1.swift in Sources */, - F710D2022405826100A6033D /* NCViewerContextMenu.swift in Sources */, + F710D2022405826100A6033D /* NCViewer+Menu.swift in Sources */, F765E9CD295C585800A09ED8 /* NCUploadScanDocument.swift in Sources */, + B5C980202DAD201A0041B146 /* NCSortMenu.swift in Sources */, F741C2242B6B9FD600E849BB /* NCMediaSelectTabBar.swift in Sources */, F77A697D250A0FBC00FF1708 /* NCCollectionViewCommon+Menu.swift in Sources */, F7BF9D822934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */, AA8D31662D411FA100FE2775 /* NCShareDateCell.swift in Sources */, - F3F442EE2DDE292D00FD701F /* NCMetadataPermissions.swift in Sources */, F3374A812D64AB9F002A38F9 /* StatusInfo.swift in Sources */, AF7E504E27A2D8FF00B5E4AF /* UIBarButton+Extension.swift in Sources */, AA8D31682D41224800FE2775 /* NCShareToggleCell.swift in Sources */, @@ -4750,19 +5640,18 @@ F78A10BF29322E8A008499B8 /* NCManageDatabase+Directory.swift in Sources */, F7743A122C33F0A20034F670 /* NCCollectionViewCommon+CollectionViewDelegate.swift in Sources */, F7D60CAF2C941ACB008FBFDD /* NCMediaPinchGesture.swift in Sources */, - F71916142E2901FB00E13E96 /* NCNetworking+Upload.swift in Sources */, F704B5E92430C0B800632F5F /* NCCreateFormUploadConflictCell.swift in Sources */, F7327E3D2B73B92800A462C7 /* NCNetworking+Synchronization.swift in Sources */, F72D404923D2082500A97FD0 /* NCViewerNextcloudText.swift in Sources */, - AFCE353927E5DE0500FEA6C2 /* Shareable.swift in Sources */, + AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */, F77BB746289984CA0090FC19 /* UIViewController+Extension.swift in Sources */, F700510522DF6A89003A3356 /* NCShare.swift in Sources */, F72D1007210B6882009C96B7 /* NCPushNotificationEncryption.m in Sources */, F76882362C0DD1E7001CF441 /* NCAcknowledgementsView.swift in Sources */, + B52FAEA82DA8EE99001AB1BD /* CCManageAutoUpload.m in Sources */, F785EE9D246196DF00B3F945 /* NCNetworkingE2EE.swift in Sources */, - F724377B2C10B83E00C7C68D /* NCSharePermissions.swift in Sources */, + F724377B2C10B83E00C7C68D /* NCPermissions.swift in Sources */, F794E13D2BBBFF2E003693D7 /* NCMainTabBarController.swift in Sources */, - F753DBDF2E5D99C300A1AF91 /* NCFiles+SyncMetadata.swift in Sources */, F7CBC1252BAC8B0000EC1D55 /* NCSectionFirstHeaderEmptyData.swift in Sources */, F7D4BF3D2CA2E8D800A5E746 /* TOPasscodeKeypadView.m in Sources */, F7D4BF3E2CA2E8D800A5E746 /* TOPasscodeSettingsKeypadView.m in Sources */, @@ -4772,6 +5661,8 @@ F7D4BF402CA2E8D800A5E746 /* TOPasscodeButtonLabel.m in Sources */, F7D4BF412CA2E8D800A5E746 /* TOPasscodeViewControllerAnimatedTransitioning.m in Sources */, F7D4BF422CA2E8D800A5E746 /* TOPasscodeSettingsViewController.m in Sources */, + B5C9801E2DACEB5A0041B146 /* NCCollectionViewCommon+SwipeCollectionViewCellDelegate.swift in Sources */, + B5D45E732DA5172900773929 /* AppUpdater.swift in Sources */, F7D4BF432CA2E8D800A5E746 /* TOPasscodeCircleImage.m in Sources */, F7D4BF442CA2E8D800A5E746 /* TOPasscodeView.m in Sources */, F7D4BF452CA2E8D800A5E746 /* TOPasscodeCircleButton.m in Sources */, @@ -4781,7 +5672,6 @@ F7D4BF492CA2E8D800A5E746 /* TOPasscodeVariableInputView.m in Sources */, F7D4BF4A2CA2E8D800A5E746 /* TOPasscodeCircleView.m in Sources */, F7D4BF4B2CA2E8D800A5E746 /* TOPasscodeViewContentLayout.m in Sources */, - F7DB7DEA2E81731B0017AF90 /* NCStorageEstimator.swift in Sources */, F7D4BF4C2CA2E8D800A5E746 /* TOPasscodeSettingsKeypadButton.m in Sources */, F7D4BF4D2CA2E8D800A5E746 /* TOPasscodeViewController.m in Sources */, F75C0C4823D1FAE300163CC8 /* NCRichWorkspaceCommon.swift in Sources */, @@ -4792,6 +5682,8 @@ F3A047972BD2668800658E7B /* NCAssistantEmptyView.swift in Sources */, F757CC8D29E82D0500F31428 /* NCGroupfolders.swift in Sources */, F760329F252F0F8E0015A421 /* NCTransferCell.swift in Sources */, + B52FAE9E2DA8DED9001AB1BD /* NCCreateDocumentCustomTextField.swift in Sources */, + B52FAE9F2DA8DED9001AB1BD /* FolderPathCustomCell.swift in Sources */, F3BB46542A3A1E9D00461F6E /* CCCellMore.swift in Sources */, AF68326A27BE65A90010BF0B /* NCMenuAction.swift in Sources */, F7F3E58E2D3BB65600A32B14 /* NCNetworking+Recommendations.swift in Sources */, @@ -4800,10 +5692,14 @@ F7F9D1BB25397CE000D9BFF5 /* NCViewer.swift in Sources */, F7E7AEA52BA32C6500512E52 /* NCCollectionViewDownloadThumbnail.swift in Sources */, AF730AF827834B1400B7520E /* NCShare+NCCellDelegate.swift in Sources */, + B5BEBE062E93BE0C0002C9E5 /* NCCreateFormUploadScanDocument.swift in Sources */, F70460522499061800BB98A7 /* NotificationCenter+MainThread.swift in Sources */, F3C587AE2D47E4FE004532DB /* PHAssetCollectionThumbnailLoader.swift in Sources */, F78F74362163781100C2ADAD /* NCTrash.swift in Sources */, F39298972A3B12CB00509762 /* BaseNCMoreCell.swift in Sources */, + B543155B2DA6929700981E7E /* NCCreateFormUploadVoiceNote.swift in Sources */, + B543155C2DA6929700981E7E /* FolderPathCustomCell.swift in Sources */, + B543155D2DA6929700981E7E /* TextTableViewCell.swift in Sources */, AF2D7C7C2742556F00ADF566 /* NCShareLinkCell.swift in Sources */, F7E41316294A19B300839300 /* UIView+Extension.swift in Sources */, F7C30E00291BD2610017149B /* NCNetworkingE2EERename.swift in Sources */, @@ -4813,10 +5709,12 @@ F73EF7BF2B02250B0087E6E9 /* NCManageDatabase+GPS.swift in Sources */, F39A1EE22D0AF8A400DAD522 /* Albums.swift in Sources */, F71F6D072B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */, + B5E2E6D82DAE571200AB2EDD /* PasswordInputField.swift in Sources */, F761856C29E98543006EB3B0 /* NCIntroCollectionViewCell.swift in Sources */, F75DD765290ABB25002EB562 /* Intent.intentdefinition in Sources */, F7D4BF012CA1831900A5E746 /* NCCollectionViewCommonPinchGesture.swift in Sources */, F74B6D952A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */, + F7A8FD522C5E2557006C9CF8 /* NCAccount.swift in Sources */, F310B1EF2BA862F1001C42F5 /* NCViewerMedia+VisionKit.swift in Sources */, F702F2F725EE5CED008F8E80 /* NCLogin.swift in Sources */, F7EB9B132BBC12F300EDF036 /* UIApplication+Extension.swift in Sources */, @@ -4829,16 +5727,17 @@ F7F878AE1FB9E3B900599E4F /* NCEndToEndMetadata.swift in Sources */, F7A7FDDD2C2DBD6200E9A93A /* NCDeepLinkHandler.swift in Sources */, F778231E2C42C07C001BB94F /* NCCollectionViewCommon+MediaLayout.swift in Sources */, + 3781B9B023DB2B7E006B4B1D /* AppDelegate+Menu.swift in Sources */, F710D1F52405770F00A6033D /* NCViewerPDF.swift in Sources */, F389C9F52CEE383300049762 /* SelectAlbumView.swift in Sources */, F7B6B70427C4E7FA00A7F6EB /* NCScan+CollectionView.swift in Sources */, F7816EF22C2C3E1F00A52517 /* NCPushNotification.swift in Sources */, F76882342C0DD1E7001CF441 /* NCDisplayView.swift in Sources */, F7C30DF6291BC0CA0017149B /* NCNetworkingE2EEUpload.swift in Sources */, + B568C2B52DA7AADD0072FCB4 /* NCMoreUserCell.swift in Sources */, F7501C332212E57500FB1415 /* NCMedia.swift in Sources */, F7411C552D7B26D700F57358 /* NCNetworking+ServerError.swift in Sources */, F72944F22A84246400246839 /* NCEndToEndMetadataV20.swift in Sources */, - F7EF2AEB2E43157B0081B2C9 /* NCNotification.swift in Sources */, F70BFC7420E0FA7D00C67599 /* NCUtility.swift in Sources */, F79EDAA526B004980007D134 /* NCPlayer.swift in Sources */, F7C1EEA525053A9C00866ACC /* NCCollectionViewDataSource.swift in Sources */, @@ -4846,6 +5745,8 @@ AFCE353527E4ED5900FEA6C2 /* DateFormatter+Extension.swift in Sources */, F718C24E254D507B00C5C256 /* NCViewerMediaDetailView.swift in Sources */, F33EE6F22BF4C9B200CA1A51 /* PKCS12.swift in Sources */, + B568C2C42DA7CCEA0072FCB4 /* OpenSourceSoftwareViewController.swift in Sources */, + B568C2C52DA7CCEA0072FCB4 /* NCSettings.m in Sources */, F7145610296433C80038D028 /* NCDocumentCamera.swift in Sources */, F76882312C0DD1E7001CF441 /* NCFileNameView.swift in Sources */, F7381EE1218218C9000B1560 /* NCOffline.swift in Sources */, @@ -4854,23 +5755,31 @@ F7FA80002C0F4F3B0072FC60 /* NCUploadAssetsModel.swift in Sources */, F719D9E2288D396100762E33 /* NCColorPicker.swift in Sources */, F73EF7DF2B02266D0087E6E9 /* NCManageDatabase+Trash.swift in Sources */, + B54315342DA64D6500981E7E /* AppUtility.swift in Sources */, F79B646026CA661600838ACA /* UIControl+Extension.swift in Sources */, F768823E2C0DD305001CF441 /* LazyView.swift in Sources */, F3E173B02C9AF637006D177A /* ScreenAwakeManager.swift in Sources */, + F7CA212D25F1333300826ABB /* NCAccountRequest.swift in Sources */, F747EB0D2C4AC1FF00F959A8 /* NCCollectionViewCommon+CollectionViewDelegateFlowLayout.swift in Sources */, F765F73125237E3F00391DBE /* NCRecent.swift in Sources */, F76B3CCE1EAE01BD00921AC9 /* NCBrand.swift in Sources */, F7FA7FFC2C0F4EE40072FC60 /* NCViewerQuickLookView.swift in Sources */, + B5BEBDC72E93AF7E0002C9E5 /* NCLoginWeb.swift in Sources */, F3A0479B2BD2668800658E7B /* NCAssistant.swift in Sources */, + B5BEBD222E93A74C0002C9E5 /* CreateLinkFooterView.swift in Sources */, + B5BEBD232E93A74C0002C9E5 /* NCPermissions.swift in Sources */, + B5BEBD242E93A74C0002C9E5 /* NCShareEmailLinkHeaderView.swift in Sources */, + B5BEBD252E93A74C0002C9E5 /* NoSharesFooterView.swift in Sources */, F359D8672A7D03420023F405 /* NCUtility+Exif.swift in Sources */, F7A03E352D427312007AA677 /* NCMainNavigationController.swift in Sources */, F769CA192966EA3C00039397 /* ComponentView.swift in Sources */, F7C9B91D2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */, AF93474C27E34120002537EE /* NCUtility+Image.swift in Sources */, + F7AEEAA62C11DBAF00011412 /* NCAccountSettingsView.swift in Sources */, F702F30125EE5D2C008F8E80 /* NYMnemonic.m in Sources */, AF93474E27E3F212002537EE /* NCShareNewUserAddComment.swift in Sources */, F7C30DFD291BD0B80017149B /* NCNetworkingE2EEDelete.swift in Sources */, - F77E8C232E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift in Sources */, + B5E2E6F02DAE6E3F00AB2EDD /* ShareDownloadLimitNetwork.swift in Sources */, F76882302C0DD1E7001CF441 /* NCFileNameModel.swift in Sources */, F7CF06882E1127460063AD04 /* NCManageDatabase+Metadata+Create.swift in Sources */, F72FD3B5297ED49A00075D28 /* NCManageDatabase+E2EE.swift in Sources */, @@ -4880,7 +5789,6 @@ AF93471227E2341B002537EE /* NCShare+Menu.swift in Sources */, F7EFA47825ADBA500083159A /* NCViewerProviderContextMenu.swift in Sources */, F755BD9B20594AC7008C5FBB /* NCService.swift in Sources */, - F376A3742E5CC6030067EE25 /* ContextMenuActions.swift in Sources */, F7E8A391295DC5E0006CB2D0 /* View+Extension.swift in Sources */, F79B869B265E19D40085C0E0 /* NSMutableAttributedString+Extension.swift in Sources */, F7B7504B2397D38F004E13EC /* UIImage+Extension.swift in Sources */, @@ -4890,18 +5798,19 @@ F76D364628A4F8BF00214537 /* NCActivityIndicator.swift in Sources */, F3A047992BD2668800658E7B /* NCAssistantModel.swift in Sources */, F76882322C0DD1E7001CF441 /* NCAutoUploadView.swift in Sources */, - F36E64F72B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBarDelegate.swift in Sources */, + F36E64F72B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBar.swift in Sources */, F79A65C62191D95E00FF6DCC /* NCSelect.swift in Sources */, F75D19E325EFE09000D74598 /* NCTrash+Menu.swift in Sources */, F70CAE3A1F8CF31A008125FD /* NCEndToEndEncryption.m in Sources */, AA8D316E2D4123B200FE2775 /* NCShareDownloadLimitTableViewControllerDelegate.swift in Sources */, - F36C514F2E89393C0097E5F7 /* UIView+BlurVibrancy.swift in Sources */, AA8D316F2D4123B200FE2775 /* NCShareDownloadLimitTableViewController.swift in Sources */, AA8D31702D4123B200FE2775 /* DownloadLimitViewModel.swift in Sources */, AA8D31712D4123B200FE2775 /* NCShareDownloadLimitViewController.swift in Sources */, AF93471B27E2361E002537EE /* NCShareAdvancePermission.swift in Sources */, F77BC3ED293E528A005F2B08 /* NCConfigServer.swift in Sources */, F7A560422AE1593700BE8FD6 /* NCOperationSaveLivePhoto.swift in Sources */, + B5E2E6DF2DAE573B00AB2EDD /* NCFilePermissionCell.swift in Sources */, + B5E2E6E02DAE573B00AB2EDD /* NCFilePermissionEditCell.swift in Sources */, F7D1C4AC2C9484FD00EC6D44 /* NCMedia+CollectionViewDataSourcePrefetching.swift in Sources */, F7D368DF2DAFE19E0037E7C6 /* NCActivityNavigationController.swift in Sources */, F7A03E332D426115007AA677 /* NCMoreNavigationController.swift in Sources */, @@ -4911,7 +5820,6 @@ F749B651297B0F2400087535 /* NCManageDatabase+Avatar.swift in Sources */, F7FAFD3A28BFA948000777FE /* NCNotification+Menu.swift in Sources */, F74C0436253F1CDC009762AB /* NCShares.swift in Sources */, - F79699E72E689F68000EC82A /* NCMediaNavigationController.swift in Sources */, F7AC1CB028AB94490032D99F /* Array+Extension.swift in Sources */, F7AE00F5230D5F9E007ACF8A /* NCLoginProvider.swift in Sources */, F707C26521A2DC5200F6181E /* NCStoreReview.swift in Sources */, @@ -4923,19 +5831,22 @@ F343A4B32A1E01FF00DDA874 /* PHAsset+Extension.swift in Sources */, F70968A424212C4E00ED60E5 /* NCLivePhoto.swift in Sources */, F7C30DFA291BCF790017149B /* NCNetworkingE2EECreateFolder.swift in Sources */, + B5BEBDDC2E93B2450002C9E5 /* NCCreateFormUploadDocuments.swift in Sources */, + B5BEBDDD2E93B2450002C9E5 /* TextTableViewCell.swift in Sources */, + B5BEBDDE2E93B2450002C9E5 /* NCCreateFormUploadVoiceNote.swift in Sources */, F722133B2D40EF9D002F7438 /* NCFilesNavigationController.swift in Sources */, F7BC288026663F85004D46C5 /* NCViewCertificateDetails.swift in Sources */, F78B87E92B62550800C65ADC /* NCMediaDownloadThumbnail.swift in Sources */, D5B6AA7827200C7200D49C24 /* NCActivityTableViewCell.swift in Sources */, F745B253222D88AE00346520 /* NCLoginQRCode.swift in Sources */, - F7FDFF6B2E437E55000D7688 /* NCAccountRequest.swift in Sources */, - F7FDFF6C2E437E55000D7688 /* NCShareAccounts.swift in Sources */, - F7FDFF6D2E437E55000D7688 /* NCAccountSettingsModel.swift in Sources */, - F7FDFF6E2E437E55000D7688 /* NCAccountSettingsView.swift in Sources */, - F7FDFF6F2E437E55000D7688 /* NCAccount.swift in Sources */, F769454822E9F20D000A798A /* NCShareNetworking.swift in Sources */, + F7AEEAA82C11DBFD00011412 /* NCAccountSettingsModel.swift in Sources */, F749B64A297B0CBB00087535 /* NCManageDatabase+Share.swift in Sources */, F7C9555521F0C5470024296E /* NCActivity.swift in Sources */, + B5BEBDA32E93AF010002C9E5 /* AppUtility.swift in Sources */, + B5BEBDA42E93AF010002C9E5 /* AdjustHelper.m in Sources */, + B5BEBDA52E93AF010002C9E5 /* TealiumHelper.swift in Sources */, + B5BEBDA62E93AF010002C9E5 /* NCEmptyDataSet.swift in Sources */, F7725A60251F33BB00D125E0 /* NCFiles.swift in Sources */, F3BB46522A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift in Sources */, F704B5E52430AA8000632F5F /* NCCreateFormUploadConflict.swift in Sources */, @@ -4948,25 +5859,37 @@ F76882232C0DD1E7001CF441 /* NCCapabilitiesModel.swift in Sources */, F7E2B64F2DDCC5C30075B4D0 /* NCMedia+TransferDelegate.swift in Sources */, F7D68FCC28CB9051009139F3 /* NCManageDatabase+DashboardWidget.swift in Sources */, + B52FAED52DA8F616001AB1BD /* NCSelectableNavigationView.swift in Sources */, F76882292C0DD1E7001CF441 /* NCManageE2EEModel.swift in Sources */, F799DF8B2C4B84EB003410B5 /* NCCollectionViewCommon+EndToEndInitialize.swift in Sources */, AA8E041D2D300FDE00E7E89C /* NCShareNetworkingDelegate.swift in Sources */, F78E2D6529AF02DB0024D4F3 /* Database.swift in Sources */, F70CEF5623E9C7E50007035B /* UIColor+Extension.swift in Sources */, + B52FAEA42DA8EE60001AB1BD /* NCManageAutoUploadFileName.swift in Sources */, F76882242C0DD1E7001CF441 /* NCSettingsAdvancedView.swift in Sources */, F785129C2D7989B30087DDD0 /* NCNetworking+TermsOfService.swift in Sources */, + B5BEBDF12E93BDB40002C9E5 /* FolderPathCustomCell.swift in Sources */, + B5BEBDF22E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift in Sources */, F77C3F5B2D9BF8CD00F3C471 /* UITabBar+Extension.swift in Sources */, F7D7A76E2DCDD437003D2007 /* NCManageDatabase+AutoUpload.swift in Sources */, - F7F563042E15762B00631A11 /* MigrationMultiDomains.swift in Sources */, F75CA1472962F13700B01130 /* NCHUDView.swift in Sources */, F77BB748289985270090FC19 /* UITabBarController+Extension.swift in Sources */, + B5BEBD982E93AED80002C9E5 /* AppUpdater.swift in Sources */, F752BA052E58C05200616A26 /* Maintenance.swift in Sources */, + B529E4082E8D1C3E006D9131 /* NCUploadAssets.swift in Sources */, F763D29D2A249C4500A3C901 /* NCManageDatabase+Capabilities.swift in Sources */, F76882252C0DD1E7001CF441 /* NCSettingsAdvancedModel.swift in Sources */, + B54315302DA647A400981E7E /* NCLoginWeb.swift in Sources */, F7C7B489245EBA4100D93E60 /* NCViewerQuickLook.swift in Sources */, + B5BEBD892E93AEA30002C9E5 /* AnalyticsService.swift in Sources */, + B5BEBD8A2E93AEA30002C9E5 /* MoEngageAnalytics.swift in Sources */, + B5BEBD8B2E93AEA30002C9E5 /* AnalyticsHelper.swift in Sources */, + B5D45E6E2DA510E000773929 /* NCRenameFile.swift in Sources */, F758B45E212C569D00515F55 /* NCScanCell.swift in Sources */, F78B87E72B62527100C65ADC /* NCMediaDataSource.swift in Sources */, + B52FAEAC2DA8EF2C001AB1BD /* NCCreateFormUploadScanDocument.swift in Sources */, F76882272C0DD1E7001CF441 /* NCManageE2EEView.swift in Sources */, + B5C9801A2DACD56C0041B146 /* NCMedia+Menu.swift in Sources */, F7864ACC2A78FE73004870E0 /* NCManageDatabase+LocalFile.swift in Sources */, F7327E302B73A86700A462C7 /* NCNetworking+WebDAV.swift in Sources */, F79FFB262A97C24A0055EEA4 /* NCNetworkingE2EEMarkFolder.swift in Sources */, @@ -4983,6 +5906,7 @@ AF2D7C7E2742559100ADF566 /* NCShareUserCell.swift in Sources */, F74DE14325135B6800917068 /* NCTransfers.swift in Sources */, AF4BF614275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */, + B529E40D2E8D1F8B006D9131 /* NCManageE2EE.swift in Sources */, F3E173C02C9B1067006D177A /* AwakeMode.swift in Sources */, F711A4DC2AF92CAE00095DD8 /* NCUtility+Date.swift in Sources */, AF4BF61E27562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */, @@ -4995,23 +5919,21 @@ files = ( F78A10C129322E8A008499B8 /* NCManageDatabase+Directory.swift in Sources */, F73EF7C12B02250B0087E6E9 /* NCManageDatabase+GPS.swift in Sources */, - F7F1FB9D2E27CE7200C79E20 /* NCNetworking.swift in Sources */, F343A4BD2A1E734600DDA874 /* Optional+Extension.swift in Sources */, F7A8D73528F17E16008BBE1C /* NCManageDatabase.swift in Sources */, - F3F442F02DDE2A7700FD701F /* NCMetadataPermissions.swift in Sources */, - F7DB7DEB2E81731B0017AF90 /* NCStorageEstimator.swift in Sources */, F7A8D74428F1827B008BBE1C /* ThreadSafeDictionary.swift in Sources */, F7C9739528F17131002C43E2 /* IntentHandler.swift in Sources */, F7A8D73D28F181D3008BBE1C /* NCUtilityFileSystem.swift in Sources */, + B5BEBD802E93AEA30002C9E5 /* AnalyticsService.swift in Sources */, + B5BEBD812E93AEA30002C9E5 /* MoEngageAnalytics.swift in Sources */, + B5BEBD822E93AEA30002C9E5 /* AnalyticsHelper.swift in Sources */, F73EF7E12B02266D0087E6E9 /* NCManageDatabase+Trash.swift in Sources */, F7C9B91F2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */, F75DD767290ABB25002EB562 /* Intent.intentdefinition in Sources */, - F72437812C10B92500C7C68D /* NCSharePermissions.swift in Sources */, + F72437812C10B92500C7C68D /* NCPermissions.swift in Sources */, F39170A92CB82024006127BC /* FileAutoRenamer+Extensions.swift in Sources */, F749B64C297B0CBB00087535 /* NCManageDatabase+Share.swift in Sources */, F7A8D73F28F181EF008BBE1C /* NCGlobal.swift in Sources */, - F7F1FBA02E27CFBC00C79E20 /* NCContentPresenter.swift in Sources */, - F7F563062E15762B00631A11 /* MigrationMultiDomains.swift in Sources */, F74B6D972A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */, F7C687EB2D22BDE5004757BC /* NCManageDatabase+RecommendedFiles.swift in Sources */, F749B653297B0F2400087535 /* NCManageDatabase+Avatar.swift in Sources */, @@ -5019,14 +5941,17 @@ F763D29F2A249C4500A3C901 /* NCManageDatabase+Capabilities.swift in Sources */, F7A8D74328F1826F008BBE1C /* String+Extension.swift in Sources */, F73EF7A32B021FAC0087E6E9 /* NCLivePhoto.swift in Sources */, + B5BEBD9A2E93AED80002C9E5 /* AppUpdater.swift in Sources */, F7A8D73728F17E1E008BBE1C /* NCManageDatabase+Account.swift in Sources */, F7817CFA29801A3500FFBC65 /* Data+Extension.swift in Sources */, - F77E8C202E79717D00EAE68F /* NCManageDatabase+LivePhoto.swift in Sources */, F7BF9D842934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */, F73EF7A92B0223900087E6E9 /* NCManageDatabase+Comments.swift in Sources */, + F7CF06812E0FF3990063AD04 /* NCAppStateManager.swift in Sources */, F7A8D73C28F181BC008BBE1C /* NCBrand.swift in Sources */, F711A4DE2AF92CAE00095DD8 /* NCUtility+Date.swift in Sources */, - F768823B2C0DD231001CF441 /* NCPreferences.swift in Sources */, + F768823B2C0DD231001CF441 /* NCKeychain.swift in Sources */, + B5BEBDE92E93BDB40002C9E5 /* FolderPathCustomCell.swift in Sources */, + B5BEBDEA2E93BDB40002C9E5 /* NCCreateDocumentCustomTextField.swift in Sources */, AA8D31532D41052300FE2775 /* NCManageDatabase+DownloadLimit.swift in Sources */, F7A8D74228F18261008BBE1C /* NCUtility.swift in Sources */, F7A8D73A28F17E28008BBE1C /* NCManageDatabase+Video.swift in Sources */, @@ -5046,6 +5971,10 @@ F73EF7D12B0225BA0087E6E9 /* NCManageDatabase+Tag.swift in Sources */, F71433E52C778FFA00E20B5A /* NotificationCenter+MainThread.swift in Sources */, F73EF7B92B0224AB0087E6E9 /* NCManageDatabase+ExternalSites.swift in Sources */, + B5BEBDBC2E93AF010002C9E5 /* AppUtility.swift in Sources */, + B5BEBDBD2E93AF010002C9E5 /* AdjustHelper.m in Sources */, + B5BEBDBE2E93AF010002C9E5 /* TealiumHelper.swift in Sources */, + B5BEBDBF2E93AF010002C9E5 /* NCEmptyDataSet.swift in Sources */, F71F6D092B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */, F33EE6F42BF4C9B200CA1A51 /* PKCS12.swift in Sources */, F33918C62C7CD8F2002D9AA1 /* FileNameValidator+Extensions.swift in Sources */, @@ -5348,9 +6277,8 @@ EXTENSION_NOTIFICATION_SERVICE, ); INFOPLIST_FILE = "$(SRCROOT)/Brand/Notification_Service_Extension.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; OTHER_LDFLAGS = ""; - PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.Notification-Service-Extension"; + PRODUCT_BUNDLE_IDENTIFIER = "de.magentacloud.next.dev2.client.Notification-Service-Extension"; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; @@ -5373,9 +6301,8 @@ EXTENSION_NOTIFICATION_SERVICE, ); INFOPLIST_FILE = "$(SRCROOT)/Brand/Notification_Service_Extension.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; OTHER_LDFLAGS = ""; - PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.Notification-Service-Extension"; + PRODUCT_BUNDLE_IDENTIFIER = "de.magentacloud.next.dev2.client.Notification-Service-Extension"; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; @@ -5633,11 +6560,10 @@ ); INFOPLIST_FILE = "$(SRCROOT)/Brand/File_Provider_Extension_UI.plist"; INFOPLIST_KEY_CFBundleDisplayName = "File Provider Extension UI"; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_LDFLAGS = ""; - PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.File-Provider-Extension-UI"; + PRODUCT_BUNDLE_IDENTIFIER = "de.magentacloud.next.dev2.client.File-Provider-Extension-UI"; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; @@ -5660,11 +6586,10 @@ ); INFOPLIST_FILE = "$(SRCROOT)/Brand/File_Provider_Extension_UI.plist"; INFOPLIST_KEY_CFBundleDisplayName = "File Provider Extension UI"; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; OTHER_LDFLAGS = ""; - PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.File-Provider-Extension-UI"; + PRODUCT_BUNDLE_IDENTIFIER = "de.magentacloud.next.dev2.client.File-Provider-Extension-UI"; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; @@ -5686,9 +6611,8 @@ EXTENSION_SHARE, ); INFOPLIST_FILE = "$(SRCROOT)/Brand/Share.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; OTHER_LDFLAGS = ""; - PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.Share; + PRODUCT_BUNDLE_IDENTIFIER = de.magentacloud.next.dev2.client.Share; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; @@ -5711,9 +6635,8 @@ EXTENSION_SHARE, ); INFOPLIST_FILE = "$(SRCROOT)/Brand/Share.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; OTHER_LDFLAGS = ""; - PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.Share; + PRODUCT_BUNDLE_IDENTIFIER = de.magentacloud.next.dev2.client.Share; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; @@ -5743,11 +6666,10 @@ GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "$(SRCROOT)/Brand/Widget.plist"; INFOPLIST_KEY_CFBundleDisplayName = Nextcloud; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_LDFLAGS = ""; - PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.Widget; + PRODUCT_BUNDLE_IDENTIFIER = de.magentacloud.next.dev2.client.Widget; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; @@ -5778,11 +6700,10 @@ GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "$(SRCROOT)/Brand/Widget.plist"; INFOPLIST_KEY_CFBundleDisplayName = Nextcloud; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; OTHER_LDFLAGS = ""; - PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.Widget; + PRODUCT_BUNDLE_IDENTIFIER = de.magentacloud.next.dev2.client.Widget; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; @@ -5807,9 +6728,8 @@ EXTENSION_FILE_PROVIDER_EXTENSION, ); INFOPLIST_FILE = "$(SRCROOT)/Brand/File_Provider_Extension.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; OTHER_LDFLAGS = ""; - PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.File-Provider-Extension"; + PRODUCT_BUNDLE_IDENTIFIER = "de.magentacloud.next.dev2.client.File-Provider-Extension"; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; @@ -5831,9 +6751,8 @@ EXTENSION_FILE_PROVIDER_EXTENSION, ); INFOPLIST_FILE = "$(SRCROOT)/Brand/File_Provider_Extension.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; OTHER_LDFLAGS = ""; - PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.File-Provider-Extension"; + PRODUCT_BUNDLE_IDENTIFIER = "de.magentacloud.next.dev2.client.File-Provider-Extension"; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; @@ -5853,9 +6772,9 @@ DEVELOPMENT_TEAM = NKUJUXUJ3B; GCC_SYMBOLS_PRIVATE_EXTERN = YES; INFOPLIST_FILE = "$(SRCROOT)/Brand/iOSClient.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; + IPHONEOS_DEPLOYMENT_TARGET = 15; OTHER_LDFLAGS = ""; - PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_BUNDLE_IDENTIFIER = de.magentacloud.next.dev2.client; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; @@ -5876,9 +6795,9 @@ DEVELOPMENT_TEAM = NKUJUXUJ3B; GCC_SYMBOLS_PRIVATE_EXTERN = YES; INFOPLIST_FILE = "$(SRCROOT)/Brand/iOSClient.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; + IPHONEOS_DEPLOYMENT_TARGET = 15; OTHER_LDFLAGS = ""; - PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_BUNDLE_IDENTIFIER = de.magentacloud.next.dev2.client; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; @@ -5914,11 +6833,10 @@ GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "$(SRCROOT)/Brand/WidgetDashboardIntentHandler.plist"; INFOPLIST_KEY_CFBundleDisplayName = WidgetDashboardIntentHandler; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_LDFLAGS = ""; - PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.WidgetDashboardIntentHandler; + PRODUCT_BUNDLE_IDENTIFIER = de.magentacloud.next.dev2.client.WidgetDashboardIntentHandler; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; @@ -5955,11 +6873,10 @@ GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "$(SRCROOT)/Brand/WidgetDashboardIntentHandler.plist"; INFOPLIST_KEY_CFBundleDisplayName = WidgetDashboardIntentHandler; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; OTHER_LDFLAGS = ""; - PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.WidgetDashboardIntentHandler; + PRODUCT_BUNDLE_IDENTIFIER = de.magentacloud.next.dev2.client.WidgetDashboardIntentHandler; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; @@ -5975,7 +6892,6 @@ F7F67BC91A24D27800EE80DA /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ENABLE_MODULES = YES; @@ -6000,7 +6916,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 0; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = NKUJUXUJ3B; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -6012,7 +6928,7 @@ GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", DEBUG, - NC, + CUSTOM_BUILD, ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; @@ -6021,16 +6937,17 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2025 Nextcloud. All rights reserved."; - IPHONEOS_DEPLOYMENT_TARGET = 17.6; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 7.1.8; + MARKETING_VERSION = 7.0.3; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = "-v"; OTHER_LDFLAGS = ""; + SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) NC DEBUG"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -6041,7 +6958,6 @@ F7F67BCA1A24D27800EE80DA /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ENABLE_MODULES = YES; @@ -6066,7 +6982,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = NKUJUXUJ3B; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -6075,7 +6991,7 @@ GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", - NC, + CUSTOM_BUILD, ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; @@ -6084,16 +7000,17 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2025 Nextcloud. All rights reserved."; - IPHONEOS_DEPLOYMENT_TARGET = 17.6; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 7.1.8; + MARKETING_VERSION = 7.0.3; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = "-v"; OTHER_LDFLAGS = ""; + SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) NC"; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; @@ -6244,7 +7161,7 @@ repositoryURL = "https://github.com/firebase/firebase-ios-sdk"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 12.0.0; + minimumVersion = 8.9.0; }; }; F710FC78277B7CFF00AA9FBF /* XCRemoteSwiftPackageReference "realm-swift" */ = { @@ -6252,7 +7169,7 @@ repositoryURL = "https://github.com/realm/realm-swift"; requirement = { kind = exactVersion; - version = 20.0.3; + version = 20.0.2; }; }; F72CD01027A7E92400E59476 /* XCRemoteSwiftPackageReference "JGProgressHUD" */ = { @@ -6273,10 +7190,10 @@ }; F734B06428E75C0100E180D5 /* XCRemoteSwiftPackageReference "TLPhotoPicker" */ = { isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/tilltue/TLPhotoPicker"; + repositoryURL = "https://github.com/marinofaggiana/TLPhotoPicker"; requirement = { - kind = upToNextMajorVersion; - minimumVersion = 2.0.0; + branch = master; + kind = branch; }; }; F73ADD1A265546880069EA0D /* XCRemoteSwiftPackageReference "SwiftEntryKit" */ = { @@ -6284,7 +7201,7 @@ repositoryURL = "https://github.com/huri000/SwiftEntryKit"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 2.0.0; + minimumVersion = 1.2.7; }; }; F753BA91281FD8010015BFB6 /* XCRemoteSwiftPackageReference "EasyTipView" */ = { @@ -6324,7 +7241,7 @@ repositoryURL = "https://github.com/nicklockwood/LRUCache"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 1.0.7; + minimumVersion = 1.0.4; }; }; F76DA961277B760E0082465B /* XCRemoteSwiftPackageReference "Queuer" */ = { @@ -6347,8 +7264,8 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/scenee/FloatingPanel"; requirement = { - kind = upToNextMinorVersion; - minimumVersion = 3.0.0; + kind = exactVersion; + version = 2.8.6; }; }; F77333862927A72100466E35 /* XCRemoteSwiftPackageReference "OpenSSL" */ = { @@ -6356,7 +7273,7 @@ repositoryURL = "https://github.com/krzyzanowskim/OpenSSL"; requirement = { kind = exactVersion; - version = 3.3.3001; + version = 3.3.2000; }; }; F77BC3E9293E5268005F2B08 /* XCRemoteSwiftPackageReference "swifter" */ = { @@ -6371,7 +7288,7 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/nextcloud/NextcloudKit"; requirement = { - branch = main; + branch = 7.0.2; kind = branch; }; }; @@ -6929,31 +7846,6 @@ package = F7ED547A25EEA65400956C55 /* XCRemoteSwiftPackageReference "QRCodeReader" */; productName = QRCodeReader; }; - F7F1FBA72E27D13700C79E20 /* Queuer */ = { - isa = XCSwiftPackageProductDependency; - package = F76DA961277B760E0082465B /* XCRemoteSwiftPackageReference "Queuer" */; - productName = Queuer; - }; - F7F1FBA92E27D14000C79E20 /* SwiftEntryKit */ = { - isa = XCSwiftPackageProductDependency; - package = F73ADD1A265546880069EA0D /* XCRemoteSwiftPackageReference "SwiftEntryKit" */; - productName = SwiftEntryKit; - }; - F7F1FBAB2E27D20400C79E20 /* Queuer */ = { - isa = XCSwiftPackageProductDependency; - package = F76DA961277B760E0082465B /* XCRemoteSwiftPackageReference "Queuer" */; - productName = Queuer; - }; - F7F1FBAD2E27D3A400C79E20 /* SwiftEntryKit */ = { - isa = XCSwiftPackageProductDependency; - package = F73ADD1A265546880069EA0D /* XCRemoteSwiftPackageReference "SwiftEntryKit" */; - productName = SwiftEntryKit; - }; - F7F1FBAF2E27D3A800C79E20 /* Queuer */ = { - isa = XCSwiftPackageProductDependency; - package = F76DA961277B760E0082465B /* XCRemoteSwiftPackageReference "Queuer" */; - productName = Queuer; - }; F7F623B42A5EF4D30022D3D4 /* Gzip */ = { isa = XCSwiftPackageProductDependency; package = F7F623B32A5EF4D30022D3D4 /* XCRemoteSwiftPackageReference "GzipSwift" */; diff --git a/Share/NCShareExtension.swift b/Share/NCShareExtension.swift index f198a10231..2a423690dd 100644 --- a/Share/NCShareExtension.swift +++ b/Share/NCShareExtension.swift @@ -10,7 +10,7 @@ enum NCShareExtensionError: Error { case cancel, fileUpload, noAccount, noFiles, versionMismatch } -class NCShareExtension: UIViewController { +class NCShareExtension: UIViewController, NCEmptyDataSetDelegate { @IBOutlet weak var collectionView: UICollectionView! @IBOutlet weak var tableView: UITableView! @IBOutlet weak var cancelButton: UIBarButtonItem! @@ -31,6 +31,7 @@ class NCShareExtension: UIViewController { var filesName: [String] = [] // ------------------------------------------------------------- + var emptyDataSet: NCEmptyDataSet? let keyLayout = NCGlobal.shared.layoutViewShareExtension var metadataFolder: tableMetadata? var dataSourceTask: URLSessionTask? @@ -39,23 +40,43 @@ class NCShareExtension: UIViewController { let heightCommandView: CGFloat = 170 var autoUploadFileName = "" var autoUploadDirectory = "" + let refreshControl = UIRefreshControl() var progress: CGFloat = 0 var counterUploaded: Int = 0 + var uploadErrors: [tableMetadata] = [] var uploadMetadata: [tableMetadata] = [] + var uploadStarted = false let hud = NCHud() let utilityFileSystem = NCUtilityFileSystem() let utility = NCUtility() let global = NCGlobal.shared var maintenanceMode: Bool = false - + let database = NCManageDatabase.shared + var account: String = "" + var session: NCSession.Session { + if !account.isEmpty, + let tableAccount = self.database.getTableAccount(account: account) { + return NCSession.Session(account: tableAccount.account, urlBase: tableAccount.urlBase, user: tableAccount.user, userId: tableAccount.userId) + } else if let activeTableAccount = self.database.getActiveTableAccount() { + self.account = activeTableAccount.account + return NCSession.Session(account: activeTableAccount.account, urlBase: activeTableAccount.urlBase, user: activeTableAccount.user, userId: activeTableAccount.userId) + } else { + return NCSession.Session(account: "", urlBase: "", user: "", userId: "") + } + } + // MARK: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() - collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") + self.navigationController?.navigationBar.prefersLargeTitles = false collectionView.register(UINib(nibName: "NCListCell", bundle: nil), forCellWithReuseIdentifier: "listCell") collectionView.collectionViewLayout = NCListLayout() + collectionView.refreshControl = refreshControl + refreshControl.tintColor = NCBrandColor.shared.brandText + refreshControl.backgroundColor = .systemBackground + refreshControl.addTarget(self, action: #selector(reloadDatasource), for: .valueChanged) commandView.backgroundColor = .secondarySystemBackground separatorView.backgroundColor = .separator @@ -69,7 +90,7 @@ class NCShareExtension: UIViewController { cancelButton.title = NSLocalizedString("_cancel_", comment: "") createFolderView.layer.cornerRadius = 10 - createFolderImage.image = utility.loadImage(named: "folder.badge.plus", colors: [NCBrandColor.shared.iconImageColor]) + createFolderImage.image = utility.loadImage(named: "folder.badge.plus", colors: [NCBrandColor.shared.iconColor]) createFolderLabel.text = NSLocalizedString("_create_folder_", comment: "") let createFolderGesture = UITapGestureRecognizer(target: self, action: #selector(actionCreateFolder(_:))) createFolderView.addGestureRecognizer(createFolderGesture) @@ -77,8 +98,8 @@ class NCShareExtension: UIViewController { uploadView.layer.cornerRadius = 10 uploadLabel.text = NSLocalizedString("_upload_", comment: "") - uploadLabel.textColor = .systemBlue - let uploadGesture = UITapGestureRecognizer(target: self, action: #selector(actionUpload(_:))) + uploadLabel.textColor = NCBrandColor.shared.customer + let uploadGesture = UITapGestureRecognizer(target: self, action: #selector(actionUpload)) uploadView.addGestureRecognizer(uploadGesture) let versionNextcloudiOS = String(format: NCBrandOptions.shared.textCopyrightNextcloudiOS, utility.getVersionBuild()) @@ -86,6 +107,21 @@ class NCShareExtension: UIViewController { nkLog(start: "Start Share session " + versionNextcloudiOS) + // LOG + let levelLog = NCKeychain().logLevel +// +// NextcloudKit.shared.nkCommonInstance.levelLog = levelLog +// NextcloudKit.shared.nkCommonInstance.pathLog = utilityFileSystem.directoryGroup +// NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Start Share session with level \(levelLog) " + versionNextcloudiOS) + NKLogFileManager.shared.logLevel = NKLogLevel(rawValue: levelLog) ?? .normal + NKLogFileManager.shared.logDirectory = URL(fileURLWithPath: utilityFileSystem.directoryGroup) + NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Start Share session with level \(levelLog) " + versionNextcloudiOS) + +// hud.indicatorView = JGProgressHUDRingIndicatorView() +// if let indicatorView = hud.indicatorView as? JGProgressHUDRingIndicatorView { +// indicatorView.ringWidth = 1.5 +// indicatorView.ringColor = NCBrandColor.shared.brandElement +// } NCBrandColor.shared.createUserColors() NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: nil) { _ in @@ -109,6 +145,9 @@ class NCShareExtension: UIViewController { if let account = NCShareExtensionData.shared.getTblAccoun()?.account { accountRequestChangeAccount(account: account, controller: nil) } + NCImageCache.shared.createImagesCache() + + NotificationCenter.default.addObserver(self, selector: #selector(didCreateFolder(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterCreateFolder), object: nil) } override func viewWillAppear(_ animated: Bool) { @@ -128,6 +167,8 @@ class NCShareExtension: UIViewController { } } + accountRequestChangeAccount(account: account, controller: nil) + guard let inputItems = extensionContext?.inputItems as? [NSExtensionItem] else { cancel(with: .noFiles) return @@ -166,10 +207,26 @@ class NCShareExtension: UIViewController { } } + // MARK: - Empty + + func emptyDataSetView(_ view: NCEmptyView) { + + if self.dataSourceTask?.state == .running { + view.emptyImage.image = UIImage(named: "networkInProgress")?.image(color: .gray, size: UIScreen.main.bounds.width) + view.emptyTitle.text = NSLocalizedString("_request_in_progress_", comment: "") + view.emptyDescription.text = "" + } else { + view.emptyImage.image = UIImage(named: "folder_nmcloud") + view.emptyTitle.text = NSLocalizedString("_files_no_folders_", comment: "") + view.emptyDescription.text = "" + } + } + // MARK: - func cancel(with error: NCShareExtensionError) { // make sure no uploads are continued + uploadStarted = false extensionContext?.cancelRequest(withError: error) } @@ -190,14 +247,15 @@ class NCShareExtension: UIViewController { navigationItem.title = navigationTitle cancelButton.title = NSLocalizedString("_cancel_", comment: "") + cancelButton.tintColor = NCBrandColor.shared.customer // BACK BUTTON let backButton = UIButton(type: .custom) - backButton.setImage(UIImage(named: "back"), for: .normal) - backButton.tintColor = .systemBlue + backButton.setImage(UIImage(named: "back")?.imageColor(NCBrandColor.shared.customer), for: .normal) + backButton.tintColor = NCBrandColor.shared.customer backButton.semanticContentAttribute = .forceLeftToRight backButton.setTitle(" " + NSLocalizedString("_back_", comment: ""), for: .normal) - backButton.setTitleColor(.systemBlue, for: .normal) + backButton.setTitleColor(NCBrandColor.shared.customer, for: .normal) backButton.action(for: .touchUpInside) { _ in while self.serverUrl.last != "/" { self.serverUrl.removeLast() } self.serverUrl.removeLast() @@ -210,35 +268,11 @@ class NCShareExtension: UIViewController { } self.setNavigationBar(navigationTitle: navigationTitle) } - - let image = utility.loadUserImage(for: tblAccount.user, displayName: tblAccount.displayName, urlBase: tblAccount.urlBase) - let profileButton = UIButton(type: .custom) - profileButton.setImage(image, for: .normal) - - if serverUrl == utilityFileSystem.getHomeServer(session: session) { - var title = " " - if !tblAccount.alias.isEmpty { - title += tblAccount.alias - } else { - title += tblAccount.displayName - } - - profileButton.setTitle(title, for: .normal) - profileButton.setTitleColor(.systemBlue, for: .normal) - } - - profileButton.semanticContentAttribute = .forceLeftToRight - profileButton.sizeToFit() - profileButton.action(for: .touchUpInside) { _ in - self.showAccountPicker() - } - var navItems = [UIBarButtonItem(customView: profileButton)] if serverUrl != utilityFileSystem.getHomeServer(session: session) { - let space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil) - space.width = 20 - navItems.append(contentsOf: [UIBarButtonItem(customView: backButton), space]) + navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton) + } else { + navigationItem.leftBarButtonItem = nil } - navigationItem.setLeftBarButtonItems(navItems, animated: true) } func setCommandView() { @@ -253,6 +287,10 @@ class NCShareExtension: UIViewController { self.tableView.isScrollEnabled = false } uploadLabel.text = NSLocalizedString("_upload_", comment: "") + " \(filesName.count) " + NSLocalizedString("_files_", comment: "") + + // Empty + emptyDataSet = NCEmptyDataSet(view: collectionView, offset: -50 * counter, delegate: self) + self.tableView.reloadData() } @@ -450,6 +488,16 @@ extension NCShareExtension { } } +extension NCShareExtension: uploadE2EEDelegate { + func start() { + self.hud.progress(0) + } + + func uploadE2EEProgress(_ totalBytesExpected: Int64, _ totalBytes: Int64, _ fractionCompleted: Double) { + self.hud.progress(fractionCompleted) + } +} + extension NCShareExtension: NCPasscodeDelegate { func passcodeReset(_ passcodeViewController: TOPasscodeViewController) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { diff --git a/Tests/Common/BaseXCTestCase.swift b/Tests/Common/BaseXCTestCase.swift new file mode 100644 index 0000000000..5c03bc5384 --- /dev/null +++ b/Tests/Common/BaseXCTestCase.swift @@ -0,0 +1,38 @@ +// +// BaseXCTestCase.swift +// Nextcloud +// +// Created by Milen on 20.03.24. +// Copyright © 2024 Marino Faggiana. All rights reserved. +// + +import XCTest +import Foundation +import UIKit +import Alamofire +import NextcloudKit +@testable import Nextcloud + +class BaseXCTestCase: XCTestCase { + var appToken = "" + + func setupAppToken() { + let expectation = expectation(description: "Should get app token") + + NextcloudKit.shared.getAppPassword(url: TestConstants.server, user: TestConstants.username, password: TestConstants.password) { token, _, error in + XCTAssertEqual(error.errorCode, 0) + XCTAssertNotNil(token) + + guard let token else { return XCTFail() } + + self.appToken = token + expectation.fulfill() + } + + waitForExpectations(timeout: TestConstants.timeoutLong) + } + + override func setUpWithError() throws { + setupAppToken() + } +} diff --git a/Tests/Common/TestConstants.swift b/Tests/Common/TestConstants.swift new file mode 100644 index 0000000000..5022e70803 --- /dev/null +++ b/Tests/Common/TestConstants.swift @@ -0,0 +1,53 @@ +// +// Copyright (c) 2023 Marcel Müller +// +// Author Marcel Müller +// +// GNU GPL version 3 or any later version +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +import Foundation +import UIKit + +/// +/// Immutable test configuration. +/// +enum TestConstants { + /// + /// The default number of seconds to wait for the appearance of user interface controls during user interface tests. + /// + static let controlExistenceTimeout: Double = 10 + + /// + /// The full base URL for the server to run against. + /// + static let server = "http://localhost:8080" + + /// + /// Default user name to sign in with. + /// + static let username = "admin" + + /// + /// Password of the default user name to sign in with. + /// + static let password = "admin" + + /// + /// Account identifier of the default user to test with. + /// + static let account = "\(username) \(server)" +} diff --git a/Tests/NextcloudIntegrationTests/BaseIntegrationXCTestCase.swift b/Tests/NextcloudIntegrationTests/BaseIntegrationXCTestCase.swift new file mode 100644 index 0000000000..703aa37f07 --- /dev/null +++ b/Tests/NextcloudIntegrationTests/BaseIntegrationXCTestCase.swift @@ -0,0 +1,29 @@ +// +// BaseIntegrationXCTestCase.swift +// +// +// Created by Milen Pivchev on 20.06.23. +// Copyright © 2023 Milen Pivchev. All rights reserved. +// +// Author: Milen Pivchev +// 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 . +// + +class BaseIntegrationXCTestCase: BaseXCTestCase { + var randomInt: Int { + get { + return Int.random(in: 1000...Int.max) + } + } +} diff --git a/Tests/NextcloudIntegrationTests/FilesIntegrationTests.swift b/Tests/NextcloudIntegrationTests/FilesIntegrationTests.swift new file mode 100644 index 0000000000..c1bcbca235 --- /dev/null +++ b/Tests/NextcloudIntegrationTests/FilesIntegrationTests.swift @@ -0,0 +1,94 @@ +// +// NextcloudIntegrationTests.swift +// NextcloudIntegrationTests +// +// Created by Milen Pivchev on 5/19/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +import XCTest +import NextcloudKit +@testable import Nextcloud + +final class FilesIntegrationTests: BaseIntegrationXCTestCase { + + override func setUp() { + NCAccount().deleteAllAccounts() + } + +// func test_createReadDeleteFolder_withProperParams_shouldCreateReadDeleteFolder() throws { +// let expectation = expectation(description: "Should finish last callback") +// +// let folderName = "TestFolder\(randomInt)" +// let serverUrl = "\(TestConstants.server)/remote.php/dav/files/\(TestConstants.username)" +// let serverUrlFileName = "\(serverUrl)/\(folderName)" +// +// NCSession.shared.appendSession(account: TestConstants.account, urlBase: TestConstants.server, user: TestConstants.username, userId: TestConstants.username) +// let session = NCSession.shared.getSession(account: TestConstants.account) +// +// NextcloudKit.shared.setup(delegate: NCNetworking.shared) +// NextcloudKit.shared.appendSession(account: TestConstants.account, urlBase: TestConstants.server, user: TestConstants.username, userId: TestConstants.username, password: appToken, userAgent: userAgent, nextcloudVersion: 0, groupIdentifier: NCBrandOptions.shared.capabilitiesGroup) +// +// // Test creating folder +// NCNetworking.shared.createFolder(fileName: folderName, serverUrl: serverUrl, overwrite: true, withPush: true, metadata: nil, sceneIdentifier: nil, session: session ) { error in +// +// XCTAssertEqual(NKError.success.errorCode, error.errorCode) +// XCTAssertEqual(NKError.success.errorDescription, error.errorDescription) +// +// Thread.sleep(forTimeInterval: 1) +// +// // Test reading folder, should exist +// NCNetworking.shared.readFolder(serverUrl: serverUrlFileName, account: TestConstants.username, checkResponseDataChanged: false, queue: .main) { account, metadataFolder, _, _, _ in +// +// XCTAssertEqual(TestConstants.account, account) +// XCTAssertEqual(NKError.success.errorCode, error.errorCode) +// XCTAssertEqual(NKError.success.errorDescription, error.errorDescription) +// XCTAssertEqual(metadataFolder?.fileName, folderName) +// +// // Check Realm directory, should exist +// let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "serverUrl == %@", serverUrlFileName)) +// XCTAssertNotNil(directory) +// +// Thread.sleep(forTimeInterval: 1) +// +// Task { +// // Test deleting folder +// await _ = NCNetworking.shared.deleteFileOrFolder(serverUrlFileName: serverUrlFileName, account: TestConstants.account) +// +// XCTAssertEqual(NKError.success.errorCode, error.errorCode) +// XCTAssertEqual(NKError.success.errorDescription, error.errorDescription) +// +// try await Task.sleep(for: .seconds(1)) +// +// // Test reading folder, should NOT exist +// NCNetworking.shared.readFolder(serverUrl: serverUrlFileName, account: TestConstants.username, checkResponseDataChanged: false, queue: .main) { account, metadataFolder, _, _, _ in +// +// defer { expectation.fulfill() } +// +// XCTAssertEqual(0, error.errorCode) +// XCTAssertNil(metadataFolder?.fileName) +// +// // Check Realm directory, should NOT exist +// let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "serverUrl == %@", serverUrlFileName)) +// XCTAssertNil(directory) +// } +// } +// } +// } +// +// waitForExpectations(timeout: TestConstants.timeoutLong) +// } +} diff --git a/Tests/NextcloudIntegrationTests/Placeholder.swift b/Tests/NextcloudIntegrationTests/Placeholder.swift deleted file mode 100644 index 6cc0aa6c4b..0000000000 --- a/Tests/NextcloudIntegrationTests/Placeholder.swift +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-FileCopyrightText: Nextcloud GmbH -// SPDX-FileCopyrightText: 2025 Iva Horn -// SPDX-License-Identifier: GPL-3.0-or-later - -// There are no unit tests yet. -// This is an empty placeholder file. -// The compiler requires at least an empty file for every target. diff --git a/Tests/NextcloudUnitTests/AssetUploadTest.swift b/Tests/NextcloudUnitTests/AssetUploadTest.swift new file mode 100644 index 0000000000..72f541042b --- /dev/null +++ b/Tests/NextcloudUnitTests/AssetUploadTest.swift @@ -0,0 +1,36 @@ +// +// AssetUploadTest.swift +// NextcloudTests +// +// Created by A200020526 on 12/06/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +import XCTest + +final class AssetUploadTest: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/Tests/NextcloudUnitTests/AudioUploadTests.swift b/Tests/NextcloudUnitTests/AudioUploadTests.swift new file mode 100644 index 0000000000..2ea01a8085 --- /dev/null +++ b/Tests/NextcloudUnitTests/AudioUploadTests.swift @@ -0,0 +1,52 @@ +// +// AudioUploadTests.swift +// NextcloudTests +// +// Created by A200020526 on 13/06/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +import XCTest +@testable import Nextcloud + +final class AudioUploadTests: XCTestCase { + var viewController:NCAudioRecorderViewController? + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + // Step 1. Create an instance of UIStoryboard + let viewController = UIStoryboard(name: "NCAudioRecorderViewController", bundle: nil).instantiateInitialViewController() as? NCAudioRecorderViewController + // Step 3. Make the viewDidLoad() execute. + viewController?.loadViewIfNeeded() + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + viewController = nil + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + + func testAudioMeterUpdateAfterDb(){ + viewController?.audioMeterDidUpdate(0.5) + XCTAssertNotNil(!(viewController?.durationLabel.text?.isEmpty ?? false)) + } + + func testStartRecorder(){ + viewController?.startStop() + XCTAssertEqual(viewController?.recording.state, nil, "Test start audio recorder") + } +} diff --git a/Tests/NextcloudUnitTests/CollaboraTestCase.swift b/Tests/NextcloudUnitTests/CollaboraTestCase.swift new file mode 100644 index 0000000000..51b3ecce1f --- /dev/null +++ b/Tests/NextcloudUnitTests/CollaboraTestCase.swift @@ -0,0 +1,142 @@ +// +// CollaboraTestCase.swift +// NextcloudTests +// +// Created by A200073704 on 06/05/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +@testable import Nextcloud +import XCTest +import NextcloudKit + +class CollaboraTestCase: XCTestCase { + + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testCollaboraDocumentIsPresent() { + + var viewForDocument: NCMenuAction? + + if let image = UIImage(named: "create_file_document") { + viewForDocument = NCMenuAction(title: NSLocalizedString("_create_new_document_", comment: ""), icon: image, action: { _ in + guard let navigationController = UIStoryboard(name: "NCCreateFormUploadDocuments", bundle: nil).instantiateInitialViewController() as? UINavigationController else { + return + } + + let viewController = navigationController.topViewController as? NCCreateFormUploadDocuments + viewController?.titleForm = NSLocalizedString("_create_new_document_", comment: "") + }) + } + + XCTAssertNotNil(viewForDocument) + + } + + func testCollaboraPresentationIsPresent() { + + var viewForPresentation: NCMenuAction? + + if let image = UIImage(named: "create_file_ppt") { + viewForPresentation = NCMenuAction(title: NSLocalizedString("_create_new_presentation_", comment: ""), icon: image, action: { _ in + guard let navigationController = UIStoryboard(name: "NCCreateFormUploadDocuments", bundle: nil).instantiateInitialViewController() as? UINavigationController else { + return + } + + let viewController = navigationController.topViewController as? NCCreateFormUploadDocuments + viewController?.titleForm = NSLocalizedString("_create_new_presentation_", comment: "") + }) + } + + XCTAssertNotNil(viewForPresentation) + + } + + func testCollaboraSpreadsheetIsPresent() { + + var viewForSpreadsheet: NCMenuAction? + + if let image = UIImage(named: "create_file_xls") { + viewForSpreadsheet = NCMenuAction(title: NSLocalizedString("_create_new_spreadsheet_", comment: ""), icon: image, action: { _ in + guard let navigationController = UIStoryboard(name: "NCCreateFormUploadDocuments", bundle: nil).instantiateInitialViewController() as? UINavigationController else { + return + } + + let viewController = navigationController.topViewController as? NCCreateFormUploadDocuments + viewController?.titleForm = NSLocalizedString("_create_new_spreadsheet_", comment: "") + }) + } + + XCTAssertNotNil(viewForSpreadsheet) + + } + + func testTextDocumentIsPresent() { + + var textMenu: NCMenuAction? + + if let image = UIImage(named: "file_txt_menu") { + textMenu = NCMenuAction(title: NSLocalizedString("_create_nextcloudtext_document_", comment: ""), icon: image, action: { _ in + guard let navigationController = UIStoryboard(name: "NCCreateFormUploadDocuments", bundle: nil).instantiateInitialViewController() as? UINavigationController else { + return + } + + let viewController = navigationController.topViewController as? NCCreateFormUploadDocuments + viewController?.titleForm = NSLocalizedString("_create_nextcloudtext_document_", comment: "") + }) + } + + XCTAssertNotNil(textMenu) + + } + + func testTextDocumentAction() { + + let text = NCGlobal.shared.actionTextDocument + XCTAssertNotNil(text, "Text Editor Should be opened") + } + + func testTextFieldIsPresent() { + + let storyboard = UIStoryboard(name: "NCCreateFormUploadDocuments", bundle: nil) + guard let viewController = storyboard.instantiateInitialViewController() as? NCCreateFormUploadDocuments else { + return + } + + // Verify that a text field is present in the view controller + let textFields = viewController.view.subviews.filter { $0 is UITextField } + XCTAssertFalse(textFields.isEmpty, "No text field found in NCCreateFormUploadDocuments") + } + + func testSavePathFolder() { + + let viewController = NCCreateFormUploadDocuments() + + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + + var row : XLFormRowDescriptor + + // the section with the title "Folder Destination" + + row = XLFormRowDescriptor(tag: "ButtonDestinationFolder", rowType: "kNMCFolderCustomCellType", title: "") + row.action.formSelector = #selector(viewController.changeDestinationFolder(_:)) + + // Verify that section was found + XCTAssertNotNil(row, "Expected save path section to exist in form.") + + } + + + + + + +} diff --git a/Tests/NextcloudUnitTests/E2EETests.swift b/Tests/NextcloudUnitTests/E2EETests.swift new file mode 100644 index 0000000000..bee1c1aa3f --- /dev/null +++ b/Tests/NextcloudUnitTests/E2EETests.swift @@ -0,0 +1,90 @@ +// +// E2EETests.swift +// NextcloudTests +// +// Created by A200020526 on 26/05/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +@testable import Nextcloud +import XCTest +import TOPasscodeViewController + +final class E2EETests: XCTestCase { + + var manageE2EE: NCManageE2EE! + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + manageE2EE = NCManageE2EE() + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + manageE2EE = nil + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + + // MARK: - Initialization + + func testInitialization() { + XCTAssertTrue(manageE2EE.endToEndInitialize.delegate === manageE2EE) + XCTAssertFalse(manageE2EE.isEndToEndEnabled) + XCTAssertEqual(manageE2EE.statusOfService, NSLocalizedString("_status_in_progress_", comment: "")) + } + + // MARK: - Delegate + + func testEndToEndInitializeSuccess() { + manageE2EE.endToEndInitializeSuccess() + XCTAssertTrue(manageE2EE.isEndToEndEnabled) + } + + // MARK: - Passcode + + func testRequestPasscodeType() { + // TODO: Implement this test case + } + + func testCorrectPasscode_startE2E() { + manageE2EE.passcodeType = "startE2E" + manageE2EE.correctPasscode() + // TODO: Add assertions for the expected behavior after entering the correct passcode for starting E2E + } + + func testCorrectPasscode_readPassphrase() { + manageE2EE.passcodeType = "readPassphrase" + // TODO: Simulate entering the correct passcode and verify the expected behavior + } + + func testCorrectPasscode_removeLocallyEncryption() { + manageE2EE.passcodeType = "removeLocallyEncryption" + // TODO: Simulate entering the correct passcode and verify the expected behavior + } + + func testDidPerformBiometricValidationRequest() { + let passcodeViewController = TOPasscodeViewController(passcodeType: .sixDigits, allowCancel: true) + manageE2EE.didPerformBiometricValidationRequest(in: passcodeViewController) + // TODO: Add assertions for the expected behavior after performing biometric validation + } + + func testDidTapCancel() { + let passcodeViewController = TOPasscodeViewController(passcodeType: .sixDigits, allowCancel: true) + manageE2EE.didTapCancel(in: passcodeViewController) + // TODO: Add assertions for the expected behavior after tapping cancel + } +} diff --git a/Tests/NextcloudUnitTests/MoreTests.swift b/Tests/NextcloudUnitTests/MoreTests.swift new file mode 100644 index 0000000000..0a96912994 --- /dev/null +++ b/Tests/NextcloudUnitTests/MoreTests.swift @@ -0,0 +1,37 @@ +// +// MoreTests.swift +// NextcloudTests +// +// Created by A200020526 on 09/06/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +@testable import Nextcloud +import XCTest + +final class MoreTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/Tests/NextcloudUnitTests/MoveAndCopyTests.swift b/Tests/NextcloudUnitTests/MoveAndCopyTests.swift new file mode 100644 index 0000000000..bd674a472f --- /dev/null +++ b/Tests/NextcloudUnitTests/MoveAndCopyTests.swift @@ -0,0 +1,106 @@ +// +// MoveAndCopyTests.swift +// NextcloudTests +// +// Created by A200073704 on 05/06/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +@testable import Nextcloud +import XCTest +import NextcloudKit + + + class MoveAndCopyTests: XCTestCase { + + var view : NCSelectCommandView? + var viewController : NCSelect? + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + let storyboard = UIStoryboard(name: "NCSelect", bundle: nil) + if let navigationController = storyboard.instantiateInitialViewController() as? UINavigationController { + let viewController = navigationController.topViewController as? NCSelect + + let _ = viewController?.view + viewController?.loadViewIfNeeded() + } + view = NCSelectCommandView() + + } + + override func setUp() { + super.setUp() + let nib = Bundle.main.loadNibNamed("NCSelectCommandViewCopyMove", owner: nil, options: nil) + view = nib?.first as? NCSelectCommandView + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + + viewController = nil + view = nil + + } + + func testCreateFolderButton() { + + let image: Void? = view?.createFolderButton?.setImage(UIImage(named: "addFolder")?.withTintColor(UIColor.label), for: .normal) + + XCTAssertNotNil(image) + } + + func testOverwriteSwitch() { + + let mySwitch = view?.overwriteSwitch + + XCTAssertNotNil(mySwitch) + + } + + func testCopyButton() { + + let copy = view?.copyButton + + XCTAssertNotNil(copy) + } + + + func testOverwriteSwitchAlwaysOn() { + + XCTAssertTrue(view?.overwriteSwitch?.isOn ?? false, "Overwrite Switch should always be on") + } + + func testCopyButtonandMoveButtonCondition() { + + // Disable copy and move + view?.copyButton?.isEnabled = false + view?.moveButton?.isEnabled = false + + // Creating a test item + let item = tableMetadata() + item.serverUrl = "serverUrl" // Set the serverUrl property of the item + + let items: [tableMetadata] = [item] + + // Update the items in the view controller + viewController?.items = items + + // Verify that the copy and move buttons are still disabled + XCTAssertFalse(view?.copyButton?.isEnabled ?? true, "Copy Button should remain disabled when items.first matches the condition") + XCTAssertFalse(view?.moveButton?.isEnabled ?? true, "Move Button should remain disabled when items.first matches the condition") + + // Enable copy and move + view?.copyButton?.isEnabled = true + view?.moveButton?.isEnabled = true + + // Update the items in the view controller + viewController?.items = [] // Empty items + + // Verify that the copyButton is still enabled + XCTAssertTrue(view?.copyButton?.isEnabled ?? false, "Copy Button should remain enabled when items.first doesn't match the condition") + XCTAssertTrue(view?.moveButton?.isEnabled ?? false, "Move Button should remain enabled when items.first doesn't match the condition") + } + +} diff --git a/Tests/NextcloudUnitTests/NCNotificationText.swift b/Tests/NextcloudUnitTests/NCNotificationText.swift new file mode 100644 index 0000000000..1a7e0b2345 --- /dev/null +++ b/Tests/NextcloudUnitTests/NCNotificationText.swift @@ -0,0 +1,85 @@ +// +// NCNotificationText.swift +// NextcloudUnitTests +// +// Created by Amrut Waghmare on 18/10/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +@testable import Nextcloud +import XCTest +import NextcloudKit + +class NCNotificationText: XCTestCase { + var viewController : NCNotification! + + override func setUpWithError() throws { + // Step 1. Create an instance of UIStoryboard + let storyboard = UIStoryboard(name: "NCNotification", bundle: nil) + // Step 2. Instantiate UIViewController with Storyboard ID + viewController = storyboard.instantiateViewController(withIdentifier: "NCNotification.storyboard") as? NCNotification + + // Step 3. Make the viewDidLoad() execute. + viewController.loadViewIfNeeded() + } + + override func tearDownWithError() throws { + viewController = nil + } + + //Test that a cell with the correct reuse identifier is dequeued + func testTableViewCellDequeue() { + let notification = NKNotifications() + viewController.notifications = [notification] + let tableView = UITableView() + tableView.register(NCNotificationCell.self, forCellReuseIdentifier: "Cell") + let indexPath = IndexPath(row: 0, section: 0) + let cell = viewController.tableView(tableView, cellForRowAt: indexPath) as? NCNotificationCell + XCTAssertNotNil(cell) + XCTAssertEqual(cell?.reuseIdentifier, "Cell") + } + + //Test that the cell's icon is set image + func testTableViewCellIcon() { + let notification = NKNotifications() + viewController.notifications = [notification] + let tableView = UITableView() + tableView.register(NCNotificationCell.self, forCellReuseIdentifier: "Cell") + let indexPath = IndexPath(row: 0, section: 0) + let cell = viewController.tableView(tableView, cellForRowAt: indexPath) as? NCNotificationCell + XCTAssertNotNil(cell?.icon.image) + } + + //Test that the cell's primary and secondary buttons are set up correctly + func testTableViewCellButtons() { + let notification = NKNotifications() + notification.actions = Data("[{\"label\":\"OK\",\"primary\":true},{\"label\":\"Cancel\",\"primary\":false}]".utf8) + viewController.notifications = [notification] + let tableView = UITableView() + tableView.register(NCNotificationCell.self, forCellReuseIdentifier: "Cell") + let indexPath = IndexPath(row: 0, section: 0) + let cell = viewController.tableView(tableView, cellForRowAt: indexPath) as? NCNotificationCell + XCTAssertEqual(cell?.primary.title(for: .normal), "OK") + XCTAssertEqual(cell?.secondary.title(for: .normal), "Cancel") + } + + //Test that the cell's date label is set correctly + func testTableViewCellDate() { + let notification = NKNotifications() + notification.date = NSDate() + viewController.notifications = [notification] + let tableView = UITableView() + tableView.register(NCNotificationCell.self, forCellReuseIdentifier: "Cell") + let indexPath = IndexPath(row: 0, section: 0) + let cell = viewController.tableView(tableView, cellForRowAt: indexPath) as? NCNotificationCell + XCTAssertEqual(cell?.date.text, "less than a minute ago") + } + + //Test with a color that is image not nil + func testImageNotNil() { + let color = UIColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 1.0) + let image = UIImage().imageColor(color) + XCTAssertNotNil(image, "Image should not be nil.") + + } +} diff --git a/Tests/NextcloudUnitTests/OnboardingTestCase.swift b/Tests/NextcloudUnitTests/OnboardingTestCase.swift new file mode 100644 index 0000000000..161b3a9258 --- /dev/null +++ b/Tests/NextcloudUnitTests/OnboardingTestCase.swift @@ -0,0 +1,158 @@ +// +// OnboardingTestCase.swift +// NextcloudTests +// +// Created by A200073704 on 21/04/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +@testable import Nextcloud +import XCTest +import NextcloudKit + + class OnboardingTestCase: XCTestCase { + + var viewController = NCIntroViewController() + + + var images:[UIImage?] = [] + let imagesLandscape = [UIImage(named: "introSlideLand1"), UIImage(named: "introSlideLand2"), UIImage(named: "introSlideLand3")] + let imagesPortrait = [UIImage(named: "introSlide1"), UIImage(named: "introSlide2"), UIImage(named: "introSlide3")] + let imagesEightPortrait = [UIImage(named: "introSlideEight1"), UIImage(named: "introSlideEight2"), UIImage(named: "introSlideEight3")] + + + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + + func testValidImage() { + + // onscreen images should not be nill + let image = [UIImage(named: "introSlideLand1"), UIImage(named: "introSlideLand2"), UIImage(named: "introSlideLand3")] + XCTAssertNotNil(image, "Image should not be nil") + + } + + func testImageDimensionsLandscape() { + + // testing height and width of the image + let introCollectionView = UIImage(named: "introSlideLand1") + XCTAssertEqual(introCollectionView?.size.width, 390, "Image width should be 390") + XCTAssertEqual(introCollectionView?.size.height, 844.3333333333334, "Image height should be 844.3333333333334") + } + + func testImageDimensionsPortrait() { + + // testing height and width of the image + let introCollectionView = UIImage(named: "introSlide1") + + XCTAssertEqual(introCollectionView?.size.width, 390, "Image width should be 390") + XCTAssertEqual(introCollectionView?.size.height, 844.3333333333334, "Image height should be 844.3333333333334") + } + + + func testImageDimentionsNotEqual() { + + // testing width and height if not equal + let introCollectionView = UIImage(named: "introSlide2") + + XCTAssertNotEqual(introCollectionView?.size.width, 100, "Image width should be 390") + XCTAssertNotEqual(introCollectionView?.size.height, 820, "Image height should be 844.3333333333334") + + } + + + func testImageContentMode() { + + // imageview content mode should be scaleAspectFill + let imageView = UIImageView() + imageView.contentMode = .scaleAspectFill + imageView.image = UIImage(named: "introSlideLand2") + XCTAssertEqual(imageView.contentMode, .scaleAspectFill, "Image content mode should be scaleAspectFill") + + } + + + // Background color of view should be customer + func testBackgroundcolor() { + + let backgroundColor = NCBrandColor.shared.customer + XCTAssertNotNil(backgroundColor, "NCBrandColor.shared.customer should not be nil") + + } + + + // Button login text color shouyld be white + func testButtonLoginTextColor() { + + let textColor: UIColor = .white + viewController.buttonLogin?.backgroundColor = textColor + + XCTAssertEqual(textColor, textColor) + + } + + // images at loginscreen should not be empty + func testImagesNotEmpty() { + + let isEightPlusDevice = UIScreen.main.bounds.height == 736 + images = UIDevice.current.orientation.isLandscape ? imagesLandscape : (isEightPlusDevice ? imagesEightPortrait : imagesPortrait) + + XCTAssertFalse(images.isEmpty) + } + + + // Status bar and navigation bar color should not be blue color + func testStatueBarColorNotEqualToCustomer() { + + + let view = NCLoginWeb() + var color = view.navigationController?.navigationBar.backgroundColor + let navigationBarColor: UIColor = NCBrandColor.shared.customer + color = .systemBlue + + XCTAssertNotEqual(navigationBarColor, color) + + } + + //NavigationBar and status Bar color should be equal + func testNavigationBarColorEqualToCustomer() { + + let statusBarColor = NCBrandColor.shared.customer + let navigationBarColor: UIColor = NCBrandColor.shared.customer + + XCTAssertEqual(navigationBarColor, statusBarColor) + } + + func testEightPlusDeviceHeight() { + + let eightPlusDevice = UIScreen.main.bounds.height >= 736 + + XCTAssertTrue(eightPlusDevice) + + } + + func testLoginButtonTapped() { + + let viewController = NCIntroViewController() + + let loginButton = UIButton() + loginButton.addTarget(nil, action: #selector(viewController.login(_:)), for: .touchUpInside) + loginButton.sendActions(for: .touchUpInside) + + viewController.login(loginButton) + + XCTAssertNotNil(loginButton) + } + + + + +} diff --git a/Tests/NextcloudUnitTests/PrivacyPolicyTest.swift b/Tests/NextcloudUnitTests/PrivacyPolicyTest.swift new file mode 100644 index 0000000000..f6265f48e7 --- /dev/null +++ b/Tests/NextcloudUnitTests/PrivacyPolicyTest.swift @@ -0,0 +1,154 @@ +// +// PrivacyPolicyTest.swift +// NextcloudTests +// +// Created by A200073704 on 27/04/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +@testable import Nextcloud +import XCTest +import NextcloudKit +import XLForm + + + class PrivacyPolicyTest: XCTestCase { + + var viewController: InitialPrivacySettingsViewController? + var privacySettingsView = PrivacySettingsViewController() + + override func setUpWithError() throws { + + // To Create an instance of UIStoryboard + let storyboard = UIStoryboard(name: "NCSettings", bundle: nil) + + // To Instantiate UIViewController with Storyboard ID + viewController = storyboard.instantiateViewController(withIdentifier: "privacyPolicyViewController") as? InitialPrivacySettingsViewController + + // Outlets are connected + let _ = viewController?.view + + // Make the viewDidLoad() execute. + viewController?.loadViewIfNeeded() + + } + + override func tearDownWithError() throws { + viewController = nil + } + + func testPrivacyPolicyViewControllerIsOpen() { + + // Check that the InitialPrivacyPolicyViewController gets opened + let storyboard = UIStoryboard(name: "NCSettings", bundle: nil) + if let privacyPolicyViewController = storyboard.instantiateViewController(withIdentifier: "privacyPolicyViewController") as? InitialPrivacySettingsViewController { + let navigationController = UINavigationController(rootViewController: privacyPolicyViewController) + + privacyPolicyViewController.loadViewIfNeeded() + + XCTAssertTrue(navigationController.topViewController is InitialPrivacySettingsViewController, "Privacy policy view controller should be open") + } + } + + func testTextViewHasCorrectText() { + + //Check that the text displayed is correct + let expectedText = NSLocalizedString("_privacy_help_text_after_login_", comment: "") + viewController?.privacySettingsHelpText?.text = expectedText + + let actualText = viewController?.privacySettingsHelpText?.text + XCTAssertEqual(actualText, expectedText, "The text view does not have the expected text") + } + + func testHasAcceptButton() { + + // Check that view has the accept button + let acceptButton = viewController?.acceptButton + + XCTAssertNotNil(acceptButton, "View controller does not have an accept button") + + } + + func testSettingsLinkTypeNavigatesToPrivacySettingsViewController() { + + // Simulate tapping the "Settings" link type + let linkType = LinkType.settings + + UserDefaults.standard.set(true, forKey: "showSettingsButton") + viewController?.privacySettingsHelpText.hyperLink(originalText: viewController?.privacyHelpText ?? "", linkTextsAndTypes: [NSLocalizedString("_key_settings_help_", comment: ""): linkType.rawValue]) + + // Check that the correct view controller was pushed onto the navigation stack + XCTAssertNotNil(viewController?.navigationController?.visibleViewController is PrivacySettingsViewController) + } + + func testPrivacyPolicyLinkType_NavigatesToPrivacyPolicyViewController() { + + // Simulate tapping the "Privacy Policy" link type + let linkType = LinkType.privacyPolicy + + viewController?.privacySettingsHelpText.hyperLink(originalText: viewController?.privacyHelpText ?? "", linkTextsAndTypes: [NSLocalizedString("_key_privacy_help_", comment: ""): linkType.rawValue]) + + // Check that the correct view controller was pushed onto the navigation + XCTAssertNotNil(viewController?.navigationController?.visibleViewController is PrivacyPolicyViewController) + } + + func testCorrectImagePresentOnInitialPrivacySettingsViewController() { + + // Check that the image view has the correct image + let expectedImage = UIImage(named: "dataPrivacy") + XCTAssertNotNil(expectedImage) + } + + func testAcceptButtonHasBackgroundColor() { + + // Check that the accept button has the correct background color + let expectedColor = NCBrandColor.shared.brand + XCTAssertEqual(viewController?.acceptButton.backgroundColor, expectedColor) + + } + + func testShowSaveSettingsButton() { + + privacySettingsView.isShowSettingsButton = UserDefaults.standard.bool(forKey: "showSettingsButton") + + XCTAssertTrue(privacySettingsView.isShowSettingsButton) + + } + + func testRequiredDataCollectionSectionExists() { + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + + var section : XLFormSectionDescriptor + var row : XLFormRowDescriptor + + // the section with the title "Required Data Collection" + row = XLFormRowDescriptor(tag: "ButtonDestinationFolder", rowType: "RequiredDataCollectionCustomCellType", title: "") + section = XLFormSectionDescriptor.formSection(withTitle: "") + section.footerTitle = NSLocalizedString("_required_data_collection_help_text_", comment: "") + + // Verify that section was found + XCTAssertNotNil(row, "Expected 'Required Data Collection' section to exist in form.") + } + + func testAnalysisDataCollectionSection() { + + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + var section : XLFormSectionDescriptor + var row : XLFormRowDescriptor + + // row with tag "AnalysisDataCollectionSwitch" + row = XLFormRowDescriptor(tag: "AnalysisDataCollectionSwitch", rowType: "AnalysisDataCollectionCustomCellType", title: "") + section = XLFormSectionDescriptor.formSection(withTitle: "") + section.footerTitle = NSLocalizedString("_analysis_data_acqusition_help_text_", comment: "") + + // Assert that the row exists + XCTAssertNotNil(row, "Expected row with tag 'AnalysisDataCollectionSwitch' to exist in form.") + + // Verify the switch is off + XCTAssertFalse(UserDefaults.standard.bool(forKey: "isAnalysisDataCollectionSwitchOn"), "Expected isAnalysisDataCollectionSwitchOn to be false.") + } + + +} diff --git a/Tests/NextcloudUnitTests/RenameFileTests.swift b/Tests/NextcloudUnitTests/RenameFileTests.swift new file mode 100644 index 0000000000..c0aa06f029 --- /dev/null +++ b/Tests/NextcloudUnitTests/RenameFileTests.swift @@ -0,0 +1,108 @@ +// +// RenameFileTests.swift +// NextcloudTests +// +// Created by A200073704 on 14/06/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +@testable import Nextcloud +import XCTest +import NextcloudKit + +class RenameFileTests: XCTestCase { + + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + + func testStoryboardPresence() { + + let storyboard = UIStoryboard(name: "NCRenameFile", bundle: nil) + XCTAssertNotNil(storyboard, "Storyboard 'NCRenameFile' should be present") + + } + + func testRenameButtonPresence() { + let storyboard = UIStoryboard(name: "NCRenameFile", bundle: nil) + guard let viewController = storyboard.instantiateInitialViewController() as? NCRenameFile else { + XCTFail("Failed to instantiate view controller from storyboard") + return + } + + _ = viewController.view // Load the view + + let renameButton = viewController.renameButton + XCTAssertNotNil(renameButton, "Rename button should be present") + } + + func testRenameButtonBackgroundColor() { + + let storyboard = UIStoryboard(name: "NCRenameFile", bundle: nil) + guard let viewController = storyboard.instantiateInitialViewController() as? NCRenameFile else { + XCTFail("Failed to instantiate view controller from storyboard") + return + } + + _ = viewController.view // Load the view + + let color = NCBrandColor.shared.brand.cgColor + let renameButton = viewController.renameButton.layer.backgroundColor + + XCTAssertEqual(renameButton,color, "Rename Button Bcakground Color should be brand") + } + + func testCancelButtonPresence() { + let storyboard = UIStoryboard(name: "NCRenameFile", bundle: nil) + guard let viewController = storyboard.instantiateInitialViewController() as? NCRenameFile else { + XCTFail("Failed to instantiate view controller from storyboard") + return + } + + _ = viewController.view // Load the view + + let cancelButton = viewController.cancelButton + XCTAssertNotNil(cancelButton, "Cancel button should be present") + } + + func testImageViewPresence() { + + let storyboard = UIStoryboard(name: "NCRenameFile", bundle: nil) + guard let viewController = storyboard.instantiateInitialViewController() as? NCRenameFile else { + XCTFail("Failed to instantiate view controller from storyboard") + return + } + + _ = viewController.view // Load the view + + let imageView = viewController.previewFile + XCTAssertNotNil(imageView, "UIImageView should be present on the storyboard") + } + + func testTextFiledPresence() { + + let storyboard = UIStoryboard(name: "NCRenameFile", bundle: nil) + guard let viewController = storyboard.instantiateInitialViewController() as? NCRenameFile else { + XCTFail("Failed to instantiate view controller from storyboard") + return + } + + _ = viewController.view // Load the view + + let textField = viewController.fileNameNoExtension + let textFieldExt = viewController.ext + + XCTAssertNotNil(textField, "FileNameNoExtention TextFiled should be present on the storyboard") + XCTAssertNotNil(textFieldExt, "Extension TextFiled should be present on the storyboard") + + } + + + +} diff --git a/Tests/NextcloudUnitTests/ScanTests.swift b/Tests/NextcloudUnitTests/ScanTests.swift new file mode 100644 index 0000000000..750fc86d01 --- /dev/null +++ b/Tests/NextcloudUnitTests/ScanTests.swift @@ -0,0 +1,111 @@ +// +// ScanTests.swift +// NextcloudTests +// +// Created by A200020526 on 18/05/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +@testable import Nextcloud +import XCTest +import XLForm + +final class ScanTests: XCTestCase { + + var viewController: NCCreateFormUploadScanDocument? + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + viewController = NCCreateFormUploadScanDocument() + } + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + viewController = nil + } + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + public func testImageColor() { + // Create a test color + let testColor = UIColor.red + // Create a test image + let testImage = UIImage(named: "activityTypeInfo") // Replace "your_image_name" with the name of your test image + // Call the imageColor function with the test color + let resultImage = testImage?.imageColor(testColor) + // Assert that the result image is not nil + XCTAssertNotNil(resultImage, "Result image should not be nil") + // Assert that the result image has the same size as the test image + XCTAssertEqual(resultImage?.size, testImage?.size, "Result image should have the same size as the test image") + } + func testIsAtleastOneFiletypeSelected() { + // Set up the initial switch states + viewController?.isPDFWithOCRSwitchOn = false + viewController?.isPDFWithoutOCRSwitchOn = false + viewController?.isTextFileSwitchOn = false + viewController?.isPNGFormatSwitchOn = false + viewController?.isJPGFormatSwitchOn = false + + // Call the function under test + let result1 = viewController?.isAtleastOneFiletypeSelected() ?? false + + // Assert the initial result + XCTAssertFalse(result1, "None of the file types are selected initially") + + // Update switch states + viewController?.isPDFWithOCRSwitchOn = true + + // Call the function under test again + let result2 = viewController?.isAtleastOneFiletypeSelected() ?? false + + // Assert the updated result + XCTAssertTrue(result2, "At least one file type is selected") + } + + func testBestFittingFont() { + // Set up the initial values + let text = "Hello, World!" + let bounds = CGRect(x: 0, y: 0, width: 200, height: 100) + let fontDescriptor = UIFontDescriptor(name: "Helvetica", size: 20) + let fontColor = UIColor.black + + // Call the function under test + let attributes = viewController?.bestFittingFont(for: text, in: bounds, fontDescriptor: fontDescriptor, fontColor: fontColor) + + // Assert the results + XCTAssertNotNil(attributes?[NSAttributedString.Key.font], "Font attribute should not be nil") + XCTAssertNotNil(attributes?[NSAttributedString.Key.foregroundColor], "Font color attribute should not be nil") + XCTAssertNotNil(attributes?[NSAttributedString.Key.kern], "Kern attribute should not be nil") + + XCTAssertEqual(attributes?[NSAttributedString.Key.foregroundColor] as? UIColor, fontColor, "Font color should match the input value") + + let font = attributes?[NSAttributedString.Key.font] as? UIFont + XCTAssertNotNil(font, "Font should not be nil") + XCTAssertEqual(font?.fontName, fontDescriptor.fontAttributes[.name] as? String, "Font name should match the input value") + } + + func testChangeCompressionImage() { + // Set up the initial values + guard let image = UIImage(named: "activityTypeInfo") else { + return + } + + // Call the function under test + let compressedImage = viewController?.changeCompressionImage(image) + + // Assert the results + XCTAssertNotNil(compressedImage, "Compressed image should not be nil") + if let width = compressedImage?.size.width, let height = compressedImage?.size.height { + XCTAssertTrue(width <= 841.8, "Compressed image width should be less than or equal to the base width") + XCTAssertTrue(height <= 595.2, "Compressed image height should be less than or equal to the base height") + } + } +} diff --git a/Tests/NextcloudUnitTests/SettingsTestCases.swift b/Tests/NextcloudUnitTests/SettingsTestCases.swift new file mode 100644 index 0000000000..4b16db93f3 --- /dev/null +++ b/Tests/NextcloudUnitTests/SettingsTestCases.swift @@ -0,0 +1,341 @@ +// +// SettingsTestCases.swift +// NextcloudTests +// +// Created by A200073704 on 12/05/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +@testable import Nextcloud +import XCTest +import NextcloudKit +import XLForm + + class SettingsTestCases: XCTestCase { + + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + // MARK: - Settings + + func testAutoUploadSectionIsPresent() { + + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + + var section : XLFormSectionDescriptor + var row : XLFormRowDescriptor + + let image = UIImage(named: "autoUpload") + row = XLFormRowDescriptor(tag: "autoUpload", rowType: XLFormRowDescriptorTypeButton, title: NSLocalizedString("_settings_autoupload_", comment: "")); + section = XLFormSectionDescriptor.formSection(withTitle: "") + section.addFormRow(row) + + XCTAssertNotNil(image) + // Verify that section was found + XCTAssertNotNil(row, "Expected 'Auto Upload' section to exist in form.") + + + } + + func testLockSectionIsPresent() { + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + + var section : XLFormSectionDescriptor + var row : XLFormRowDescriptor + + let image = UIImage(named: "lock_open") + row = XLFormRowDescriptor(tag: "bloccopasscode", rowType: XLFormRowDescriptorTypeButton, title: NSLocalizedString("_lock_not_active_", comment: "")); + section = XLFormSectionDescriptor.formSection(withTitle: "") + section.addFormRow(row) + + XCTAssertNotNil(image) + + XCTAssertNotNil(row, "Expected 'Lock Active / Off ' section exists") + + + } + + func testEnableTouchIDSectionIsPresent() { + + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + + var section : XLFormSectionDescriptor + var row : XLFormRowDescriptor + + row = XLFormRowDescriptor(tag: "enableTouchDaceID", rowType: XLFormRowDescriptorTypeBooleanSwitch, title: NSLocalizedString("_enable_touch_face_id_", comment: "")); + section = XLFormSectionDescriptor.formSection(withTitle: "") + section.addFormRow(row) + + XCTAssertNotNil(row, "Expected 'Enable/Disable touch ID' is present") + + } + + func testEndToEndEncryptionSectionIsPresent() { + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + + var section : XLFormSectionDescriptor + var row : XLFormRowDescriptor + + row = XLFormRowDescriptor(tag: "e2eEncryption", rowType: XLFormRowDescriptorTypeButton, title: NSLocalizedString("_e2e_settings_", comment: "")); + section = XLFormSectionDescriptor.formSection(withTitle: "") + section.addFormRow(row) + + XCTAssertNotNil(row, "Expected 'End to End encryption' section exists") + + + } + + func testAdvancedSectionIsPresent() { + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + + var section : XLFormSectionDescriptor + var row : XLFormRowDescriptor + + row = XLFormRowDescriptor(tag: "advanced", rowType: XLFormRowDescriptorTypeButton, title: NSLocalizedString("_e2e_settings_", comment: "")); + section = XLFormSectionDescriptor.formSection(withTitle: "") + section.addFormRow(row) + + XCTAssertNotNil(row, " Expected 'Advanced' Section exists") + } + + + + func testNavigatesToOpenSourceViewController() { + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + let section = XLFormSectionDescriptor.formSection() + form.addFormSection(section) + + let row = XLFormRowDescriptor(tag: "buttonLeftAligned", rowType: XLFormRowDescriptorTypeButton, title: NSLocalizedString("_used_opensource_software_", comment: "")) + section.addFormRow(row) + + // Create a view controller with the form and add it to a navigation controller + let viewController = OpenSourceSoftwareViewController() + let window = UIApplication.shared.windows.first { $0.isKeyWindow } + let navigationController = UINavigationController(rootViewController: viewController) + window?.rootViewController = navigationController + + viewController.loadViewIfNeeded() + let indexPath = IndexPath(row: 0, section: 0) + print("Calling didSelectRowAt for row at \(indexPath)") + + // Verify that the OpenSourceSoftwareViewController class is opened + XCTAssertTrue(navigationController.topViewController is OpenSourceSoftwareViewController) + + } + + func testHelpSectionIsPresent() { + + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + let section = XLFormSectionDescriptor.formSection() + form.addFormSection(section) + + let row = XLFormRowDescriptor(tag: "buttonLeftAligned", rowType: XLFormRowDescriptorTypeButton, title: NSLocalizedString("_help_", comment: "")) + section.addFormRow(row) + + // Create a view controller with the form and add it to a navigation controller + let viewController = HelpViewController() + let window = UIApplication.shared.windows.first { $0.isKeyWindow } + let navigationController = UINavigationController(rootViewController: viewController) + window?.rootViewController = navigationController + + viewController.loadViewIfNeeded() + let indexPath = IndexPath(row: 0, section: 0) + print("Calling didSelectRowAt for row at \(indexPath)") + + // Verify that the HelpViewController class is opened + XCTAssertTrue(navigationController.topViewController is HelpViewController) + + XCTAssertNotNil(row, "Expected 'Help' Section is present") + + } + + func testImprintSectionIsPresent() { + + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + let section = XLFormSectionDescriptor.formSection() + form.addFormSection(section) + + let row = XLFormRowDescriptor(tag: "buttonLeftAligned", rowType: XLFormRowDescriptorTypeButton, title: NSLocalizedString("_imprint_", comment: "")) + section.addFormRow(row) + + // Create a view controller with the form and add it to a navigation controller + let viewController = ImprintViewController() + let window = UIApplication.shared.windows.first { $0.isKeyWindow } + let navigationController = UINavigationController(rootViewController: viewController) + window?.rootViewController = navigationController + + viewController.loadViewIfNeeded() + let indexPath = IndexPath(row: 0, section: 0) + print("Calling didSelectRowAt for row at \(indexPath)") + + // Verify that the ImprintViewController class is opened + XCTAssertTrue(navigationController.topViewController is ImprintViewController) + + XCTAssertNotNil(row, "Expected 'Imprint' Section is present") + } + + func testMagentaCloudVersionSectionIsPresent() { + + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + let section = XLFormSectionDescriptor.formSection() + form.addFormSection(section) + + let row = XLFormRowDescriptor(tag: "disablefilesapp", rowType: "kNMCCustomCellType", title: NSLocalizedString("_magentacloud_version_", comment: "")) + section.addFormRow(row) + + XCTAssertNotNil(row, "Expected 'MagentaCloud Version' is present") + + + } + + // MARK: - Advanced + + func testShowHiddenFilesSectionIsPresent() { + + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + let section = XLFormSectionDescriptor.formSection() + form.addFormSection(section) + + let row = XLFormRowDescriptor(tag: "showHiddenFiles", rowType: XLFormRowDescriptorTypeBooleanSwitch, title: NSLocalizedString("_show_hidden_files_", comment: "")) + section.addFormRow(row) + + XCTAssertNotNil(row, "Expected 'Show hidden files' section is present") + + } + + func testMostCompatibleSectionIsPresent() { + + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + let section = XLFormSectionDescriptor.formSection() + form.addFormSection(section) + + let row = XLFormRowDescriptor(tag: "formatCompatibility", rowType: XLFormRowDescriptorTypeBooleanSwitch, title: NSLocalizedString("_format_compatibility_", comment: "")) + row.value = "1" + section.addFormRow(row) + + XCTAssertNotNil(row, "Expected 'Most Compatible' is present") + } + + func testLivePhotoSectionIsPresent() { + + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + let section = XLFormSectionDescriptor.formSection() + form.addFormSection(section) + + let row = XLFormRowDescriptor(tag: "livePhoto", rowType: XLFormRowDescriptorTypeBooleanSwitch, title: NSLocalizedString("_upload_mov_livephoto_", comment: "")) + if CCUtility.getLivePhoto() { + row.value = "1" + } else { + row.value = "0" + } + section.addFormRow(row) + + XCTAssertNotNil(row, "Expected 'Live Photo' section is present") + + } + + func testImageResolutionSectionIsPresent() { + + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + let section = XLFormSectionDescriptor.formSection() + form.addFormSection(section) + + let row = XLFormRowDescriptor(tag: "automaticDownloadImage", rowType: XLFormRowDescriptorTypeBooleanSwitch, title: NSLocalizedString("_automatic_Download_Image_", comment: "")) + section.addFormRow(row) + + XCTAssertNotNil(row, "Expected 'Use images in full resolution' section is present") + } + + func testAppIntegrationSectionIsPresent() { + + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + let section = XLFormSectionDescriptor.formSection() + form.addFormSection(section) + + let row = XLFormRowDescriptor(tag: "disablefilesapp", rowType: XLFormRowDescriptorTypeBooleanSwitch, title: NSLocalizedString("_disable_files_app_", comment: "")) + section.addFormRow(row) + + XCTAssertNotNil(row, "Expected 'Disable Files App Integration' section is present") + } + + func testDeleteFilesSectionIsPresent() { + + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + let section = XLFormSectionDescriptor.formSection() + form.addFormSection(section) + + let row = XLFormRowDescriptor(tag: "deleteoldfiles", rowType: XLFormRowDescriptorTypeSelectorPush, title: NSLocalizedString("_delete_old_files_", comment: "")) + section.addFormRow(row) + + XCTAssertNotNil(row, "Expected 'Delete all files older than..' section is present") + } + + func testClearCacheSectionIsPresent() { + + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + let section = XLFormSectionDescriptor.formSection() + form.addFormSection(section) + + let image = UIImage(named: "trash") + + let row = XLFormRowDescriptor(tag: "azzeracache", rowType:XLFormRowDescriptorTypeButton, title: NSLocalizedString("_clear_cache_", comment: "")) + section.addFormRow(row) + + XCTAssertNotNil(image) + + XCTAssertNotNil(row, "Expected 'Clear Cache' section is present") + + } + + func testLogoutButtonIsPresent() { + + let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor + form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow + let section = XLFormSectionDescriptor.formSection() + form.addFormSection(section) + + let image = UIImage(named: "xmark") + + let row = XLFormRowDescriptor(tag: "esci", rowType: XLFormRowDescriptorTypeButton, title: NSLocalizedString("_exit_", comment: "")) + section.addFormRow(row) + + XCTAssertNotNil(image) + + XCTAssertNotNil(row, "Expected 'Logout' Button is present") + + + } + + + + + + + + + + + +} diff --git a/Tests/NextcloudUnitTests/SharingTest.swift b/Tests/NextcloudUnitTests/SharingTest.swift new file mode 100644 index 0000000000..66d94dbfbb --- /dev/null +++ b/Tests/NextcloudUnitTests/SharingTest.swift @@ -0,0 +1,232 @@ +// +// SharingTest.swift +// NextcloudTests +// +// Created by A200020526 on 07/06/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +import XCTest +@testable import Nextcloud +final class SharingTest: XCTestCase { + + var button: UIButton? + var ncShare: NCShare? + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + super.setUp() + button = UIButton() + ncShare = NCShare() + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + button = nil + ncShare = nil + super.tearDown() + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + + + //Date exntesion test case + func testTomorrow() { + let tomorrow = Date.tomorrow + let expectedTomorrow = Calendar.current.date(byAdding: .day, value: 1, to: Date())! + XCTAssertEqual(tomorrow.extendedIso8601String, expectedTomorrow.extendedIso8601String, "Tomorrow date should be correct.") + } + func testToday() { + let today = Date.today + let currentDate = Date() + XCTAssertEqual(today.extendedIso8601String, currentDate.extendedIso8601String, "Today date should be correct.") + } + + func testDayAfter() { + let date = Date() + let dayAfter = date.dayAfter + let expectedDayAfter = Calendar.current.date(byAdding: .day, value: 1, to: date)! + XCTAssertEqual(dayAfter.extendedIso8601String, expectedDayAfter.extendedIso8601String, "Day after date should be correct.") + } + + //Date Formatter extension Test Case + func testShareExpDate() { + let dateFormatter = DateFormatter.shareExpDate + + XCTAssertEqual(dateFormatter.formatterBehavior, .behavior10_4, "Formatter behavior should be correct.") + XCTAssertEqual(dateFormatter.dateStyle, .medium, "Date style should be correct.") + XCTAssertEqual(dateFormatter.dateFormat, NCShareAdvancePermission.displayDateFormat, "Date format should be correct.") + } + + //Button Extension test case + func testSetBackgroundColor() { + // Arrange + let color = UIColor.red + let state: UIControl.State = .normal + + // Act + button?.setBackgroundColor(color, for: state) + + // Assert + XCTAssertNotNil(button?.currentBackgroundImage, "Button background image not nil") + } + + func testSetBackgroundColorForDifferentStates() { + // Arrange + + let selectedColor = UIColor.green + + // Act + button?.isSelected = true + button?.setBackgroundColor(selectedColor, for: .selected) + + // Assert + XCTAssertNotNil(button?.currentBackgroundImage, "Button background image not nil") + button?.isSelected = false + XCTAssertNil(button?.currentBackgroundImage,"Button background image will be nil") + button?.isHighlighted = true + XCTAssertNil(button?.currentBackgroundImage, "Button background image will be nil") + } + + //UIView extension shadow test case + func testAddShadowWithLocation() { + // Create a UIView instance + let view = UIView() + + // Set the shadow with bottom location + view.addShadow(location: .bottom, height: 2, color: .red, opacity: 0.4, radius: 2) + + // Verify that the shadow offset is set correctly for the bottom location + let bottomShadowOffset = view.layer.shadowOffset + XCTAssertEqual(bottomShadowOffset, CGSize(width: 0, height: 2), "Shadow offset not set correctly for bottom location") + + // Verify that the shadow color is set correctly + let shadowColor = view.layer.shadowColor + XCTAssertEqual(shadowColor, UIColor.red.cgColor, "Shadow color not set correctly") + + // Verify that the shadow opacity is set correctly + let shadowOpacity = view.layer.shadowOpacity + XCTAssertEqual(shadowOpacity, 0.4, "Shadow opacity not set correctly") + + // Verify that the shadow radius is set correctly + let shadowRadius = view.layer.shadowRadius + XCTAssertEqual(shadowRadius, 2.0, "Shadow radius not set correctly") + } + + func testAddShadowWithOffset() { + // Create a UIView instance + let view = UIView() + + // Set the shadow with a custom offset + view.addShadow(offset: CGSize(width: 0, height: -4), color: .blue, opacity: 0.6, radius: 3) + + // Verify that the shadow offset is set correctly + let shadowOffset = view.layer.shadowOffset + XCTAssertEqual(shadowOffset, CGSize(width: 0, height: -4), "Shadow offset not set correctly") + + // Verify that the shadow color is set correctly + let shadowColor = view.layer.shadowColor + XCTAssertEqual(shadowColor, UIColor.blue.cgColor, "Shadow color not set correctly") + + // Verify that the shadow opacity is set correctly + let shadowOpacity = view.layer.shadowOpacity + XCTAssertEqual(shadowOpacity, 0.6, "Shadow opacity not set correctly") + + // Verify that the shadow radius is set correctly + let shadowRadius = view.layer.shadowRadius + XCTAssertEqual(shadowRadius, 3.0, "Shadow radius not set correctly") + } + + func testAddShadowForLocation() { + // Create a UIView instance + let view = UIView() + + // Add shadow to the bottom + view.addShadow(location: .bottom, color: UIColor.black) + + // Verify that the shadow properties are set correctly for the bottom location + XCTAssertEqual(view.layer.shadowOffset, CGSize(width: 0, height: 2), "Shadow offset not set correctly for bottom location") + XCTAssertEqual(view.layer.shadowColor, UIColor.black.cgColor, "Shadow color not set correctly for bottom location") + XCTAssertEqual(view.layer.shadowOpacity, 0.4, "Shadow opacity not set correctly for bottom location") + XCTAssertEqual(view.layer.shadowRadius, 2.0, "Shadow radius not set correctly for bottom location") + + // Add shadow to the top + view.addShadow(location: .top) + + // Verify that the shadow properties are set correctly for the top location + XCTAssertEqual(view.layer.shadowOffset, CGSize(width: 0, height: -2), "Shadow offset not set correctly for top location") + XCTAssertEqual(view.layer.shadowColor, NCBrandColor.shared.customerDarkGrey.cgColor, "Shadow color not set correctly for top location") + XCTAssertEqual(view.layer.shadowOpacity, 0.4, "Shadow opacity not set correctly for top location") + XCTAssertEqual(view.layer.shadowRadius, 2.0, "Shadow radius not set correctly for top location") + } + + func testAddShadowForOffset() { + // Create a UIView instance + let view = UIView() + + // Add shadow with custom offset + view.addShadow(offset: CGSize(width: 2, height: 2)) + + // Verify that the shadow properties are set correctly for the custom offset + XCTAssertEqual(view.layer.shadowOffset, CGSize(width: 2, height: 2), "Shadow offset not set correctly for custom offset") + XCTAssertEqual(view.layer.shadowColor, UIColor.black.cgColor, "Shadow color not set correctly for custom offset") + XCTAssertEqual(view.layer.shadowOpacity, 0.5, "Shadow opacity not set correctly for custom offset") + XCTAssertEqual(view.layer.shadowRadius, 5.0, "Shadow radius not set correctly for custom offset") + } + + + func testHasUploadPermission() { + // Create an instance of NCShare + let share = NCShare() + + // Define the input parameters + let tableShareWithUploadPermission = tableShare() + tableShareWithUploadPermission.permissions = NCGlobal.shared.permissionMaxFileShare + + let tableShareWithoutUploadPermission = tableShare() + tableShareWithoutUploadPermission.permissions = NCGlobal.shared.permissionReadShare + + // Call the hasUploadPermission function + let hasUploadPermission1 = share.hasUploadPermission(tableShare: tableShareWithUploadPermission) + let hasUploadPermission2 = share.hasUploadPermission(tableShare: tableShareWithoutUploadPermission) + + // Verify the results + XCTAssertTrue(hasUploadPermission1, "hasUploadPermission returned false for a tableShare with upload permission") + XCTAssertFalse(hasUploadPermission2, "hasUploadPermission returned true for a tableShare without upload permission") + } + + func testGetImageShareType() { + let sut = NCShareCommon() // Replace with the actual class containing the getImageShareType function + + // Test case 1: SHARE_TYPE_USER + let shareType1 = sut.SHARE_TYPE_USER + let result1 = sut.getImageShareType(shareType: shareType1) + XCTAssertEqual(result1, UIImage(named: "shareTypeEmail")?.imageColor(NCBrandColor.shared.label)) + + // Test case 2: SHARE_TYPE_GROUP + let shareType2 = sut.SHARE_TYPE_GROUP + let result2 = sut.getImageShareType(shareType: shareType2) + XCTAssertEqual(result2, UIImage(named: "shareTypeGroup")?.imageColor(NCBrandColor.shared.label)) + + // Test case 3: SHARE_TYPE_LINK + let shareType3 = sut.SHARE_TYPE_LINK + let result3 = sut.getImageShareType(shareType: shareType3) + XCTAssertEqual(result3, UIImage(named: "shareTypeLink")?.imageColor(NCBrandColor.shared.label)) + + // Test case 4: SHARE_TYPE_EMAIL (with isDropDown=false) + let shareType4 = sut.SHARE_TYPE_EMAIL + let result4 = sut.getImageShareType(shareType: shareType4) + XCTAssertEqual(result4, UIImage(named: "shareTypeUser")?.imageColor(NCBrandColor.shared.label)) + + // Test case 5: SHARE_TYPE_EMAIL (with isDropDown=true) + let shareType5 = sut.SHARE_TYPE_EMAIL + let isDropDown5 = true + let result5 = sut.getImageShareType(shareType: shareType5, isDropDown: isDropDown5) + XCTAssertEqual(result5, UIImage(named: "email")?.imageColor(NCBrandColor.shared.label)) + } +} diff --git a/iOSClient/Activity/NCActivity.swift b/iOSClient/Activity/NCActivity.swift index 480421d897..77b26d1175 100644 --- a/iOSClient/Activity/NCActivity.swift +++ b/iOSClient/Activity/NCActivity.swift @@ -1,6 +1,26 @@ -// SPDX-FileCopyrightText: Nextcloud GmbH -// SPDX-FileCopyrightText: 2019 Marino Faggiana -// SPDX-License-Identifier: GPL-3.0-or-later +// +// NCActivity.swift +// Nextcloud +// +// Created by Marino Faggiana on 17/01/2019. +// Copyright © 2019 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana +// Author Henrik Storch +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// import UIKit import SwiftRichString @@ -12,7 +32,7 @@ class NCActivity: UIViewController, NCSharePagingContent { @IBOutlet weak var tableView: UITableView! var commentView: NCActivityCommentView? - var textField: UIView? { commentView?.newCommentField } + var textField: UITextField? { commentView?.newCommentField } var height: CGFloat = 0 var metadata: tableMetadata? var showComments: Bool = false @@ -22,6 +42,7 @@ class NCActivity: UIViewController, NCSharePagingContent { let database = NCManageDatabase.shared var allItems: [DateCompareable] = [] var sectionDates: [Date] = [] + var dataSourceTask: URLSessionTask? var insets = UIEdgeInsets(top: 8, left: 0, bottom: 0, right: 0) var didSelectItemEnable: Bool = true @@ -30,13 +51,11 @@ class NCActivity: UIViewController, NCSharePagingContent { var isFetchingActivity = false var hasActivityToLoad = true { - didSet { - tableView.tableFooterView?.isHidden = hasActivityToLoad - } + didSet { tableView.tableFooterView?.isHidden = hasActivityToLoad } } var dateAutomaticFetch: Date? + private let appDelegate = (UIApplication.shared.delegate as? AppDelegate)! - @MainActor var session: NCSession.Session { if account.isEmpty { NCSession.shared.getSession(controller: tabBarController) @@ -50,7 +69,7 @@ class NCActivity: UIViewController, NCSharePagingContent { override func viewDidLoad() { super.viewDidLoad() - navigationController?.setNavigationBarAppearance() + self.navigationController?.navigationBar.prefersLargeTitles = true view.backgroundColor = .systemBackground self.title = NSLocalizedString("_activity_", comment: "") @@ -71,14 +90,7 @@ class NCActivity: UIViewController, NCSharePagingContent { commentView = Bundle.main.loadNibNamed("NCActivityCommentView", owner: self, options: nil)?.first as? NCActivityCommentView commentView?.setup(account: metadata.account) { newComment in guard let newComment = newComment, !newComment.isEmpty, let metadata = self.metadata else { return } - NextcloudKit.shared.putComments(fileId: metadata.fileId, message: newComment, account: metadata.account) { task in - Task { - let identifier = await NCNetworking.shared.networkingTasks.createIdentifier(account: metadata.account, - path: metadata.fileId, - name: "putComments") - await NCNetworking.shared.networkingTasks.track(identifier: identifier, task: task) - } - } completion: { _, _, error in + NextcloudKit.shared.putComments(fileId: metadata.fileId, message: newComment, account: metadata.account) { _, _, error in if error == .success { self.commentView?.newCommentField.text?.removeAll() self.loadComments() @@ -92,18 +104,17 @@ class NCActivity: UIViewController, NCSharePagingContent { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) + appDelegate.activeViewController = self + navigationController?.setNavigationBarAppearance() fetchAll(isInitial: true) } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - Task { - await NCNetworking.shared.networkingTasks.cancel(identifier: "NCActivity") - } - // Cancel Queue & Retrieves Properties NCNetworking.shared.downloadThumbnailActivityQueue.cancelAll() + dataSourceTask?.cancel() } override func viewWillLayoutSubviews() { @@ -122,14 +133,10 @@ class NCActivity: UIViewController, NCSharePagingContent { let label = UILabel() label.font = UIFont.systemFont(ofSize: 15) - label.textColor = NCBrandColor.shared.textColor2 + label.textColor = UIColor.systemGray label.textAlignment = .center label.text = NSLocalizedString("_no_activity_footer_", comment: "") view.addSubview(label) - label.translatesAutoresizingMaskIntoConstraints = false - label.topAnchor.constraint(equalTo: view.topAnchor, constant: 20).isActive = true - label.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true - label.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true return view } @@ -226,8 +233,8 @@ extension NCActivity: UITableViewDataSource { cell.fileAvatarImageView?.image = results.image } - if let tblAvatar = results.tblAvatar, - !tblAvatar.loaded, + if let tableAvatar = results.tableAvatar, + !tableAvatar.loaded, NCNetworking.shared.downloadAvatarQueue.operations.filter({ ($0 as? NCOperationDownloadAvatar)?.fileName == fileName }).isEmpty { NCNetworking.shared.downloadAvatarQueue.addOperation(NCOperationDownloadAvatar(user: comment.actorId, fileName: fileName, account: account, view: tableView)) } @@ -272,7 +279,7 @@ extension NCActivity: UITableViewDataSource { if !activity.icon.isEmpty { activity.icon = activity.icon.replacingOccurrences(of: ".png", with: ".svg") let fileNameIcon = (activity.icon as NSString).lastPathComponent - let fileNameLocalPath = utilityFileSystem.createServerUrl(serverUrl: utilityFileSystem.directoryUserData, fileName: fileNameIcon) + let fileNameLocalPath = utilityFileSystem.directoryUserData + "/" + fileNameIcon if FileManager.default.fileExists(atPath: fileNameLocalPath) { let image = fileNameIcon.contains(".svg") ? SVGKImage(contentsOfFile: fileNameLocalPath)?.uiImage : UIImage(contentsOfFile: fileNameLocalPath) @@ -281,14 +288,7 @@ extension NCActivity: UITableViewDataSource { cell.icon.image = image.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) } } else { - NextcloudKit.shared.downloadContent(serverUrl: activity.icon, account: activity.account) { task in - Task { - let identifier = await NCNetworking.shared.networkingTasks.createIdentifier(account: self.account, - path: activity.icon, - name: "downloadContent") - await NCNetworking.shared.networkingTasks.track(identifier: identifier, task: task) - } - } completion: { _, responseData, error in + NextcloudKit.shared.downloadContent(serverUrl: activity.icon, account: activity.account) { _, responseData, error in if error == .success, let data = responseData?.data { do { try data.write(to: NSURL(fileURLWithPath: fileNameLocalPath) as URL, options: .atomic) @@ -314,7 +314,7 @@ extension NCActivity: UITableViewDataSource { cell.fileAvatarImageView?.image = results.image } - if !(results.tblAvatar?.loaded ?? false), + if !(results.tableAvatar?.loaded ?? false), NCNetworking.shared.downloadAvatarQueue.operations.filter({ ($0 as? NCOperationDownloadAvatar)?.fileName == fileName }).isEmpty { NCNetworking.shared.downloadAvatarQueue.addOperation(NCOperationDownloadAvatar(user: activity.user, fileName: fileName, account: session.account, view: tableView)) } @@ -338,7 +338,7 @@ extension NCActivity: UITableViewDataSource { for key in keys { if let result = database.getActivitySubjectRich(account: session.account, idActivity: activity.idActivity, key: key) { orderKeysId.append(result.id) - subject = subject.replacingOccurrences(of: "{\(key)}", with: "" + result.name.escapedForMarkup + "") + subject = subject.replacingOccurrences(of: "{\(key)}", with: "" + result.name + "") } } @@ -377,8 +377,12 @@ extension NCActivity { func fetchAll(isInitial: Bool) { guard !isFetchingActivity else { return } self.isFetchingActivity = true + var bottom: CGFloat = 0 - NCActivityIndicator.shared.start(backgroundView: self.view, style: .medium) + if let mainTabBar = self.tabBarController?.tabBar as? NCMainTabBar { + bottom = -mainTabBar.getHeight() + } + NCActivityIndicator.shared.start(backgroundView: self.view, bottom: bottom - 35, style: .medium) let dispatchGroup = DispatchGroup() loadComments(disptachGroup: dispatchGroup) @@ -425,14 +429,7 @@ extension NCActivity { guard showComments, let metadata = metadata else { return } disptachGroup?.enter() - NextcloudKit.shared.getComments(fileId: metadata.fileId, account: metadata.account) { task in - Task { - let identifier = await NCNetworking.shared.networkingTasks.createIdentifier(account: metadata.account, - path: metadata.fileId, - name: "getComments") - await NCNetworking.shared.networkingTasks.track(identifier: identifier, task: task) - } - } completion: { _, comments, _, error in + NextcloudKit.shared.getComments(fileId: metadata.fileId, account: metadata.account) { _, comments, _, error in if error == .success, let comments = comments { self.database.addComments(comments, account: metadata.account, objectId: metadata.fileId) } else if error.errorCode != NCGlobal.shared.errorResourceNotFound { @@ -449,13 +446,6 @@ extension NCActivity { /// Check if most recent activivities are loaded, if not trigger reload func checkRecentActivity(disptachGroup: DispatchGroup) { - Task { - // If is already in-flight, do nothing - if await NCNetworking.shared.networkingTasks.isReading(identifier: "NCActivity") { - return - } - } - guard let result = database.getLatestActivityId(account: session.account), metadata == nil, hasActivityToLoad else { return self.loadActivity(idActivity: 0, disptachGroup: disptachGroup) } @@ -463,15 +453,14 @@ extension NCActivity { disptachGroup.enter() - NextcloudKit.shared.getActivity(since: 0, - limit: 1, - objectId: nil, - objectType: objectType, - previews: true, - account: session.account) { task in - Task { - await NCNetworking.shared.networkingTasks.track(identifier: "NCActivity", task: task) - } + NextcloudKit.shared.getActivity( + since: 0, + limit: 1, + objectId: nil, + objectType: objectType, + previews: true, + account: session.account) { task in + self.dataSourceTask = task } completion: { account, _, activityFirstKnown, activityLastGiven, _, error in defer { disptachGroup.leave() } @@ -489,21 +478,18 @@ extension NCActivity { } func loadActivity(idActivity: Int, limit: Int = 200, disptachGroup: DispatchGroup) { - guard hasActivityToLoad else { - return - } + guard hasActivityToLoad else { return } var resultActivityId = 0 disptachGroup.enter() - NextcloudKit.shared.getActivity(since: idActivity, - limit: min(limit, 200), - objectId: metadata?.fileId, - objectType: objectType, - previews: true, - account: session.account) { task in - Task { - await NCNetworking.shared.networkingTasks.track(identifier: "NCActivity", task: task) - } + NextcloudKit.shared.getActivity( + since: idActivity, + limit: min(limit, 200), + objectId: metadata?.fileId, + objectType: objectType, + previews: true, + account: session.account) { task in + self.dataSourceTask = task } completion: { account, activities, activityFirstKnown, activityLastGiven, _, error in defer { disptachGroup.leave() } guard error == .success, @@ -532,26 +518,22 @@ extension NCActivity: NCShareCommentsCellDelegate { guard let tableComment = tableComment else { return } - self.showProfileMenu(userId: tableComment.actorId, session: session, sender: sender) + self.showProfileMenu(userId: tableComment.actorId, session: session) } func tapMenu(with tableComments: tableComments?, sender: Any) { - toggleMenu(with: tableComments, sender: sender) + toggleMenu(with: tableComments) } - func toggleMenu(with tableComments: tableComments?, sender: Any) { + func toggleMenu(with tableComments: tableComments?) { var actions = [NCMenuAction]() actions.append( NCMenuAction( title: NSLocalizedString("_edit_comment_", comment: ""), icon: utility.loadImage(named: "pencil", colors: [NCBrandColor.shared.iconImageColor]), - sender: sender, action: { _ in - guard let metadata = self.metadata, - let tableComments = tableComments else { - return - } + guard let metadata = self.metadata, let tableComments = tableComments else { return } let alert = UIAlertController(title: NSLocalizedString("_edit_comment_", comment: ""), message: nil, preferredStyle: .alert) alert.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel, handler: nil)) @@ -563,14 +545,7 @@ extension NCActivity: NCShareCommentsCellDelegate { alert.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in guard let message = alert.textFields?.first?.text, !message.isEmpty else { return } - NextcloudKit.shared.updateComments(fileId: metadata.fileId, messageId: tableComments.messageId, message: message, account: metadata.account) { task in - Task { - let identifier = await NCNetworking.shared.networkingTasks.createIdentifier(account: metadata.account, - path: metadata.fileId, - name: "updateComments") - await NCNetworking.shared.networkingTasks.track(identifier: identifier, task: task) - } - } completion: { _, _, error in + NextcloudKit.shared.updateComments(fileId: metadata.fileId, messageId: tableComments.messageId, message: message, account: metadata.account) { _, _, error in if error == .success { self.loadComments() } else { @@ -589,18 +564,10 @@ extension NCActivity: NCShareCommentsCellDelegate { title: NSLocalizedString("_delete_comment_", comment: ""), destructive: true, icon: utility.loadImage(named: "trash", colors: [.red]), - sender: sender, action: { _ in guard let metadata = self.metadata, let tableComments = tableComments else { return } - NextcloudKit.shared.deleteComments(fileId: metadata.fileId, messageId: tableComments.messageId, account: metadata.account) { task in - Task { - let identifier = await NCNetworking.shared.networkingTasks.createIdentifier(account: metadata.account, - path: metadata.fileId, - name: "deleteComments") - await NCNetworking.shared.networkingTasks.track(identifier: identifier, task: task) - } - } completion: { _, _, error in + NextcloudKit.shared.deleteComments(fileId: metadata.fileId, messageId: tableComments.messageId, account: metadata.account) { _, _, error in if error == .success { self.loadComments() } else { @@ -611,6 +578,6 @@ extension NCActivity: NCShareCommentsCellDelegate { ) ) - presentMenu(with: actions, sender: sender) + presentMenu(with: actions) } } diff --git a/iOSClient/Analytics/AnalyticsHelper.swift b/iOSClient/Analytics/AnalyticsHelper.swift new file mode 100644 index 0000000000..54281e40df --- /dev/null +++ b/iOSClient/Analytics/AnalyticsHelper.swift @@ -0,0 +1,90 @@ +// +// AnalyticsHelper.swift +// Nextcloud +// +// Created by Amrut Waghmare on 10/06/24. +// Copyright © 2024 Marino Faggiana. All rights reserved. +// + +import Foundation + +class AnalyticsHelper: NSObject, AnalyticsService { + + @objc static let shared = AnalyticsHelper() + + private var analyticsServices: [AnalyticsService] + + private override init() { + // Initialize the analytics services + let moEngageAnalytics = MoEngageAnalytics() + moEngageAnalytics.trackAppId() + analyticsServices = [moEngageAnalytics] + super.init() + } + + func trackEvent(eventName: AnalyticEvents, properties: [String: Any]? = nil) { + DispatchQueue.global(qos: .background).async { + self.analyticsServices.forEach { $0.trackEvent(eventName: eventName, properties: properties) } + } + } + + func trackUserData() { + DispatchQueue.global(qos: .background).async { + self.analyticsServices.forEach { $0.trackUserData() } + } + } + + func trackUsedStorageData(quotaUsed: Int64) { + DispatchQueue.global(qos: .background).async { + self.analyticsServices.forEach { $0.trackUsedStorageData(quotaUsed: quotaUsed) } + } + } + + @objc func trackAutoUpload(isEnable: Bool) { + DispatchQueue.global(qos: .background).async { + self.analyticsServices.forEach { $0.trackAutoUpload(isEnable: isEnable) } + } + } + + func trackAppVersion(oldVersion: String?) { + DispatchQueue.global(qos: .background).async { + self.analyticsServices.forEach { $0.trackAppVersion(oldVersion: oldVersion) } + } + } + + func trackLogout() { + DispatchQueue.global(qos: .background).async { + self.analyticsServices.forEach { $0.trackLogout() } + } + } + + func trackCreateFile(metadata: tableMetadata) { + DispatchQueue.global(qos: .background).async { + self.analyticsServices.forEach { $0.trackCreateFile(metadata: metadata) } + } + } + + func trackEventWithMetadata(eventName: AnalyticEvents, metadata: tableMetadata) { + DispatchQueue.global(qos: .background).async { + self.analyticsServices.forEach { $0.trackEventWithMetadata(eventName: eventName, metadata: metadata) } + } + } + + func trackCreateVoiceMemo(size: Int64, date: Date) { + DispatchQueue.global(qos: .background).async { + self.analyticsServices.forEach { $0.trackCreateVoiceMemo(size: size, date: date) } + } + } + + func trackCreateFolder(isEncrypted: Bool, creationDate: Date) { + DispatchQueue.global(qos: .background).async { + self.analyticsServices.forEach { $0.trackCreateFolder(isEncrypted: isEncrypted, creationDate: creationDate) } + } + } + + func displayInAppNotification() { + self.analyticsServices.forEach { $0.displayInAppNotification() } + } + + +} diff --git a/iOSClient/Analytics/AnalyticsService.swift b/iOSClient/Analytics/AnalyticsService.swift new file mode 100644 index 0000000000..e20600ca76 --- /dev/null +++ b/iOSClient/Analytics/AnalyticsService.swift @@ -0,0 +1,98 @@ +// +// AnalyticsService.swift +// Nextcloud +// +// Created by Amrut Waghmare on 10/06/24. +// Copyright © 2024 Marino Faggiana. All rights reserved. +// + +import Foundation + +protocol AnalyticsService { + func trackEvent(eventName: AnalyticEvents, properties: [String: Any]?) + func trackUserData() + func trackUsedStorageData(quotaUsed: Int64) + func trackAutoUpload(isEnable: Bool) + func trackAppVersion(oldVersion: String?) + func trackLogout() + func trackCreateFile(metadata: tableMetadata) + func trackCreateVoiceMemo(size: Int64, date: Date) + func trackCreateFolder(isEncrypted: Bool, creationDate: Date) + func trackEventWithMetadata(eventName: AnalyticEvents, metadata: tableMetadata) + func displayInAppNotification() +} + +// swiftlint:disable identifier_name +enum AnalyticEvents: String { + case USER_PROPERTIES_STORAGE_CAPACITY = "storage_capacity" // in GB + case USER_PROPERTIES_STORAGE_USED = "storage_used" // % of storage used + case USER_PROPERTIES_AUTO_UPLOAD = "auto_upload_on" + case USER_PROPERTIES_APP_VERSION = "app_version" + case EVENT__ACTION_BUTTON = "action_button_clicked" // when user clicks on fab + button + case EVENT__UPLOAD_FILE = "upload_file" // when user uploads any file (not applicable for folder) from other apps + case EVENT__CREATE_FILE = "create_file" // when user creates any file in app + case EVENT__CREATE_FOLDER = "create_folder" + case EVENT__CREATE_VOICE_MEMO = "create_voice_memo" + case EVENT__ADD_FAVORITE = "add_favorite" + case EVENT__SHARE_FILE = "share_file" // when user share any file using link + case EVENT__OFFLINE_AVAILABLE = "offline_available" + case EVENT__ONLINE_OFFICE_USED = "online_office_used" // when user opens any office files + + // screen view events when user open specific screen + case SCREEN_EVENT__FAVOURITES = "favorites" + case SCREEN_EVENT__MEDIA = "medien" + case SCREEN_EVENT__OFFLINE_FILES = "offline_files" + case SCREEN_EVENT__SHARED = "shared" + case SCREEN_EVENT__DELETED_FILES = "deleted_files" + case SCREEN_EVENT__NOTIFICATIONS = "notifications" + + var moEngageEvent: String { + switch self { + default: + return self.rawValue + } + } + + var teliumEvent: String { + return self.rawValue + } + + var adjustEvent: String { + return self.rawValue + } +} + +// swiftlint:disable identifier_name +enum AnalyticPropertyAttributes: String { + // properties attributes key + case PROPERTIES__FILE_TYPE = "file_type" + case PROPERTIES__FOLDER_TYPE = "folder_type" + case PROPERTIES__FILE_SIZE = "file_size" // in MB + case PROPERTIES__CREATION_DATE = "creation_date" // yyyy-MM-dd + case PROPERTIES__UPLOAD_DATE = "upload_date" // // yyyy-MM-dd +} + +enum FolderType: String { + // properties attributes key + case FOLDER_ENCRYPTED = "encrypted" + case FOLDER_NORMAL = "not encrypted" +} + + +enum Size { + static let KILOBYTE = 1024 + static let MEGABYTE = KILOBYTE * 1024 + static let GIGABYTE = MEGABYTE * 1024 +} + +enum FileType: String { + case FOTO = "foto" + case AUDIO = "audio" + case VIDEO = "video" + case PDF = "pdf" + case TEXT = "text" + case DOCX = "docx" + case XLSX = "xlsx" + case PPT = "ppt" + case OTHER = "other" +} diff --git a/iOSClient/Analytics/MoEngage/MoEngageAnalytics.swift b/iOSClient/Analytics/MoEngage/MoEngageAnalytics.swift new file mode 100644 index 0000000000..ca07324744 --- /dev/null +++ b/iOSClient/Analytics/MoEngage/MoEngageAnalytics.swift @@ -0,0 +1,274 @@ +// +// MoEngageAnalytics.swift +// Nextcloud +// +// Created by Amrut Waghmare on 10/06/24. +// Copyright © 2024 Marino Faggiana. All rights reserved. +// + +import Foundation +import MoEngageSDK +import MoEngageInApps +import StoreKit + +class MoEngageAnalytics: NSObject { + + // Initializer for the MoEngageAnalytics class + override init() { + super.init() + + // Create a configuration object for MoEngage SDK with the given App ID and Data Center + let sdkConfig = MoEngageSDKConfig(appId: "7KWWUKA6OKXGP8Q6DMCXLDX5", dataCenter: MoEngageDataCenter.data_center_02) + + // Disable periodic flushing of analytics data + sdkConfig.analyticsDisablePeriodicFlush = true + + // Initialize the MoEngage SDK + // Use different initialization methods for Debug and Production environments + +#if DEBUG + MoEngage.sharedInstance.initializeDefaultTestInstance(sdkConfig) +#else + MoEngage.sharedInstance.initializeDefaultLiveInstance(sdkConfig) +#endif + setupMoEngageInAppMessaging() + + // Register delegate for In-App Native callbacks + MoEngageSDKInApp.sharedInstance.setInAppDelegate(self) + } + + // Method to track the App ID + func trackAppId() { + MoEngageSDKAnalytics.sharedInstance.trackLocale(forAppID: "312838242") + } + + func setupMoEngageInAppMessaging() { + //MARK: MoEngage In-App messages + MoEngageSDKInApp.sharedInstance.showInApp() + MoEngageSDKInApp.sharedInstance.showNudge() + } + + // Handles triggering Apple's native review popup +// private func requestAppStoreReview() { +// DispatchQueue.main.async { +// if let scene = UIApplication.shared.connectedScenes +// .first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene { +// SKStoreReviewController.requestReview(in: scene) +// } +// } +// } + + private func requestAppStoreReview() { + DispatchQueue.main.async { + guard + let windowScene = UIApplication.shared.connectedScenes + .compactMap({ $0 as? UIWindowScene }) + .first(where: { $0.activationState == .foregroundActive }) + else { + return + } + + #if targetEnvironment(simulator) + // Simulator fallback for testing + let alert = UIAlertController( + title: "Review Prompt (Simulator)", + message: "This simulates the App Store review dialog.", + preferredStyle: .alert + ) + alert.addAction(UIAlertAction(title: "OK", style: .default)) + windowScene.keyWindow?.rootViewController?.present(alert, animated: true) + #else + // Real request on device + SKStoreReviewController.requestReview(in: windowScene) + #endif + } + } + +} + +// AnalyticsService protocol +extension MoEngageAnalytics: AnalyticsService { + // Method to track a specific event with optional properties + func trackEvent(eventName: AnalyticEvents, properties: [String: Any]?) { + let eventProperties = MoEngageProperties(withAttributes: properties) + MoEngageSDKAnalytics.sharedInstance.trackEvent(eventName.moEngageEvent, withProperties: eventProperties) + } + + // Method to track user data + func trackUserData() { + // Get the active user account from the database + guard let user = NCManageDatabase.shared.getActiveTableAccount() else { return } + + // Set user attributes in the MoEngage SDK + MoEngageSDKAnalytics.sharedInstance.setUniqueID(user.userId) + MoEngageSDKAnalytics.sharedInstance.setName(user.displayName) + MoEngageSDKAnalytics.sharedInstance.setEmailID(user.email) + + // Convert the user's total storage quota to a readable format and set it as a user attribute + let storageCapacity = NCUtilityFileSystem().transformedSize(user.quotaTotal) + MoEngageSDKAnalytics.sharedInstance.setUserAttribute(storageCapacity, withAttributeName: AnalyticEvents.USER_PROPERTIES_STORAGE_CAPACITY.rawValue) + + // Track whether auto-upload is enabled for the user + trackAutoUpload(isEnable: user.autoUpload) + } + + // Method to track the used storage data + func trackUsedStorageData(quotaUsed: Int64) { + MoEngageSDKAnalytics.sharedInstance.setUserAttribute(quotaUsed, withAttributeName: AnalyticEvents.USER_PROPERTIES_STORAGE_USED.rawValue) + } + + // Method to track the auto-upload setting + func trackAutoUpload(isEnable: Bool) { + if isEnable { + MoEngageSDKAnalytics.sharedInstance.setUserAttribute(isEnable, withAttributeName: AnalyticEvents.USER_PROPERTIES_AUTO_UPLOAD.rawValue) + } + } + + // Method to track the app version + func trackAppVersion(oldVersion: String?) { + // Get the app version and set it as a user attribute + let version = NCUtility().getVersionApp() as String + + // Check if a build version key is present in UserDefaults + if let oldVersion { + if version != oldVersion { + MoEngageSDKAnalytics.sharedInstance.appStatus(.update) + if let oldAppVersion = Int(oldVersion.dropLast().replacingOccurrences(of: ".", with: "")) { + if oldAppVersion < NCGlobal.shared.moEngageAppVersion { + trackUserData() + } + } + } + } else { + MoEngageSDKAnalytics.sharedInstance.appStatus(.install) + } + + MoEngageSDKAnalytics.sharedInstance.setUserAttribute(version, withAttributeName: AnalyticEvents.USER_PROPERTIES_APP_VERSION.rawValue) + } + + //Method to track user logout + func trackLogout() { + MoEngageSDKAnalytics.sharedInstance.resetUser() + } + + //Method to track create file + func trackCreateFile(metadata: tableMetadata) { + let properties = MoEngageProperties() + properties.addAttribute(getFileType(contentType: metadata.contentType), withName: AnalyticPropertyAttributes.PROPERTIES__FILE_TYPE.rawValue) + properties.addAttribute(String(getFileSizeInMB(bytes: Int(metadata.size))), withName: AnalyticPropertyAttributes.PROPERTIES__FILE_SIZE.rawValue) + properties.addAttribute(getDate(date: metadata.creationDate as Date), withName: AnalyticPropertyAttributes.PROPERTIES__CREATION_DATE.rawValue) + MoEngageSDKAnalytics.sharedInstance.trackEvent(AnalyticEvents.EVENT__CREATE_FILE.rawValue, withProperties: properties) + } + + //Method to track upload file + func trackEventWithMetadata(eventName: AnalyticEvents, metadata: tableMetadata) { + let properties = MoEngageProperties() + properties.addAttribute(getFileType(contentType: metadata.contentType), withName: AnalyticPropertyAttributes.PROPERTIES__FILE_TYPE.rawValue) + properties.addAttribute(String(getFileSizeInMB(bytes: Int(metadata.size))), withName: AnalyticPropertyAttributes.PROPERTIES__FILE_SIZE.rawValue) + properties.addAttribute(getDate(date: metadata.creationDate as Date), withName: AnalyticPropertyAttributes.PROPERTIES__CREATION_DATE.rawValue) + properties.addAttribute(getDate(date: metadata.uploadDate as Date), withName: AnalyticPropertyAttributes.PROPERTIES__UPLOAD_DATE.rawValue) + MoEngageSDKAnalytics.sharedInstance.trackEvent(eventName.rawValue, withProperties: properties) + } + + //Method to track create folder + func trackCreateFolder(isEncrypted: Bool, creationDate: Date) { + let properties = MoEngageProperties() + properties.addAttribute(isEncrypted ? FolderType.FOLDER_ENCRYPTED.rawValue : FolderType.FOLDER_NORMAL.rawValue , withName: AnalyticPropertyAttributes.PROPERTIES__FILE_TYPE.rawValue) + properties.addAttribute(getDate(date: creationDate), withName: AnalyticPropertyAttributes.PROPERTIES__CREATION_DATE.rawValue) + MoEngageSDKAnalytics.sharedInstance.trackEvent(AnalyticEvents.EVENT__CREATE_FOLDER.rawValue, withProperties: properties) + } + + //Method to track create voice memo + func trackCreateVoiceMemo(size: Int64, date: Date) { + let properties = MoEngageProperties() + properties.addAttribute(FileType.AUDIO.rawValue, withName: AnalyticPropertyAttributes.PROPERTIES__FILE_TYPE.rawValue) + properties.addAttribute(String(getFileSizeInMB(bytes: Int(size))), withName: AnalyticPropertyAttributes.PROPERTIES__FILE_SIZE.rawValue) + properties.addAttribute(getDate(date: date), withName: AnalyticPropertyAttributes.PROPERTIES__CREATION_DATE.rawValue) + MoEngageSDKAnalytics.sharedInstance.trackEvent(AnalyticEvents.EVENT__CREATE_VOICE_MEMO.rawValue, withProperties: properties) + } + + func displayInAppNotification() { + MoEngageSDKInApp.sharedInstance.showInApp() + //For showing nudges at any mentioned position + MoEngageSDKInApp.sharedInstance.showNudge() + } +} + +// Functions +extension MoEngageAnalytics { + private func getFileType(contentType: String) -> String? { + switch contentType { + case "image/png": + return FileType.FOTO.rawValue + case "audio/x-m4a", "audio/mp4": + return FileType.AUDIO.rawValue + case "video/mp4": + return FileType.VIDEO.rawValue + case "application/pdf": + return FileType.PDF.rawValue + case "text/x-markdown","text/plain": + return FileType.TEXT.rawValue + case "application/vnd.openxmlformats-officedocument.wordprocessingml.document": + return FileType.DOCX.rawValue + case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","text/csv": + return FileType.XLSX.rawValue + case "application/vnd.openxmlformats-officedocument.presentationml.presentation": + return FileType.PPT.rawValue + default: + return FileType.OTHER.rawValue + } + } + + private func getDate(date: Date) -> String { + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd" + return dateFormatter.string(from: date) + } + + private func getFileSizeInMB(bytes: Int) -> Float { + return round((Float(bytes) / Float(Size.MEGABYTE)) * 10) / 10 + } + +} + +// MARK: - MoEngage In-App Native Delegate +extension MoEngageAnalytics: MoEngageInAppNativeDelegate { + + // Called when user clicks an in-app with navigation action (e.g., deep link) + func inAppClicked(withCampaignInfo inappCampaign: MoEngageInAppCampaign, + andNavigationActionInfo navigationAction: MoEngageInAppNavigationAction, + forAccountMeta accountMeta: MoEngageAccountMeta) { + // handle navigation actions if needed + } + + // Called when user clicks an in-app with custom action (e.g., our rating trigger) + func inAppClicked(withCampaignInfo inappCampaign: MoEngageInAppCampaign, + andCustomActionInfo customAction: MoEngageInAppAction, + forAccountMeta accountMeta: MoEngageAccountMeta) { + + let kv = customAction.keyValuePairs + + if let showRating = kv["show-native-rating"] as? String, + showRating.lowercased() == "true" { + requestAppStoreReview() + } + } + + // Called when a "self-handled" in-app is triggered + func selfHandledInAppTriggered(withInfo inAppCampaign: MoEngageInAppSelfHandledCampaign, + forAccountMeta accountMeta: MoEngageAccountMeta) { + // no-op unless you use self-handled campaigns + } + + // Optional — track impression + func inAppShown(withCampaignInfo inappCampaign: MoEngageInAppCampaign, + forAccountMeta accountMeta: MoEngageAccountMeta) { + // no-op + } + + // Optional — track dismissal + func inAppDismissed(withCampaignInfo inappCampaign: MoEngageInAppCampaign, + forAccountMeta accountMeta: MoEngageAccountMeta) { + // no-op + } +} diff --git a/iOSClient/AppDelegate.swift b/iOSClient/AppDelegate.swift index 53087a9f8d..bc856ceb56 100644 --- a/iOSClient/AppDelegate.swift +++ b/iOSClient/AppDelegate.swift @@ -12,73 +12,78 @@ import WidgetKit import Queuer import EasyTipView import SwiftUI -import RealmSwift +import MoEngageInApps @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate { var backgroundSessionCompletionHandler: (() -> Void)? + var activeLogin: NCLogin? + var activeLoginWeb: NCLoginWeb? + var taskAutoUploadDate: Date = Date() + var orientationLock = UIInterfaceOrientationMask.all + @objc let adjust = AdjustHelper() var isUiTestingEnabled: Bool { return ProcessInfo.processInfo.arguments.contains("UI_TESTING") } var notificationSettings: UNNotificationSettings? + var pushKitToken: String? var loginFlowV2Token = "" var loginFlowV2Endpoint = "" var loginFlowV2Login = "" - let backgroundQueue = DispatchQueue(label: "com.nextcloud.bgTaskQueue") - let global = NCGlobal.shared - - var pushSubscriptionTask: Task? + let database = NCManageDatabase.shared + var window: UIWindow? + @objc var sceneIdentifier: String = "" + @objc var activeViewController: UIViewController? + @objc var account: String = "" + @objc var urlBase: String = "" + @objc var user: String = "" + @objc var userId: String = "" + @objc var password: String = "" + var timerErrorNetworking: Timer? + var tipView: EasyTipView? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { if isUiTestingEnabled { - Task { - await NCAccount().deleteAllAccounts() - } + NCAccount().deleteAllAccounts() } + UINavigationBar.appearance().tintColor = NCBrandColor.shared.customer + UIToolbar.appearance().tintColor = NCBrandColor.shared.customer + let utilityFileSystem = NCUtilityFileSystem() let utility = NCUtility() - - utilityFileSystem.createDirectoryStandard() - utilityFileSystem.emptyTemporaryDirectory() - utilityFileSystem.clearCacheDirectory("com.limit-point.LivePhoto") - - let versionNextcloudiOS = String(format: NCBrandOptions.shared.textCopyrightNextcloudiOS, utility.getVersionBuild()) + let versionNextcloudiOS = String(format: NCBrandOptions.shared.textCopyrightNextcloudiOS, utility.getVersionApp()) NCAppVersionManager.shared.checkAndUpdateInstallState() NCSettingsBundleHelper.checkAndExecuteSettings(delay: 0) UserDefaults.standard.register(defaults: ["UserAgent": userAgent]) - - #if !DEBUG - if !NCPreferences().disableCrashservice, !NCBrandOptions.shared.disable_crash_service { + if !NCKeychain().disableCrashservice, !NCBrandOptions.shared.disable_crash_service { FirebaseApp.configure() } - #endif + + utilityFileSystem.createDirectoryStandard() + utilityFileSystem.emptyTemporaryDirectory() + utilityFileSystem.clearCacheDirectory("com.limit-point.LivePhoto") NCBrandColor.shared.createUserColors() + NCImageCache.shared.createImagesCache() NextcloudKit.shared.setup(groupIdentifier: NCBrandOptions.shared.capabilitiesGroup, delegate: NCNetworking.shared) - NextcloudKit.configureLogger(logLevel: (NCBrandOptions.shared.disable_log ? .disabled : NCPreferences().log)) - - #if DEBUG -// For the tags look NCGlobal LOG TAG - -// var black: [String] = [] -// black.append("NETWORKING TASKS") -// NextcloudKit.configureLoggerBlacklist(blacklist: black) - -// var white: [String] = [] -// white.append("SYNC METADATA") -// NextcloudKit.configureLoggerWhitelist(whitelist: white) - #endif - - nkLog(start: "Start session with level \(NCPreferences().log) " + versionNextcloudiOS) + if NCBrandOptions.shared.disable_log { + utilityFileSystem.removeFile(atPath: NextcloudKit.shared.nkCommonInstance.filenamePathLog) + utilityFileSystem.removeFile(atPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! + "/" + NextcloudKit.shared.nkCommonInstance.filenameLog) + } else { + NextcloudKit.shared.setupLog(pathLog: utilityFileSystem.directoryGroup, + levelLog: NCKeychain().logLevel, + copyLogToDocumentDirectory: true) + NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Start session with level \(NCKeychain().logLevel) " + versionNextcloudiOS) + } - // Push Notification & display notification + /// Push Notification & display notification UNUserNotificationCenter.current().getNotificationSettings { settings in self.notificationSettings = settings } @@ -92,30 +97,49 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD review.showStoreReview() #endif - // BACKGROUND TASK - // - BGTaskScheduler.shared.register(forTaskWithIdentifier: global.refreshTask, using: backgroundQueue) { task in - guard let appRefreshTask = task as? BGAppRefreshTask else { - task.setTaskCompleted(success: false) - return - } - self.handleAppRefresh(appRefreshTask) + /// Background task register + BGTaskScheduler.shared.register(forTaskWithIdentifier: NCGlobal.shared.refreshTask, using: nil) { task in + self.handleAppRefresh(task) } - scheduleAppRefresh() - - BGTaskScheduler.shared.register(forTaskWithIdentifier: global.processingTask, using: backgroundQueue) { task in - guard let processingTask = task as? BGProcessingTask else { - task.setTaskCompleted(success: false) - return - } - self.handleProcessingTask(processingTask) + BGTaskScheduler.shared.register(forTaskWithIdentifier: NCGlobal.shared.processingTask, using: nil) { task in + self.handleProcessingTask(task) } - scheduleAppProcessing() if NCBrandOptions.shared.enforce_passcode_lock { - NCPreferences().requestPasscodeAtStart = true + NCKeychain().requestPasscodeAtStart = true } + /// Activation singleton + _ = NCNetworking.shared + _ = NCActionCenter.shared + _ = NCNetworkingProcess.shared + _ = NCTransferProgress.shared + _ = NCActionCenter.shared + + NCTransferProgress.shared.setup() + NCActionCenter.shared.setup() + +// if account.isEmpty { +// if NCBrandOptions.shared.disable_intro { +// openLogin(viewController: nil, selector: NCGlobal.shared.introLogin, openLoginWeb: false) +// } else { +// if let viewController = UIStoryboard(name: "NCIntro", bundle: nil).instantiateInitialViewController() { +// let navigationController = NCLoginNavigationController(rootViewController: viewController) +// window?.rootViewController = navigationController +// window?.makeKeyAndVisible() +// } +// } +// } else { +// NCPasscode.shared.presentPasscode(delegate: self) { +// NCPasscode.shared.enableTouchFaceID() +// } +// } + adjust.configAdjust() + adjust.subsessionStart() + TealiumHelper.shared.start() + FirebaseApp.configure() + + return true } @@ -129,7 +153,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD notificationCenter.add(req) } - nkLog(debug: "bye bye") + NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] bye bye") } // MARK: - UISceneSession Lifecycle @@ -152,14 +176,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD @discussion Schedule a refresh task request to ask that the system launch your app briefly so that you can download data and keep your app's contents up-to-date. The system will fulfill this request intelligently based on system conditions and app usage. */ func scheduleAppRefresh() { - let request = BGAppRefreshTaskRequest(identifier: global.refreshTask) + let request = BGAppRefreshTaskRequest(identifier: NCGlobal.shared.refreshTask) request.earliestBeginDate = Date(timeIntervalSinceNow: 60) // Refresh after 60 seconds. - do { try BGTaskScheduler.shared.submit(request) } catch { - nkLog(tag: self.global.logTagTask, emoji: .error, message: "Refresh task failed to submit request: \(error)") + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Refresh task failed to submit request: \(error)") } } @@ -167,28 +190,19 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD @discussion Schedule a processing task request to ask that the system launch your app when conditions are favorable for battery life to handle deferrable, longer-running processing, such as syncing, database maintenance, or similar tasks. The system will attempt to fulfill this request to the best of its ability within the next two days as long as the user has used your app within the past week. */ func scheduleAppProcessing() { - let request = BGProcessingTaskRequest(identifier: global.processingTask) + let request = BGProcessingTaskRequest(identifier: NCGlobal.shared.processingTask) request.earliestBeginDate = Date(timeIntervalSinceNow: 5 * 60) // Refresh after 5 minutes. request.requiresNetworkConnectivity = false request.requiresExternalPower = false - do { try BGTaskScheduler.shared.submit(request) } catch { - nkLog(tag: self.global.logTagTask, emoji: .error, message: "Processing task failed to submit request: \(error)") + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Background Processing task failed to submit request: \(error)") } } - func handleAppRefresh(_ task: BGAppRefreshTask) { - nkLog(tag: self.global.logTagTask, emoji: .start, message: "Start refresh task") - guard NCManageDatabase.shared.openRealmBackground() else { - nkLog(tag: self.global.logTagTask, emoji: .error, message: "Failed to open Realm in background") - task.setTaskCompleted(success: false) - return - } - - // Schedule next refresh + func handleAppRefresh(_ task: BGTask) { scheduleAppRefresh() Task { @@ -200,15 +214,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD } } - func handleProcessingTask(_ task: BGProcessingTask) { - nkLog(tag: self.global.logTagTask, emoji: .start, message: "Start processing task") - guard NCManageDatabase.shared.openRealmBackground() else { - nkLog(tag: self.global.logTagTask, emoji: .error, message: "Failed to open Realm in background") - task.setTaskCompleted(success: false) - return - } - - // Schedule next processing task + func handleProcessingTask(_ task: BGTask) { scheduleAppProcessing() Task { @@ -264,7 +270,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD return } } - + // Capacity computation let downloading = allMetadatas.lazy.filter { $0.status == self.global.metadataStatusDownloading }.count let uploading = allMetadatas.lazy.filter { $0.status == self.global.metadataStatusUploading }.count @@ -307,6 +313,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD nkLog(tag: self.global.logTagBgSync, emoji: .error, message: "Upload failed \(metadata.fileName) -> \(metadata.serverUrl) [\(err.errorDescription)]") } } + + let counter = NCManageDatabase.shared.getResultsMetadatas(predicate: NSPredicate(format: "account == %@ AND (session == %@ || session == %@) AND status != %d", + account, + NCNetworking.shared.sessionDownloadBackground, + NCNetworking.shared.sessionUploadBackground, + NCGlobal.shared.metadataStatusNormal))?.count ?? 0 + UIApplication.shared.applicationIconBadgeNumber = counter + + NextcloudKit.shared.nkCommonInstance.writeLog("[DEBUG] \(taskText) completion handle") + completion() } } @@ -335,22 +351,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD } func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { - if let deviceToken = NCPushNotificationEncryption.shared().string(withDeviceToken: deviceToken) { - NCPreferences().deviceTokenPushNotification = deviceToken - pushSubscriptionTask = Task.detached { - // Wait bounded time for maintenance to be OFF - let canProceed = await NCAppStateManager.shared.waitForMaintenanceOffAsync() - guard canProceed else { - nkLog(error: "[PUSH] Skipping subscription: maintenance mode still ON after timeout") - return - } - - try? await Task.sleep(nanoseconds: 1_000_000_000) - - let tblAccounts = await NCManageDatabase.shared.getAllTableAccountAsync() - for tblAccount in tblAccounts { - await NCPushNotification.shared.subscribingNextcloudServerPushNotification(account: tblAccount.account, urlBase: tblAccount.urlBase) - } + if let pushKitToken = NCPushNotificationEncryption.shared().string(withDeviceToken: deviceToken) { + self.pushKitToken = pushKitToken + // https://github.com/nextcloud/talk-ios/issues/691 + for tblAccount in NCManageDatabase.shared.getAllTableAccount() { + subscribingPushNotification(account: tblAccount.account, urlBase: tblAccount.urlBase, user: tblAccount.user) } } } @@ -361,6 +366,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD } } + func subscribingPushNotification(account: String, urlBase: String, user: String) { +#if !targetEnvironment(simulator) + NCNetworking.shared.checkPushNotificationServerProxyCertificateUntrusted(viewController: UIApplication.shared.firstWindow?.rootViewController) { error in + if error == .success { + NCPushNotification.shared.subscribingNextcloudServerPushNotification(account: account, urlBase: urlBase, user: user, pushKitToken: self.pushKitToken) + } + } +#endif + } + func nextcloudPushNotificationAction(data: [String: AnyObject]) { guard let data = NCApplicationHandle().nextcloudPushNotificationAction(data: data) else { @@ -371,12 +386,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD func openNotification(controller: NCMainTabBarController) { if app == NCGlobal.shared.termsOfServiceName { - Task { - await NCNetworking.shared.transferDispatcher.notifyAllDelegatesAsync { delegate in - try? await Task.sleep(nanoseconds: 500_000_000) - delegate.transferRequestData(serverUrl: nil) - } - } + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterGetServerData, second: 0.5) } else if let navigationController = UIStoryboard(name: "NCNotification", bundle: nil).instantiateInitialViewController() as? UINavigationController, let viewController = navigationController.topViewController as? NCNotification { viewController.modalPresentationStyle = .pageSheet @@ -389,10 +399,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD if let controller = SceneManager.shared.getControllers().first(where: { $0.account == account }) { openNotification(controller: controller) - } else if let tblAccount = NCManageDatabase.shared.getAllTableAccount().first(where: { $0.account == account }), + } else if let tableAccount = NCManageDatabase.shared.getAllTableAccount().first(where: { $0.account == account }), let controller = UIApplication.shared.firstWindow?.rootViewController as? NCMainTabBarController { - Task { @MainActor in - await NCAccount().changeAccount(tblAccount.account, userProfile: nil, controller: controller) + NCAccount().changeAccount(tableAccount.account, userProfile: nil, controller: controller) { openNotification(controller: controller) } } else { @@ -403,11 +412,180 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD } } + // MARK: - Login + + func openLogin(selector: Int, window: UIWindow? = nil) { + UIApplication.shared.allSceneSessionDestructionExceptFirst() + +// func showLoginViewController(_ viewController: UIViewController?) { +// guard let viewController else { return } +// let navigationController = NCLoginNavigationController(rootViewController: viewController) +// +// navigationController.modalPresentationStyle = .fullScreen +// navigationController.navigationBar.barStyle = .black +// navigationController.navigationBar.tintColor = NCBrandColor.shared.customerText +// navigationController.navigationBar.barTintColor = NCBrandColor.shared.customer +// navigationController.navigationBar.isTranslucent = false +// +// if let controller = UIApplication.shared.firstWindow?.rootViewController { +// if let presentedVC = controller.presentedViewController, !(presentedVC is NCLoginNavigationController) { +// presentedVC.dismiss(animated: false) { +// controller.present(navigationController, animated: true) +// } +// } else { +// controller.present(navigationController, animated: true) +// } +// } else { +// window?.rootViewController = navigationController +// window?.makeKeyAndVisible() +// } +// } + + // Nextcloud standard login + if selector == NCGlobal.shared.introSignup { + if activeLogin?.view.window == nil { + if selector == NCGlobal.shared.introSignup { + let web = UIStoryboard(name: "NCLogin", bundle: nil).instantiateViewController(withIdentifier: "NCLoginProvider") as? NCLoginProvider + web?.urlBase = NCBrandOptions.shared.linkloginPreferredProviders + showLoginViewController(web) + } else { + activeLogin = UIStoryboard(name: "NCLogin", bundle: nil).instantiateViewController(withIdentifier: "NCLogin") as? NCLogin + if let controller = UIApplication.shared.firstWindow?.rootViewController as? NCMainTabBarController, !controller.account.isEmpty { + let session = NCSession.shared.getSession(account: controller.account) + activeLogin?.urlBase = session.urlBase + } + showLoginViewController(activeLogin) + } + } + } else { + if activeLogin?.view.window == nil { + activeLogin = UIStoryboard(name: "NCLogin", bundle: nil).instantiateViewController(withIdentifier: "NCLogin") as? NCLogin + activeLogin?.urlBase = NCBrandOptions.shared.disable_request_login_url ? NCBrandOptions.shared.loginBaseUrl : "" + showLoginViewController(activeLogin) + } + } + } + + @objc func openLogin(viewController: UIViewController?, selector: Int, openLoginWeb: Bool) { +// openLogin(selector: NCGlobal.shared.introLogin) + // [WEBPersonalized] [AppConfig] + if NCBrandOptions.shared.use_login_web_personalized || NCBrandOptions.shared.use_AppConfig { + + if activeLoginWeb?.view.window == nil { + activeLoginWeb = UIStoryboard(name: "NCLogin", bundle: nil).instantiateViewController(withIdentifier: "NCLoginWeb") as? NCLoginWeb + activeLoginWeb?.urlBase = NCBrandOptions.shared.loginBaseUrl + showLoginViewController(activeLoginWeb, contextViewController: viewController) + } + return + } + + // Nextcloud standard login + if selector == NCGlobal.shared.introSignup { + + if activeLoginWeb?.view.window == nil { + activeLoginWeb = UIStoryboard(name: "NCLogin", bundle: nil).instantiateViewController(withIdentifier: "NCLoginWeb") as? NCLoginWeb + if selector == NCGlobal.shared.introSignup { + activeLoginWeb?.urlBase = NCBrandOptions.shared.linkloginPreferredProviders + } else { + activeLoginWeb?.urlBase = self.urlBase + } + showLoginViewController(activeLoginWeb, contextViewController: viewController) + } + + } else if NCBrandOptions.shared.disable_intro && NCBrandOptions.shared.disable_request_login_url { + + if activeLoginWeb?.view.window == nil { + activeLoginWeb = UIStoryboard(name: "NCLogin", bundle: nil).instantiateViewController(withIdentifier: "NCLoginWeb") as? NCLoginWeb + activeLoginWeb?.urlBase = NCBrandOptions.shared.loginBaseUrl + showLoginViewController(activeLoginWeb, contextViewController: viewController) + } + + } else if openLoginWeb { + + // Used also for reinsert the account (change passwd) + if activeLoginWeb?.view.window == nil { + activeLoginWeb = UIStoryboard(name: "NCLogin", bundle: nil).instantiateViewController(withIdentifier: "NCLoginWeb") as? NCLoginWeb + activeLoginWeb?.urlBase = urlBase + activeLoginWeb?.user = user + showLoginViewController(activeLoginWeb, contextViewController: viewController) + } + + } else { + + if activeLogin?.view.window == nil { + activeLogin = UIStoryboard(name: "NCLogin", bundle: nil).instantiateViewController(withIdentifier: "NCLogin") as? NCLogin + showLoginViewController(activeLogin, contextViewController: viewController) + } + } + } + + func showLoginViewController(_ viewController: UIViewController?) { + guard let viewController else { return } + let navigationController = NCLoginNavigationController(rootViewController: viewController) + + navigationController.modalPresentationStyle = .fullScreen + navigationController.navigationBar.barStyle = .black + navigationController.navigationBar.tintColor = NCBrandColor.shared.customerText + navigationController.navigationBar.barTintColor = NCBrandColor.shared.customer + navigationController.navigationBar.isTranslucent = false + + if let controller = UIApplication.shared.firstWindow?.rootViewController { + if let presentedVC = controller.presentedViewController, !(presentedVC is NCLoginNavigationController) { + presentedVC.dismiss(animated: false) { + controller.present(navigationController, animated: true) + } + } else { + controller.present(navigationController, animated: true) + } + } else { + window?.rootViewController = navigationController + window?.makeKeyAndVisible() + } + } + + func showLoginViewController(_ viewController: UIViewController?, contextViewController: UIViewController?) { + + if contextViewController == nil { + if let viewController = viewController { + let navigationController = NCLoginNavigationController(rootViewController: viewController) + navigationController.navigationBar.barStyle = .black + navigationController.navigationBar.tintColor = NCBrandColor.shared.customerText + navigationController.navigationBar.barTintColor = NCBrandColor.shared.customer + navigationController.navigationBar.isTranslucent = false + window?.rootViewController = navigationController + window?.makeKeyAndVisible() + } + } else if contextViewController is UINavigationController { + if let contextViewController = contextViewController, let viewController = viewController { + (contextViewController as? UINavigationController)?.pushViewController(viewController, animated: true) + } + } else { + if let viewController = viewController, let contextViewController = contextViewController { + let navigationController = NCLoginNavigationController(rootViewController: viewController) + navigationController.modalPresentationStyle = .fullScreen + navigationController.navigationBar.barStyle = .black + navigationController.navigationBar.tintColor = NCBrandColor.shared.customerText + navigationController.navigationBar.barTintColor = NCBrandColor.shared.customer + navigationController.navigationBar.isTranslucent = false + contextViewController.present(navigationController, animated: true) { } + } + } + } + + @objc func startTimerErrorNetworking() { + timerErrorNetworking = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(checkErrorNetworking), userInfo: nil, repeats: true) + } + + @objc private func checkErrorNetworking() { + guard !account.isEmpty, NCKeychain().getPassword(account: account).isEmpty else { return } + openLogin(viewController: window?.rootViewController, selector: NCGlobal.shared.introLogin, openLoginWeb: true) + } + // MARK: - func trustCertificateError(host: String) { - guard let activeTblAccount = NCManageDatabase.shared.getActiveTableAccount(), - let currentHost = URL(string: activeTblAccount.urlBase)?.host, + guard let activeTableAccount = NCManageDatabase.shared.getActiveTableAccount(), + let currentHost = URL(string: activeTableAccount.urlBase)?.host, let pushNotificationServerProxyHost = URL(string: NCBrandOptions.shared.pushNotificationServerProxy)?.host, host != pushNotificationServerProxyHost, host == currentHost @@ -438,10 +616,31 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD UIApplication.shared.firstWindow?.rootViewController?.present(alertController, animated: true) } + + // MARK: - Account + + @objc func changeAccount(_ account: String, userProfile: NKUserProfile?) { +// NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterChangeUser) + } + + @objc func deleteAccount(_ account: String, wipe: Bool) { + NCAccount().deleteAccount(account, wipe: wipe) + } + + func deleteAllAccounts() { + let accounts = NCManageDatabase.shared.getAccounts() + accounts?.forEach({ account in + deleteAccount(account, wipe: true) + }) + } + + func updateShareAccounts() -> Error? { + return NCAccount().updateAppsShareAccounts() + } // MARK: - Reset Application - func resetApplication() { + @objc func resetApplication() { let utilityFileSystem = NCUtilityFileSystem() NCNetworking.shared.cancelAllTask() @@ -453,7 +652,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD utilityFileSystem.removeDocumentsDirectory() utilityFileSystem.removeTemporaryDirectory() - NCPreferences().removeAll() + NCKeychain().removeAll() + NCNetworking.shared.removeAllKeyUserDefaultsData(account: nil) exit(0) } @@ -476,10 +676,14 @@ extension AppDelegate: NCViewCertificateDetailsDelegate { extension AppDelegate: NCCreateFormUploadConflictDelegate { func dismissCreateFormUploadConflict(metadatas: [tableMetadata]?) { - if let metadatas { - Task { - await NCManageDatabase.shared.addMetadatasAsync(metadatas) - } - } + guard let metadatas = metadatas, !metadatas.isEmpty else { return } + NCNetworkingProcess.shared.createProcessUploads(metadatas: metadatas) + } +} + +//MARK: NMC Customisation +extension AppDelegate { + func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { + return self.orientationLock } } diff --git a/iOSClient/AppUpdate/AppUpdater.swift b/iOSClient/AppUpdate/AppUpdater.swift new file mode 100644 index 0000000000..15dd5f6991 --- /dev/null +++ b/iOSClient/AppUpdate/AppUpdater.swift @@ -0,0 +1,104 @@ +// +// AppUpdater.swift +// Nextcloud +// +// Created by Amrut Waghmare on 09/10/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +import Foundation +import FirebaseRemoteConfig + +struct AppUpdaterKey { + static let lastUpdateCheckDate : String = "lastUpdateCheckDate" +} + +class AppUpdater { + func checkForUpdate() { + checkUpdate{ (version, isForceupdate) in + DispatchQueue.main.async { + if let version = version, let isForceupdate = isForceupdate { + if (isForceupdate) { + self.showUpdateAlert(version: version, isForceUpdate: isForceupdate) + } else { + if self.checkLastUpdate() { + self.showUpdateAlert(version: version, isForceUpdate: isForceupdate) + } + } + } + } + } + } + + func showUpdateAlert(version: String, isForceUpdate: Bool){ + guard let appDelegate = UIApplication.shared.delegate as? AppDelegate, let viewControlller = appDelegate.window?.rootViewController else { return } + let descriptionMsg = String(format: NSLocalizedString("update_description", comment: ""), version) + let alert = UIAlertController(title: NSLocalizedString("update_available", comment: ""), message: descriptionMsg, preferredStyle: .alert) + let updateAction = UIAlertAction(title: NSLocalizedString("update", comment: ""), style: .default, handler: { action in + guard let url = URL(string: NCBrandOptions.shared.appStoreUrl) else { return } + UIApplication.shared.open(url) + }) + alert.addAction(updateAction) + if !isForceUpdate { + alert.addAction(UIAlertAction(title: NSLocalizedString("not_now", comment: ""), style: .default, handler: { action in + self.saveAppUpdateCheckDate() + })) + } + alert.preferredAction = updateAction + viewControlller.present(alert, animated: true, completion: {}) + } + + func checkLastUpdate() -> Bool { + if let lastUpdateCheckDate = UserDefaults.standard.object(forKey: AppUpdaterKey.lastUpdateCheckDate) as? Date { + return daysBetweenDate(from: lastUpdateCheckDate) > 7 + } else { + return true + } + } + + func checkUpdate(completion: @escaping (String?, Bool?) -> Void) { + let remoteConfig = RemoteConfig.remoteConfig() + remoteConfig.fetch(withExpirationDuration: 1) { (status, error) in + if status == .success { + remoteConfig.activate { value, error in + // Remote config values fetched successfully + let iOSVersionString = remoteConfig["ios_app_version"].stringValue ?? "default_value" + let isForcheUpdate = remoteConfig["ios_force_update"].boolValue + if let currentVersionString = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String, + let currentVersion = Int(currentVersionString.replacingOccurrences(of: ".", with: "")), + let iOSVersion = Int(iOSVersionString.replacingOccurrences(of: ".", with: "")) { +// if let currentVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String { + if iOSVersion != currentVersion { + // There is an update available + completion(iOSVersionString,isForcheUpdate) + } else { + completion(nil, nil) + } + } +// let iOSVersion = remoteConfig["ios_app_version"].stringValue ?? "default_value" +// let isForcheUpdate = remoteConfig["ios_force_update"].boolValue +// if let currentVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String { +// if iOSVersion != currentVersion { +// // There is an update available +// completion(iOSVersion,isForcheUpdate) +// } else { +// completion(nil, nil) +// } +// } + } + } else { + // Handle error + print("Error fetching remote config: \(error?.localizedDescription ?? "Unknown error")") + completion(nil, nil) + } + } + } + + func saveAppUpdateCheckDate() { + UserDefaults.standard.setValue(Date(), forKey: AppUpdaterKey.lastUpdateCheckDate) + } + + func daysBetweenDate(from date: Date) -> Int { + return Calendar.current.dateComponents([.day], from: date, to: Date()).day ?? 0 + } +} diff --git a/iOSClient/AppUtility.swift b/iOSClient/AppUtility.swift new file mode 100644 index 0000000000..bb7c625e53 --- /dev/null +++ b/iOSClient/AppUtility.swift @@ -0,0 +1,21 @@ +// +// AppUtility.swift +// Nextcloud +// +// Created by Amrut Waghmare on 17/10/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +import Foundation +struct AppUtility { + static func lockOrientation(_ orientation: UIInterfaceOrientationMask) { + if let delegate = UIApplication.shared.delegate as? AppDelegate { + delegate.orientationLock = orientation + } + } + + static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) { + self.lockOrientation(orientation) + UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation") + } +} diff --git a/iOSClient/AudioRecorder/NCAudioRecorderViewController.swift b/iOSClient/AudioRecorder/NCAudioRecorderViewController.swift index 64d4698235..8e47df5e17 100644 --- a/iOSClient/AudioRecorder/NCAudioRecorderViewController.swift +++ b/iOSClient/AudioRecorder/NCAudioRecorderViewController.swift @@ -1,7 +1,24 @@ -// SPDX-FileCopyrightText: Nextcloud GmbH -// SPDX-FileCopyrightText: 2019 Marino Faggiana -// SPDX-License-Identifier: GPL-3.0-or-later - +// +// NCAudioRecorderViewController.swift +// Nextcloud +// +// Created by Marino Faggiana on 08/03/19. +// Copyright (c) 2019 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . // // -------------------------------- // Based on code of Venkat Kukunuru @@ -13,6 +30,7 @@ import QuartzCore import NextcloudKit class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate { + @IBOutlet weak var contentContainerView: UIView! @IBOutlet weak var durationLabel: UILabel! @IBOutlet weak var startStopLabel: UILabel! @@ -22,12 +40,10 @@ class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate { var startDate: Date = Date() var fileName: String = "" var controller: NCMainTabBarController! - let database = NCManageDatabase.shared - - @MainActor var session: NCSession.Session { NCSession.shared.getSession(controller: controller) } + let appDelegate = (UIApplication.shared.delegate as? AppDelegate)! // MARK: - View Life Cycle @@ -40,18 +56,16 @@ class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate { view.backgroundColor = .clear contentContainerView.backgroundColor = UIColor.lightGray - voiceRecordHUD.fillColor = UIColor.green + voiceRecordHUD.fillColor = NCBrandColor.shared.progressColorGreen60 - Task { - self.fileName = await NCNetworking.shared.createFileName(fileNameBase: NSLocalizedString("_untitled_", comment: "") + ".m4a", account: self.session.account, serverUrl: controller.currentServerUrl()) - recording = NCAudioRecorder(to: self.fileName) - recording.delegate = self - do { - try self.recording.prepare() - startStopLabel.text = NSLocalizedString("_voice_memo_start_", comment: "") - } catch { - print(error) - } + self.fileName = NCUtilityFileSystem().createFileNameDate(NSLocalizedString("_voice_memo_filename_", comment: ""), ext: "m4a") + recording = NCAudioRecorder(to: self.fileName) + recording.delegate = self + do { + try self.recording.prepare() + startStopLabel.text = NSLocalizedString("_voice_memo_start_", comment: "") + } catch { + print(error) } } @@ -69,8 +83,12 @@ class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate { if recording.state == .record { recording.stop() voiceRecordHUD.update(0.0) - dismiss(animated: true) { - self.uploadMetadata() + dismiss(animated: true) { [self] in + 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: controller.currentServerUrl(), fileNamePath: NSTemporaryDirectory() + self.fileName, fileName: self.fileName) + UIApplication.shared.firstWindow?.rootViewController?.present(navigationController, animated: true) } } else { do { @@ -123,7 +141,7 @@ class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate { } voiceRecordHUD.update(CGFloat(rate)) - voiceRecordHUD.fillColor = UIColor.green + voiceRecordHUD.fillColor = NCBrandColor.shared.progressColorGreen60 let formatter = DateComponentsFormatter() formatter.allowedUnits = [.second] @@ -137,7 +155,8 @@ class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate { } open class NCAudioRecorder: NSObject { - public enum State: Int { + + @objc public enum State: Int { case none, record, play } diff --git a/iOSClient/BrowserWeb/NCBrowserWeb.swift b/iOSClient/BrowserWeb/NCBrowserWeb.swift index 206197c76c..10ee6d71ca 100644 --- a/iOSClient/BrowserWeb/NCBrowserWeb.swift +++ b/iOSClient/BrowserWeb/NCBrowserWeb.swift @@ -1,6 +1,25 @@ -// SPDX-FileCopyrightText: Nextcloud GmbH -// SPDX-FileCopyrightText: 2019 Marino Faggiana -// SPDX-License-Identifier: GPL-3.0-or-later +// +// NCBrowserWeb.swift +// Nextcloud +// +// Created by Marino Faggiana on 22/08/2019. +// Copyright (c) 2019 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// import UIKit @preconcurrency import WebKit @@ -36,7 +55,7 @@ class NCBrowserWeb: UIViewController { buttonExit.isHidden = true } else { self.view.bringSubviewToFront(buttonExit) - let image = NCUtility().loadImage(named: "xmark", colors: [.systemBlue]) + let image = NCUtility().loadImage(named: "xmark", colors: [NCBrandColor.shared.customer]) buttonExit.setImage(image, for: .normal) } diff --git a/iOSClient/Data/NCManageDatabase+Metadata.swift b/iOSClient/Data/NCManageDatabase+Metadata.swift index 8540380db0..d4b8f1ae20 100644 --- a/iOSClient/Data/NCManageDatabase+Metadata.swift +++ b/iOSClient/Data/NCManageDatabase+Metadata.swift @@ -1,12 +1,30 @@ -// SPDX-FileCopyrightText: Nextcloud GmbH -// SPDX-FileCopyrightText: 2021 Marino Faggiana -// SPDX-License-Identifier: GPL-3.0-or-later +// +// NCManageDatabase+Metadata.swift +// Nextcloud +// +// Created by Henrik Storch on 30.11.21. +// Copyright © 2021 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// import Foundation import UIKit import RealmSwift import NextcloudKit -import Photos class tableMetadata: Object { override func isEqual(_ object: Any?) -> Bool { @@ -33,7 +51,8 @@ class tableMetadata: Object { self.altitude == object.altitude, self.status == object.status, Array(self.tags).elementsEqual(Array(object.tags)), - Array(self.shareType).elementsEqual(Array(object.shareType)) { + Array(self.shareType).elementsEqual(Array(object.shareType)), + Array(self.sharePermissionsCloudMesh).elementsEqual(Array(object.sharePermissionsCloudMesh)) { return true } else { return false @@ -56,6 +75,7 @@ class tableMetadata: Object { @objc dynamic var e2eEncrypted: Bool = false @objc dynamic var edited: Bool = false @objc dynamic var etag = "" + @objc dynamic var etagResource = "" let exifPhotos = List() @objc dynamic var favorite: Bool = false @objc dynamic var fileId = "" @@ -82,7 +102,6 @@ class tableMetadata: Object { @objc public var lockOwnerDisplayName = "" @objc public var lockTime: Date? @objc public var lockTimeOut: Date? - @objc dynamic var mediaSearch: Bool = false @objc dynamic var path = "" @objc dynamic var permissions = "" @objc dynamic var placePhotos: String? @@ -92,15 +111,15 @@ class tableMetadata: Object { @objc dynamic var richWorkspace: String? @objc dynamic var sceneIdentifier: String? @objc dynamic var serverUrl = "" - @objc dynamic var serverUrlFileName = "" - @objc dynamic var destination = "" + @objc dynamic var serveUrlFileName = "" + @objc dynamic var serverUrlTo = "" @objc dynamic var session = "" @objc dynamic var sessionDate: Date? @objc dynamic var sessionError = "" @objc dynamic var sessionSelector = "" @objc dynamic var sessionTaskIdentifier: Int = 0 - /// The integer for sharing permissions. @objc dynamic var sharePermissionsCollaborationServices: Int = 0 + let sharePermissionsCloudMesh = List() let shareType = List() @objc dynamic var size: Int64 = 0 @objc dynamic var status: Int = 0 @@ -123,8 +142,6 @@ class tableMetadata: Object { @objc dynamic var errorCode: Int = 0 @objc dynamic var nativeFormat: Bool = false @objc dynamic var autoUploadServerUrlBase: String? - @objc dynamic var typeIdentifier: String = "" - @objc dynamic var progress: Double = 0 override static func primaryKey() -> String { return "ocId" @@ -141,9 +158,6 @@ extension tableMetadata { } var isRenameable: Bool { - if !NCMetadataPermissions.canRename(self) { - return false - } if lock { return false } @@ -153,76 +167,121 @@ extension tableMetadata { return true } + + var isPrintable: Bool { + if isDocumentViewableOnly { + return false + } + if ["application/pdf", "com.adobe.pdf"].contains(contentType) || contentType.hasPrefix("text/") || classFile == NKCommon.TypeClassFile.image.rawValue { + return true + } + return false + } + var isSavebleInCameraRoll: Bool { - return (classFile == NKTypeClassFile.image.rawValue && contentType != "image/svg+xml") || classFile == NKTypeClassFile.video.rawValue + return (classFile == NKCommon.TypeClassFile.image.rawValue && contentType != "image/svg+xml") || classFile == NKCommon.TypeClassFile.video.rawValue + } + + + var isDocumentViewableOnly: Bool { + sharePermissionsCollaborationServices == NCPermissions().permissionReadShare && classFile == NKCommon.TypeClassFile.document.rawValue + } + + var isDocumentViewableOnly: Bool { + sharePermissionsCollaborationServices == NCPermissions().permissionReadShare && classFile == NKCommon.TypeClassFile.document.rawValue } var isAudioOrVideo: Bool { - return classFile == NKTypeClassFile.audio.rawValue || classFile == NKTypeClassFile.video.rawValue + return classFile == NKCommon.TypeClassFile.audio.rawValue || classFile == NKCommon.TypeClassFile.video.rawValue } var isImageOrVideo: Bool { - return classFile == NKTypeClassFile.image.rawValue || classFile == NKTypeClassFile.video.rawValue + return classFile == NKCommon.TypeClassFile.image.rawValue || classFile == NKCommon.TypeClassFile.video.rawValue } var isVideo: Bool { - return classFile == NKTypeClassFile.video.rawValue + return classFile == NKCommon.TypeClassFile.video.rawValue } var isAudio: Bool { - return classFile == NKTypeClassFile.audio.rawValue + return classFile == NKCommon.TypeClassFile.audio.rawValue } var isImage: Bool { - return classFile == NKTypeClassFile.image.rawValue + return classFile == NKCommon.TypeClassFile.image.rawValue } var isSavebleAsImage: Bool { - classFile == NKTypeClassFile.image.rawValue && contentType != "image/svg+xml" + classFile == NKCommon.TypeClassFile.image.rawValue && contentType != "image/svg+xml" } var isCopyableInPasteboard: Bool { - !directory + !isDocumentViewableOnly && !directory } var isCopyableMovable: Bool { - !isDirectoryE2EE && !e2eEncrypted + !isDocumentViewableOnly && !isDirectoryE2EE && !e2eEncrypted } var isModifiableWithQuickLook: Bool { - if directory || isDirectoryE2EE { + if directory || isDocumentViewableOnly || isDirectoryE2EE { return false } return isPDF || isImage } - var isCreatable: Bool { - if isDirectory { - return NCMetadataPermissions.canCreateFolder(self) - } else { - return NCMetadataPermissions.canCreateFile(self) - } - } - var isDeletable: Bool { - if (!isDirectoryE2EE && e2eEncrypted) || !NCMetadataPermissions.canDelete(self) { + if !isDirectoryE2EE && e2eEncrypted { return false } return true } var canSetAsAvailableOffline: Bool { +// return session.isEmpty && !isDirectoryE2EE && !e2eEncrypted + return session.isEmpty && !isDocumentViewableOnly +// return session.isEmpty && !isDocumentViewableOnly //!isDirectoryE2EE && !e2eEncrypted return session.isEmpty && !isDirectoryE2EE && !e2eEncrypted } var canShare: Bool { - return session.isEmpty && !directory && !NCBrandOptions.shared.disable_openin_file + return session.isEmpty && !isDocumentViewableOnly && !directory && !NCBrandOptions.shared.disable_openin_file + } + + var canSetDirectoryAsE2EE: Bool { + return directory && size == 0 && !e2eEncrypted && NCKeychain().isEndToEndEnabled(account: account) } var canUnsetDirectoryAsE2EE: Bool { - return !isDirectoryE2EE && directory && size == 0 && e2eEncrypted && NCPreferences().isEndToEndEnabled(account: account) + return !isDirectoryE2EE && directory && size == 0 && e2eEncrypted && NCKeychain().isEndToEndEnabled(account: account) } + var canOpenExternalEditor: Bool { + if isDocumentViewableOnly { + return false + } + let utility = NCUtility() + let editors = utility.editorsDirectEditing(account: account, contentType: contentType) + let isRichDocument = utility.isTypeFileRichDocument(self) + return classFile == NKCommon.TypeClassFile.document.rawValue && editors.contains(NCGlobal.shared.editorText) && ((editors.contains(NCGlobal.shared.editorOnlyoffice) || isRichDocument)) + } + + var isWaitingTransfer: Bool { + status == NCGlobal.shared.metadataStatusWaitDownload || status == NCGlobal.shared.metadataStatusWaitUpload || status == NCGlobal.shared.metadataStatusUploadError + } + + var isInTransfer: Bool { + status == NCGlobal.shared.metadataStatusDownloading || status == NCGlobal.shared.metadataStatusUploading + } + + var isTransferInForeground: Bool { + (status > 0 && (chunk > 0 || e2eEncrypted)) + } + + var isDownloadUpload: Bool { + status == NCGlobal.shared.metadataStatusDownloading || status == NCGlobal.shared.metadataStatusUploading + } + var isDownload: Bool { status == NCGlobal.shared.metadataStatusWaitDownload || status == NCGlobal.shared.metadataStatusDownloading } @@ -236,7 +295,12 @@ extension tableMetadata { } @objc var isDirectoryE2EE: Bool { - return NCUtilityFileSystem().isDirectoryE2EE(serverUrl: serverUrl, urlBase: urlBase, userId: userId, account: account) + let session = NCSession.Session(account: account, urlBase: urlBase, user: user, userId: userId) + return NCUtilityFileSystem().isDirectoryE2EE(session: session, serverUrl: serverUrl) + } + + var isDirectoryE2EETop: Bool { + NCUtilityFileSystem().isDirectoryE2EETop(account: account, serverUrl: serverUrl) } var isLivePhoto: Bool { @@ -252,27 +316,21 @@ extension tableMetadata { } var hasPreviewBorder: Bool { - !isImage && !isAudioOrVideo && hasPreview && NCUtilityFileSystem().fileProviderStorageImageExists(ocId, etag: etag, ext: NCGlobal.shared.previewExt1024, userId: userId, urlBase: urlBase) + !isImage && !isAudioOrVideo && hasPreview && NCUtilityFileSystem().fileProviderStorageImageExists(ocId, etag: etag, ext: NCGlobal.shared.previewExt1024) } var isAvailableEditorView: Bool { guard !isPDF, - classFile == NKTypeClassFile.document.rawValue, - NextcloudKit.shared.isNetworkReachable() else { - return false - } + classFile == NKCommon.TypeClassFile.document.rawValue, + NextcloudKit.shared.isNetworkReachable() else { return false } let utility = NCUtility() - let directEditingEditors = utility.editorsDirectEditing(account: account, contentType: contentType).map { $0.lowercased() } + let directEditingEditors = utility.editorsDirectEditing(account: account, contentType: contentType) let richDocumentEditor = utility.isTypeFileRichDocument(self) - let capabilities = NCNetworking.shared.capabilities[account] - if let capabilities, - capabilities.richDocumentsEnabled, - richDocumentEditor, - directEditingEditors.isEmpty { + if NCCapabilities.shared.getCapabilities(account: account).capabilityRichDocumentsEnabled && richDocumentEditor && directEditingEditors.isEmpty { // RichDocument: Collabora return true - } else if directEditingEditors.contains("nextcloud text") || directEditingEditors.contains("onlyoffice") { + } else if directEditingEditors.contains(NCGlobal.shared.editorText) || directEditingEditors.contains(NCGlobal.shared.editorOnlyoffice) { // DirectEditing: Nextcloud Text - OnlyOffice return true } @@ -280,9 +338,8 @@ extension tableMetadata { } var isAvailableRichDocumentEditorView: Bool { - guard let capabilities = NCNetworking.shared.capabilities[account], - classFile == NKTypeClassFile.document.rawValue, - capabilities.richDocumentsEnabled, + guard classFile == NKCommon.TypeClassFile.document.rawValue, + NCCapabilities.shared.getCapabilities(account: account).capabilityRichDocumentsEnabled, NextcloudKit.shared.isNetworkReachable() else { return false } if NCUtility().isTypeFileRichDocument(self) { @@ -292,12 +349,10 @@ extension tableMetadata { } var isAvailableDirectEditingEditorView: Bool { - guard (classFile == NKTypeClassFile.document.rawValue) && NextcloudKit.shared.isNetworkReachable() else { - return false - } - let editors = NCUtility().editorsDirectEditing(account: account, contentType: contentType).map { $0.lowercased() } + guard (classFile == NKCommon.TypeClassFile.document.rawValue) && NextcloudKit.shared.isNetworkReachable() else { return false } + let editors = NCUtility().editorsDirectEditing(account: account, contentType: contentType) - if editors.contains("nextcloud text") || editors.contains("onlyoffice") { + if editors.contains(NCGlobal.shared.editorText) || editors.contains(NCGlobal.shared.editorOnlyoffice) { return true } return false @@ -314,13 +369,13 @@ extension tableMetadata { // Return if is sharable func isSharable() -> Bool { - guard let capabilities = NCNetworking.shared.capabilities[account] else { + if !NCCapabilities.shared.getCapabilities(account: account).capabilityFileSharingApiEnabled || (NCCapabilities.shared.getCapabilities(account: account).capabilityE2EEEnabled && isDirectoryE2EE), !e2eEncrypted { return false } if !capabilities.fileSharingApiEnabled || (capabilities.e2EEEnabled && isDirectoryE2EE) { return false } - return true + return !e2eEncrypted } /// Returns a detached (unmanaged) deep copy of the current `tableMetadata` object. @@ -339,137 +394,372 @@ extension tableMetadata { detached.exifPhotos.append(objectsIn: self.exifPhotos.map { NCKeyValue(value: $0) }) return detached + return !e2eEncrypted } } extension NCManageDatabase { - func isMetadataShareOrMounted(metadata: tableMetadata, metadataFolder: tableMetadata?) -> Bool { - var isShare = false - var isMounted = false - if metadataFolder != nil { - isShare = metadata.permissions.contains(NCMetadataPermissions.permissionShared) && !metadataFolder!.permissions.contains(NCMetadataPermissions.permissionShared) - isMounted = metadata.permissions.contains(NCMetadataPermissions.permissionMounted) && !metadataFolder!.permissions.contains(NCMetadataPermissions.permissionMounted) - } else if let directory = getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, metadata.serverUrl)) { - isShare = metadata.permissions.contains(NCMetadataPermissions.permissionShared) && !directory.permissions.contains(NCMetadataPermissions.permissionShared) - isMounted = metadata.permissions.contains(NCMetadataPermissions.permissionMounted) && !directory.permissions.contains(NCMetadataPermissions.permissionMounted) - } + // MARK: - Create Metadata - if isShare || isMounted { - return true + func convertFileToMetadata(_ file: NKFile, isDirectoryE2EE: Bool) -> tableMetadata { + let metadata = tableMetadata() + + metadata.account = file.account + metadata.checksums = file.checksums + metadata.commentsUnread = file.commentsUnread + metadata.contentType = file.contentType + if let date = file.creationDate { + metadata.creationDate = date as NSDate } else { - return false + metadata.creationDate = file.date as NSDate + } + metadata.dataFingerprint = file.dataFingerprint + metadata.date = file.date as NSDate + if let datePhotosOriginal = file.datePhotosOriginal { + metadata.datePhotosOriginal = datePhotosOriginal as NSDate + } else { + metadata.datePhotosOriginal = metadata.date + } + metadata.directory = file.directory + metadata.downloadURL = file.downloadURL + metadata.e2eEncrypted = file.e2eEncrypted + metadata.etag = file.etag + for dict in file.exifPhotos { + for (key, value) in dict { + let keyValue = NCKeyValue() + keyValue.key = key + keyValue.value = value + metadata.exifPhotos.append(keyValue) + } + } + metadata.favorite = file.favorite + metadata.fileId = file.fileId + metadata.fileName = file.fileName + metadata.fileNameView = file.fileName + metadata.hasPreview = file.hasPreview + metadata.hidden = file.hidden + metadata.iconName = file.iconName + switch (file.fileName as NSString).pathExtension { + case "odg": + metadata.iconName = "diagram" + case "csv", "xlsm" : + metadata.iconName = "file_xls" + default: + metadata.iconName = file.iconName + } + metadata.mountType = file.mountType + metadata.name = file.name + metadata.note = file.note + metadata.ocId = file.ocId + metadata.ocIdTransfer = 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.placePhotos = file.placePhotos + metadata.quotaUsedBytes = file.quotaUsedBytes + metadata.quotaAvailableBytes = file.quotaAvailableBytes + metadata.richWorkspace = file.richWorkspace + metadata.resourceType = file.resourceType + metadata.serverUrl = file.serverUrl + metadata.serveUrlFileName = file.serverUrl + "/" + file.fileName + metadata.sharePermissionsCollaborationServices = file.sharePermissionsCollaborationServices + + for element in file.sharePermissionsCloudMesh { + metadata.sharePermissionsCloudMesh.append(element) + } + for element in file.shareType { + metadata.shareType.append(element) + } + for element in file.tags { + metadata.tags.append(element) + } + metadata.size = file.size + metadata.classFile = file.classFile + // iOS 12.0,* don't detect UTI text/markdown, text/x-markdown + if (metadata.contentType == "text/markdown" || metadata.contentType == "text/x-markdown") && metadata.classFile == NKCommon.TypeClassFile.unknow.rawValue { + metadata.classFile = NKCommon.TypeClassFile.document.rawValue + } + if let date = file.uploadDate { + metadata.uploadDate = date as NSDate + } else { + metadata.uploadDate = file.date as NSDate + } + metadata.urlBase = file.urlBase + metadata.user = file.user + metadata.userId = file.userId + metadata.latitude = file.latitude + metadata.longitude = file.longitude + metadata.altitude = file.altitude + metadata.height = Int(file.height) + metadata.width = Int(file.width) + metadata.livePhotoFile = file.livePhotoFile + metadata.isFlaggedAsLivePhotoByServer = file.isFlaggedAsLivePhotoByServer + + // E2EE find the fileName for fileNameView + if isDirectoryE2EE || file.e2eEncrypted { + if let tableE2eEncryption = getE2eEncryption(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileNameIdentifier == %@", file.account, file.serverUrl, file.fileName)) { + metadata.fileNameView = tableE2eEncryption.fileName + let results = NextcloudKit.shared.nkCommonInstance.getInternalType(fileName: metadata.fileNameView, mimeType: file.contentType, directory: file.directory, account: file.account) + metadata.contentType = results.mimeType + metadata.iconName = results.iconName + metadata.classFile = results.classFile + } } + return metadata } - // MARK: - Realm Write + func convertFilesToMetadatas(_ files: [NKFile], useFirstAsMetadataFolder: Bool, completion: @escaping (_ metadataFolder: tableMetadata, _ metadatas: [tableMetadata]) -> Void) { + var counter: Int = 0 + var isDirectoryE2EE: Bool = false + let listServerUrl = ThreadSafeDictionary() + var metadataFolder = tableMetadata() + var metadatas: [tableMetadata] = [] - func addMetadataIfNeededAsync(_ metadata: tableMetadata, sync: Bool = true) { - let detached = metadata.detachedCopy() + for file in files { + if let key = listServerUrl[file.serverUrl] { + isDirectoryE2EE = key + } else { + isDirectoryE2EE = NCUtilityFileSystem().isDirectoryE2EE(file: file) + listServerUrl[file.serverUrl] = isDirectoryE2EE + } - performRealmWrite(sync: sync) { realm in - if realm.object(ofType: tableMetadata.self, forPrimaryKey: metadata.ocId) == nil { - realm.add(detached) + let metadata = convertFileToMetadata(file, isDirectoryE2EE: isDirectoryE2EE) + + if counter == 0 && useFirstAsMetadataFolder { + metadataFolder = metadata + metadataFolder = tableMetadata(value: metadata) + } else { + metadatas.append(metadata) } + + counter += 1 } + completion(tableMetadata(value: metadataFolder), metadatas) } - func addAndReturnMetadata(_ metadata: tableMetadata) -> tableMetadata? { - let detached = metadata.detachedCopy() - - performRealmWrite { realm in - realm.add(detached, update: .all) + func convertFilesToMetadatasAsync(_ files: [NKFile], useFirstAsMetadataFolder: Bool) async -> (metadataFolder: tableMetadata, metadatas: [tableMetadata]) { + await withCheckedContinuation { continuation in + convertFilesToMetadatas(files, useFirstAsMetadataFolder: useFirstAsMetadataFolder) { metadataFolder, metadatas in + continuation.resume(returning: (metadataFolder, metadatas)) + } } + } - return performRealmRead { realm in - realm.objects(tableMetadata.self) - .filter("ocId == %@", metadata.ocId) - .first - .map { $0.detachedCopy() } - } + completion(metadataFolder, metadatas) } + + func convertFilesToMetadatas(_ files: [NKFile], useMetadataFolder: Bool, completion: @escaping (_ metadataFolder: tableMetadata, _ metadatasFolder: [tableMetadata], _ metadatas: [tableMetadata]) -> Void) { - func addAndReturnMetadataAsync(_ metadata: tableMetadata) async -> tableMetadata? { - let detached = metadata.detachedCopy() + var counter: Int = 0 + var isDirectoryE2EE: Bool = false + let listServerUrl = ThreadSafeDictionary() - await performRealmWriteAsync { realm in - realm.add(detached, update: .all) - } + var metadataFolder = tableMetadata() + var metadataFolders: [tableMetadata] = [] + var metadatas: [tableMetadata] = [] - return await performRealmReadAsync { realm in - realm.objects(tableMetadata.self) - .filter("ocId == %@", metadata.ocId) - .first? - .detachedCopy() - } - } + for file in files { - func addMetadata(_ metadata: tableMetadata, sync: Bool = true) { - let detached = metadata.detachedCopy() + if let key = listServerUrl[file.serverUrl] { + isDirectoryE2EE = key + } else { + isDirectoryE2EE = NCUtilityFileSystem().isDirectoryE2EE(file: file) + listServerUrl[file.serverUrl] = isDirectoryE2EE + } - performRealmWrite(sync: sync) { realm in - realm.add(detached, update: .all) - } - } + let metadata = convertFileToMetadata(file, isDirectoryE2EE: isDirectoryE2EE) - func addMetadataAsync(_ metadata: tableMetadata) async { - let detached = metadata.detachedCopy() + if counter == 0 && useMetadataFolder { + metadataFolder = tableMetadata.init(value: metadata) + } else { + metadatas.append(metadata) + if metadata.directory { + metadataFolders.append(metadata) + } + } - await performRealmWriteAsync { realm in - realm.add(detached, update: .all) - } + counter += 1 + } + + completion(metadataFolder, metadataFolders, metadatas) + } + +// func convertFilesToMetadatas(_ files: [NKFile], useMetadataFolder: Bool, completion: @escaping (_ metadataFolder: tableMetadata, _ metadatasFolder: [tableMetadata], _ metadatas: [tableMetadata]) -> Void) { +// +// var counter: Int = 0 +// var isDirectoryE2EE: Bool = false +// let listServerUrl = ThreadSafeDictionary() +// +// var metadataFolder = tableMetadata() +// var metadataFolders: [tableMetadata] = [] +// var metadatas: [tableMetadata] = [] +// +// for file in files { +// +// if let key = listServerUrl[file.serverUrl] { +// isDirectoryE2EE = key +// } else { +// isDirectoryE2EE = NCUtilityFileSystem().isDirectoryE2EE(file: file) +// listServerUrl[file.serverUrl] = isDirectoryE2EE +// } +// +// let metadata = convertFileToMetadata(file, isDirectoryE2EE: isDirectoryE2EE) +// +// if counter == 0 && useMetadataFolder { +// metadataFolder = tableMetadata.init(value: metadata) +// } else { +// metadatas.append(metadata) +// if metadata.directory { +// metadataFolders.append(metadata) +// } +// } +// +// counter += 1 +// } +// +// completion(metadataFolder, metadataFolders, metadatas) +// } + + func getMetadataDirectoryFrom(files: [NKFile]) -> tableMetadata? { + guard let file = files.first else { return nil } + let isDirectoryE2EE = NCUtilityFileSystem().isDirectoryE2EE(file: file) + let metadata = convertFileToMetadata(file, isDirectoryE2EE: isDirectoryE2EE) + + return metadata + } + + func convertFilesToMetadatas(_ files: [NKFile], useFirstAsMetadataFolder: Bool) async -> (metadataFolder: tableMetadata, metadatas: [tableMetadata]) { + await withUnsafeContinuation({ continuation in + convertFilesToMetadatas(files, useFirstAsMetadataFolder: useFirstAsMetadataFolder) { metadataFolder, metadatas in + continuation.resume(returning: (metadataFolder, metadatas)) + } + }) } - func addMetadatas(_ metadatas: [tableMetadata], sync: Bool = true) { - let detached = metadatas.map { $0.detachedCopy() } + func createMetadata(fileName: String, fileNameView: String, ocId: String, serverUrl: String, url: String, contentType: String, isUrl: Bool = false, name: String = NCGlobal.shared.appName, subline: String? = nil, iconName: String? = nil, iconUrl: String? = nil, directory: Bool = false, session: NCSession.Session, sceneIdentifier: String?) -> tableMetadata { + let metadata = tableMetadata() - performRealmWrite(sync: sync) { realm in - realm.add(detached, update: .all) + if isUrl { + metadata.contentType = "text/uri-list" + if let iconName = iconName { + metadata.iconName = iconName + } else { + metadata.iconName = NKCommon.TypeClassFile.url.rawValue + } + metadata.classFile = NKCommon.TypeClassFile.url.rawValue + } else { + let (mimeType, classFile, iconName, _, _, _) = NextcloudKit.shared.nkCommonInstance.getInternalType(fileName: fileName, mimeType: contentType, directory: directory, account: session.account) + metadata.contentType = mimeType + metadata.iconName = iconName + metadata.classFile = classFile + // iOS 12.0,* don't detect UTI text/markdown, text/x-markdown + if classFile == NKCommon.TypeClassFile.unknow.rawValue && (mimeType == "text/x-markdown" || mimeType == "text/markdown") { + metadata.iconName = NKCommon.TypeIconFile.txt.rawValue + metadata.classFile = NKCommon.TypeClassFile.document.rawValue + } } + if let iconUrl = iconUrl { + metadata.iconUrl = iconUrl + } + + let fileName = fileName.trimmingCharacters(in: .whitespacesAndNewlines) + + metadata.account = session.account + metadata.creationDate = Date() as NSDate + metadata.date = Date() as NSDate + metadata.directory = directory + metadata.hasPreview = true + metadata.etag = ocId + metadata.fileName = fileName + metadata.fileNameView = fileName + metadata.name = name + metadata.ocId = ocId + metadata.ocIdTransfer = ocId + metadata.permissions = "RGDNVW" + metadata.serverUrl = serverUrl + metadata.serveUrlFileName = serverUrl + "/" + fileName + metadata.subline = subline + metadata.uploadDate = Date() as NSDate + metadata.url = url + metadata.urlBase = session.urlBase + metadata.user = session.user + metadata.userId = session.userId + metadata.sceneIdentifier = sceneIdentifier + metadata.nativeFormat = !NCKeychain().formatCompatibility + + if !metadata.urlBase.isEmpty, metadata.serverUrl.hasPrefix(metadata.urlBase) { + metadata.path = String(metadata.serverUrl.dropFirst(metadata.urlBase.count)) + "/" + } + return metadata } - func addMetadatasAsync(_ metadatas: [tableMetadata]) async { - let detached = metadatas.map { $0.detachedCopy() } + func isMetadataShareOrMounted(metadata: tableMetadata, metadataFolder: tableMetadata?) -> Bool { + let permissions = NCPermissions() + var isShare = false + var isMounted = false - await performRealmWriteAsync { realm in - realm.add(detached, update: .all) + if metadataFolder != nil { + isShare = metadata.permissions.contains(permissions.permissionShared) && !metadataFolder!.permissions.contains(permissions.permissionShared) + isMounted = metadata.permissions.contains(permissions.permissionMounted) && !metadataFolder!.permissions.contains(permissions.permissionMounted) + } else if let directory = getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, metadata.serverUrl)) { + isShare = metadata.permissions.contains(permissions.permissionShared) && !directory.permissions.contains(permissions.permissionShared) + isMounted = metadata.permissions.contains(permissions.permissionMounted) && !directory.permissions.contains(permissions.permissionMounted) } - } - func deleteMetadataAsync(predicate: NSPredicate) async { - await performRealmWriteAsync { realm in - let result = realm.objects(tableMetadata.self) - .filter(predicate) - realm.delete(result) + if isShare || isMounted { + return true + } else { + return false } } - func deleteMetadataAsync(id: String?) async { - guard let id else { return } + // MARK: - Set - await performRealmWriteAsync { realm in - let result = realm.objects(tableMetadata.self) - .filter("ocId == %@ OR fileId == %@", id, id) - realm.delete(result) + @discardableResult + func addMetadata(_ metadata: tableMetadata) -> tableMetadata { + do { + let realm = try Realm() + try realm.write { + return tableMetadata(value: realm.create(tableMetadata.self, value: metadata, update: .all)) + } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } + + return tableMetadata(value: metadata) } - func deleteMetadataOcIds(_ ocIds: [String], sync: Bool = true) { - performRealmWrite(sync: sync) { realm in - let result = realm.objects(tableMetadata.self) - .filter("ocId IN %@", ocIds) - realm.delete(result) + func addMetadatas(_ metadatas: [tableMetadata]) { + do { + let realm = try Realm() + try realm.write { + for metadata in metadatas { + realm.create(tableMetadata.self, value: metadata, update: .all) + } + } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } } - func replaceMetadataAsync(id: String, metadata: tableMetadata) async { - let detached = metadata.detachedCopy() - - await performRealmWriteAsync { realm in - let result = realm.objects(tableMetadata.self) - .filter("ocId == %@ OR ocIdTransfer == %@", id, id) - realm.delete(result) - realm.add(detached, update: .all) + func deleteMetadata(predicate: NSPredicate) { + do { + let realm = try Realm() + try realm.write { + let results = realm.objects(tableMetadata.self).filter(predicate) + realm.delete(results) + } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } } @@ -494,602 +784,470 @@ extension NCManageDatabase { } let detached = metadatas.map { $0.detachedCopy() } - await performRealmWriteAsync { realm in - for detached in detached { - if let managed = realm.object(ofType: tableMetadata.self, forPrimaryKey: detached.ocId) { - realm.delete(managed) - } + do { + let realm = try Realm() + try realm.write { + let results = realm.objects(tableMetadata.self).filter("ocId == %@", ocId) + realm.delete(results) } + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } } - func renameMetadata(fileNameNew: String, ocId: String, status: Int = NCGlobal.shared.metadataStatusNormal) async { - await performRealmWriteAsync { realm in - guard let metadata = realm.objects(tableMetadata.self) - .filter("ocId == %@", ocId) - .first else { - return - } - - let oldFileNameView = metadata.fileNameView - let account = metadata.account - let originalServerUrl = metadata.serverUrl - - metadata.fileName = fileNameNew - metadata.fileNameView = fileNameNew - metadata.status = status - metadata.sessionDate = (status == NCGlobal.shared.metadataStatusNormal) ? nil : Date() - - if metadata.directory { - let oldDirUrl = self.utilityFileSystem.createServerUrl(serverUrl: originalServerUrl, fileName: oldFileNameView) - let newDirUrl = self.utilityFileSystem.createServerUrl(serverUrl: originalServerUrl, fileName: fileNameNew) - - if let dir = realm.objects(tableDirectory.self) - .filter("account == %@ AND serverUrl == %@", account, oldDirUrl) - .first { - dir.serverUrl = newDirUrl - } - } else { - let atPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId, userId: metadata.userId, urlBase: metadata.urlBase) + "/" + oldFileNameView - let toPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId, userId: metadata.userId, urlBase: metadata.urlBase) + "/" + fileNameNew - self.utilityFileSystem.moveFile(atPath: atPath, toPath: toPath) + func deleteMetadataOcIds(_ ocIds: [String]) { + do { + let realm = try Realm() + try realm.write { + let results = realm.objects(tableMetadata.self).filter("ocId IN %@", ocIds) + realm.delete(results) } + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } } - func restoreMetadataFileName(ocId: String, sync: Bool = true) { - performRealmWrite(sync: sync) { realm in - if let result = realm.objects(tableMetadata.self) - .filter("ocId == %@", ocId) - .first, - let encodedURLString = result.serverUrlFileName.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), - let url = URL(string: encodedURLString) { - let fileIdMOV = result.livePhotoFile - let directoryServerUrl = self.utilityFileSystem.createServerUrl(serverUrl: result.serverUrl, fileName: result.fileNameView) - let lastPathComponent = url.lastPathComponent - let fileName = lastPathComponent.removingPercentEncoding ?? lastPathComponent - let fileNameView = result.fileNameView - - result.fileName = fileName - result.fileNameView = fileName - result.status = NCGlobal.shared.metadataStatusNormal - result.sessionDate = nil - - if result.directory, - let resultDirectory = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", result.account, directoryServerUrl).first { - let serverUrlTo = self.utilityFileSystem.createServerUrl(serverUrl: result.serverUrl, fileName: fileName) - - resultDirectory.serverUrl = serverUrlTo - } else { - let atPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(result.ocId, userId: result.userId, urlBase: result.urlBase) + "/" + fileNameView - let toPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(result.ocId, userId: result.userId, urlBase: result.urlBase) + "/" + fileName - - self.utilityFileSystem.moveFile(atPath: atPath, toPath: toPath) + func deleteMetadatas(_ metadatas: [tableMetadata]) { + do { + let realm = try Realm() + try realm.write { + realm.delete(metadatas) + } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") + } + } + + func renameMetadata(fileNameNew: String, ocId: String, status: Int = NCGlobal.shared.metadataStatusNormal) { + do { + let realm = try Realm() + try realm.write { + if let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first { + let fileNameView = result.fileNameView + let fileIdMOV = result.livePhotoFile + let directoryServerUrl = self.utilityFileSystem.stringAppendServerUrl(result.serverUrl, addFileName: fileNameView) + let resultsType = NextcloudKit.shared.nkCommonInstance.getInternalType(fileName: fileNameNew, mimeType: "", directory: result.directory, account: result.account) + + result.fileName = fileNameNew + result.fileNameView = fileNameNew + result.iconName = resultsType.iconName + result.contentType = resultsType.mimeType + result.classFile = resultsType.classFile + result.status = status + + if status == NCGlobal.shared.metadataStatusNormal { + result.sessionDate = nil + } else { + result.sessionDate = Date() + } + + if result.directory, + let resultDirectory = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", result.account, directoryServerUrl).first { + let serverUrlTo = self.utilityFileSystem.stringAppendServerUrl(result.serverUrl, addFileName: fileNameNew) + + resultDirectory.serverUrl = serverUrlTo + } else { + let atPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(result.ocId) + "/" + fileNameView + let toPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(result.ocId) + "/" + fileNameNew + + self.utilityFileSystem.moveFile(atPath: atPath, toPath: toPath) + } + + if result.isLivePhoto, + let resultMOV = realm.objects(tableMetadata.self).filter("fileId == %@ AND account == %@", fileIdMOV, result.account).first { + let fileNameView = resultMOV.fileNameView + let fileName = (fileNameNew as NSString).deletingPathExtension + let ext = (resultMOV.fileName as NSString).pathExtension + resultMOV.fileName = fileName + "." + ext + resultMOV.fileNameView = fileName + "." + ext + + let atPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(resultMOV.ocId) + "/" + fileNameView + let toPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(resultMOV.ocId) + "/" + fileName + "." + ext + + self.utilityFileSystem.moveFile(atPath: atPath, toPath: toPath) + } } + } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") + } + } + + func restoreMetadataFileName(ocId: String) { + do { + let realm = try Realm() + try realm.write { + if let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first, + let encodedURLString = result.serveUrlFileName.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), + let url = URL(string: encodedURLString) { + let fileIdMOV = result.livePhotoFile + let directoryServerUrl = self.utilityFileSystem.stringAppendServerUrl(result.serverUrl, addFileName: result.fileNameView) + let lastPathComponent = url.lastPathComponent + let fileName = lastPathComponent.removingPercentEncoding ?? lastPathComponent + let fileNameView = result.fileNameView + + result.fileName = fileName + result.fileNameView = fileName + result.status = NCGlobal.shared.metadataStatusNormal + result.sessionDate = nil - if result.isLivePhoto, - let resultMOV = realm.objects(tableMetadata.self).filter("fileId == %@ AND account == %@", fileIdMOV, result.account).first { - let fileNameView = resultMOV.fileNameView - let fileName = (fileName as NSString).deletingPathExtension - let ext = (resultMOV.fileName as NSString).pathExtension - resultMOV.fileName = fileName + "." + ext - resultMOV.fileNameView = fileName + "." + ext + if result.directory, + let resultDirectory = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", result.account, directoryServerUrl).first { + let serverUrlTo = self.utilityFileSystem.stringAppendServerUrl(result.serverUrl, addFileName: fileName) - let atPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(resultMOV.ocId, userId: resultMOV.userId, urlBase: resultMOV.urlBase) + "/" + fileNameView - let toPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(resultMOV.ocId, userId: resultMOV.userId, urlBase: resultMOV.urlBase) + "/" + fileName + "." + ext + resultDirectory.serverUrl = serverUrlTo + } else { + let atPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(result.ocId) + "/" + fileNameView + let toPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(result.ocId) + "/" + fileName - self.utilityFileSystem.moveFile(atPath: atPath, toPath: toPath) - } - } - } - } + self.utilityFileSystem.moveFile(atPath: atPath, toPath: toPath) + } - /// Asynchronously restores the file name of a metadata entry and updates related file system and Realm entries. - /// - Parameter ocId: The object ID (ocId) of the file to restore. - func restoreMetadataFileNameAsync(ocId: String) async { - await performRealmWriteAsync { realm in - guard let result = realm.objects(tableMetadata.self) - .filter("ocId == %@", ocId) - .first, - let encodedURLString = result.serverUrlFileName.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), - let url = URL(string: encodedURLString) - else { - return - } + if result.isLivePhoto, + let resultMOV = realm.objects(tableMetadata.self).filter("fileId == %@ AND account == %@", fileIdMOV, result.account).first { + let fileNameView = resultMOV.fileNameView + let fileName = (fileName as NSString).deletingPathExtension + let ext = (resultMOV.fileName as NSString).pathExtension + resultMOV.fileName = fileName + "." + ext + resultMOV.fileNameView = fileName + "." + ext - let fileIdMOV = result.livePhotoFile - let directoryServerUrl = self.utilityFileSystem.createServerUrl(serverUrl: result.serverUrl, fileName: result.fileNameView) - let lastPathComponent = url.lastPathComponent - let fileName = lastPathComponent.removingPercentEncoding ?? lastPathComponent - let fileNameView = result.fileNameView - - result.fileName = fileName - result.fileNameView = fileName - result.status = NCGlobal.shared.metadataStatusNormal - result.sessionDate = nil - - if result.directory, - let resultDirectory = realm.objects(tableDirectory.self) - .filter("account == %@ AND serverUrl == %@", result.account, directoryServerUrl) - .first { - let serverUrlTo = self.utilityFileSystem.createServerUrl(serverUrl: result.serverUrl, fileName: fileName) - resultDirectory.serverUrl = serverUrlTo - } else { - let atPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(result.ocId, userId: result.userId, urlBase: result.urlBase) + "/" + fileNameView - let toPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(result.ocId, userId: result.userId, urlBase: result.urlBase) + "/" + fileName - self.utilityFileSystem.moveFile(atPath: atPath, toPath: toPath) - } + let atPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(resultMOV.ocId) + "/" + fileNameView + let toPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(resultMOV.ocId) + "/" + fileName + "." + ext - if result.isLivePhoto, - let resultMOV = realm.objects(tableMetadata.self) - .filter("fileId == %@ AND account == %@", fileIdMOV, result.account) - .first { - let fileNameViewMOV = resultMOV.fileNameView - let baseName = (fileName as NSString).deletingPathExtension - let ext = (resultMOV.fileName as NSString).pathExtension - let fullFileName = baseName + "." + ext - - resultMOV.fileName = fullFileName - resultMOV.fileNameView = fullFileName - - let atPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(resultMOV.ocId, userId: resultMOV.userId, urlBase: resultMOV.urlBase) + "/" + fileNameViewMOV - let toPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(resultMOV.ocId, userId: resultMOV.userId, urlBase: resultMOV.urlBase) + "/" + fullFileName - self.utilityFileSystem.moveFile(atPath: atPath, toPath: toPath) + self.utilityFileSystem.moveFile(atPath: atPath, toPath: toPath) + } + } } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } } - func setMetadataServerUrlFileNameStatusNormal(ocId: String, sync: Bool = true) { - performRealmWrite(sync: sync) { realm in - if let result = realm.objects(tableMetadata.self) - .filter("ocId == %@", ocId) - .first { - result.serverUrlFileName = self.utilityFileSystem.createServerUrl(serverUrl: result.serverUrl, fileName: result.fileName) - result.status = NCGlobal.shared.metadataStatusNormal - result.sessionDate = nil + func setMetadataServeUrlFileNameStatusNormal(ocId: String) { + do { + let realm = try Realm() + try realm.write { + if let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first { + result.serveUrlFileName = self.utilityFileSystem.stringAppendServerUrl(result.serverUrl, addFileName: result.fileName) + result.status = NCGlobal.shared.metadataStatusNormal + result.sessionDate = nil + } } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } } - func setMetadataServerUrlFileNameStatusNormalAsync(ocId: String) async { - await performRealmWriteAsync { realm in - if let result = realm.objects(tableMetadata.self) - .filter("ocId == %@", ocId) - .first { - result.serverUrlFileName = self.utilityFileSystem.createServerUrl(serverUrl: result.serverUrl, fileName: result.fileName) - result.status = NCGlobal.shared.metadataStatusNormal - result.sessionDate = nil - } - } - } + func setMetadataEtagResource(ocId: String, etagResource: String?) { + guard let etagResource else { return } - func setMetadataLivePhotoByServerAsync(account: String, - ocId: String, - livePhotoFile: String) async { - await performRealmWriteAsync { realm in - if let result = realm.objects(tableMetadata.self) - .filter("account == %@ AND ocId == %@", account, ocId) - .first { - result.isFlaggedAsLivePhotoByServer = true - result.livePhotoFile = livePhotoFile + do { + let realm = try Realm() + try realm.write { + let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first + result?.etagResource = etagResource } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } } - func updateMetadatasFavoriteAsync(account: String, metadatas: [tableMetadata]) async { - guard !metadatas.isEmpty else { return } - - await performRealmWriteAsync { realm in - let oldFavorites = realm.objects(tableMetadata.self) - .filter("account == %@ AND favorite == true", account) - for item in oldFavorites { - item.favorite = false + func setMetadataLivePhotoByServer(account: String, ocId: String, livePhotoFile: String) { + do { + let realm = try Realm() + try realm.write { + if let result = realm.objects(tableMetadata.self).filter("account == %@ AND ocId == %@", account, ocId).first { + result.isFlaggedAsLivePhotoByServer = true + result.livePhotoFile = livePhotoFile + } } - realm.add(metadatas, update: .all) + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } } - /// Asynchronously updates a list of `tableMetadata` entries in Realm for a given account and server URL. - /// - /// This function performs the following steps: - /// 1. Skips all entries with `status != metadataStatusNormal`. - /// 2. Deletes existing metadata entries with `status == metadataStatusNormal` that are not in the skip list. - /// 3. Copies matching `mediaSearch` from previously deleted metadata to the incoming list. - /// 4. Inserts or updates new metadata entries into Realm, except those in the skip list. - /// - /// - Parameters: - /// - metadatas: An array of incoming detached `tableMetadata` objects to insert or update. - /// - serverUrl: The server URL associated with the metadata entries. - /// - account: The account identifier used to scope the metadata update. - func updateMetadatasFilesAsync(_ metadatas: [tableMetadata], serverUrl: String, account: String) async { - await performRealmWriteAsync { realm in - let ocIdsToSkip = Set( - realm.objects(tableMetadata.self) - .filter("status != %d", NCGlobal.shared.metadataStatusNormal) - .map(\.ocId) - ) - - let resultsToDelete = realm.objects(tableMetadata.self) - .filter("account == %@ AND serverUrl == %@ AND status == %d AND fileName != %@", account, serverUrl, NCGlobal.shared.metadataStatusNormal, NextcloudKit.shared.nkCommonInstance.rootFileName) - .filter { !ocIdsToSkip.contains($0.ocId) } - let metadatasCopy = Array(resultsToDelete).map { tableMetadata(value: $0) } - - realm.delete(resultsToDelete) - - for metadata in metadatas { - guard !ocIdsToSkip.contains(metadata.ocId) else { - continue - } - if let match = metadatasCopy.first(where: { $0.ocId == metadata.ocId }) { - metadata.mediaSearch = match.mediaSearch + func updateMetadatasFavorite(account: String, metadatas: [tableMetadata]) { + do { + let realm = try Realm() + try realm.write { + let results = realm.objects(tableMetadata.self).filter("account == %@ AND favorite == true", account) + for result in results { + result.favorite = false } - realm.add(metadata.detachedCopy(), update: .all) + realm.add(metadatas, update: .all) } - } - } - - func setMetadataEncrypted(ocId: String, encrypted: Bool, sync: Bool = true) { - performRealmWrite(sync: sync) { realm in - let result = realm.objects(tableMetadata.self) - .filter("ocId == %@", ocId) - .first - result?.e2eEncrypted = encrypted - } - } - - func setMetadataEncryptedAsync(ocId: String, encrypted: Bool) async { - await performRealmWriteAsync { realm in - let result = realm.objects(tableMetadata.self) - .filter("ocId == %@", ocId) - .first - result?.e2eEncrypted = encrypted - } - } - - func setMetadataFileNameView(serverUrl: String, fileName: String, newFileNameView: String, account: String, sync: Bool = true) { - performRealmWrite(sync: sync) { realm in - let result = realm.objects(tableMetadata.self) - .filter("account == %@ AND serverUrl == %@ AND fileName == %@", account, serverUrl, fileName) - .first - result?.fileNameView = newFileNameView - } - } - - func setMetadataFileNameViewAsync(serverUrl: String, fileName: String, newFileNameView: String, account: String) async { - await performRealmWriteAsync { realm in - let result = realm.objects(tableMetadata.self) - .filter("account == %@ AND serverUrl == %@ AND fileName == %@", account, serverUrl, fileName) - .first - result?.fileNameView = newFileNameView - } - } - - func moveMetadata(ocId: String, serverUrlTo: String, sync: Bool = true) { - performRealmWrite(sync: sync) { realm in - if let result = realm.objects(tableMetadata.self) - .filter("ocId == %@", ocId) - .first { - result.serverUrl = serverUrlTo + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") + } + } + + func updateMetadatasFiles(_ metadatas: [tableMetadata], serverUrl: String, account: String) { + do { + let realm = try Realm() + try realm.write { + let results = realm.objects(tableMetadata.self).filter(NSPredicate(format: "account == %@ AND serverUrl == %@ AND status == %d", account, serverUrl, NCGlobal.shared.metadataStatusNormal)) + realm.delete(results) + for metadata in metadatas { + if realm.objects(tableMetadata.self).filter(NSPredicate(format: "ocId == %@ AND status != %d", metadata.ocId, NCGlobal.shared.metadataStatusNormal)).first != nil { + continue + } + realm.add(tableMetadata(value: metadata), update: .all) + } } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } } - func moveMetadataAsync(ocId: String, serverUrlTo: String) async { - await performRealmWriteAsync { realm in - if let result = realm.objects(tableMetadata.self) - .filter("ocId == %@", ocId) - .first { - result.serverUrl = serverUrlTo + func setMetadataEncrypted(ocId: String, encrypted: Bool) { + do { + let realm = try Realm() + try realm.write { + let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first + result?.e2eEncrypted = encrypted } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } } - func setLivePhotoFile(fileId: String, livePhotoFile: String) async { - await performRealmWriteAsync { realm in - let result = realm.objects(tableMetadata.self) - .filter("fileId == %@", fileId) - .first - result?.livePhotoFile = livePhotoFile - } - } - - func clearAssetLocalIdentifiersAsync(_ assetLocalIdentifiers: [String]) async { - await performRealmWriteAsync { realm in - let results = realm.objects(tableMetadata.self) - .filter("assetLocalIdentifier IN %@", assetLocalIdentifiers) - for result in results { - result.assetLocalIdentifier = "" + func setMetadataFileNameView(serverUrl: String, fileName: String, newFileNameView: String, account: String) { + do { + let realm = try Realm() + try realm.write { + let result = realm.objects(tableMetadata.self).filter("account == %@ AND serverUrl == %@ AND fileName == %@", account, serverUrl, fileName).first + result?.fileNameView = newFileNameView } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } } - func setMetadataFavorite(ocId: String, favorite: Bool?, saveOldFavorite: String?, status: Int, sync: Bool = true) { - performRealmWrite(sync: sync) { realm in - let result = realm.objects(tableMetadata.self) - .filter("ocId == %@", ocId) - .first - if let favorite { - result?.favorite = favorite - } - result?.storeFlag = saveOldFavorite - result?.status = status - - if status == NCGlobal.shared.metadataStatusNormal { - result?.sessionDate = nil - } else { - result?.sessionDate = Date() + func moveMetadata(ocId: String, serverUrlTo: String) { + do { + let realm = try Realm() + try realm.write { + if let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first { + result.serverUrl = serverUrlTo + } } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } } - /// Asynchronously sets the favorite status of a `tableMetadata` entry. - /// Optionally stores the previous favorite flag and updates the sync status. - func setMetadataFavoriteAsync(ocId: String, favorite: Bool?, saveOldFavorite: String?, status: Int) async { - await performRealmWriteAsync { realm in - guard let result = realm.objects(tableMetadata.self) - .filter("ocId == %@", ocId) - .first else { - return - } - - if let favorite { - result.favorite = favorite + func clearAssetLocalIdentifiers(_ assetLocalIdentifiers: [String]) { + do { + let realm = try Realm() + try realm.write { + let results = realm.objects(tableMetadata.self).filter("assetLocalIdentifier IN %@", assetLocalIdentifiers) + for result in results { + result.assetLocalIdentifier = "" + } } - - result.storeFlag = saveOldFavorite - result.status = status - result.sessionDate = (status == NCGlobal.shared.metadataStatusNormal) ? nil : Date() + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } } - func setMetadataCopyMove(ocId: String, serverUrlTo: String, overwrite: String?, status: Int, sync: Bool = true) { - performRealmWrite(sync: sync) { realm in - if let result = realm.objects(tableMetadata.self) - .filter("ocId == %@", ocId) - .first { - result.destination = serverUrlTo - result.storeFlag = overwrite - result.status = status + func setMetadataFavorite(ocId: String, favorite: Bool?, saveOldFavorite: String?, status: Int) { + do { + let realm = try Realm() + try realm.write { + let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first + if let favorite { + result?.favorite = favorite + } + result?.storeFlag = saveOldFavorite + result?.status = status if status == NCGlobal.shared.metadataStatusNormal { - result.sessionDate = nil + result?.sessionDate = nil } else { - result.sessionDate = Date() + result?.sessionDate = Date() } } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } } - /// Asynchronously updates a `tableMetadata` entry to set copy/move status and target server URL. - func setMetadataCopyMoveAsync(ocId: String, destination: String, overwrite: String?, status: Int) async { - await performRealmWriteAsync { realm in - guard let result = realm.objects(tableMetadata.self) - .filter("ocId == %@", ocId) - .first else { - return - } - - result.destination = destination - result.storeFlag = overwrite - result.status = status - result.sessionDate = (status == NCGlobal.shared.metadataStatusNormal) ? nil : Date() - } - } - - func clearMetadatasUpload(account: String, sync: Bool = true) { - performRealmWrite(sync: sync) { realm in - let results = realm.objects(tableMetadata.self) - .filter("account == %@ AND (status == %d OR status == %d)", account, NCGlobal.shared.metadataStatusWaitUpload, NCGlobal.shared.metadataStatusUploadError) - realm.delete(results) - } - } - - func clearMetadatasUploadAsync(account: String) async { - await performRealmWriteAsync { realm in - let results = realm.objects(tableMetadata.self) - .filter("account == %@ AND (status == %d OR status == %d)", account, NCGlobal.shared.metadataStatusWaitUpload, NCGlobal.shared.metadataStatusUploadError) - realm.delete(results) - } - } + func setMetadataCopyMove(ocId: String, serverUrlTo: String, overwrite: String?, status: Int) { + do { + let realm = try Realm() + try realm.write { + let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first + result?.serverUrlTo = serverUrlTo + result?.storeFlag = overwrite + result?.status = status - /// Syncs the remote and local metadata. - /// Returns true if there were changes (additions or deletions), false if everything was already up-to-date. - func mergeRemoteMetadatasAsync(remoteMetadatas: [tableMetadata], localMetadatas: [tableMetadata]) async -> Bool { - // Set of ocId - let remoteOcIds = Set(remoteMetadatas.map { $0.ocId }) - let localOcIds = Set(localMetadatas.map { $0.ocId }) - - // Calculate diffs - let toDeleteOcIds = localOcIds.subtracting(remoteOcIds) - let toAddOcIds = remoteOcIds.subtracting(localOcIds) - - guard !toDeleteOcIds.isEmpty || !toAddOcIds.isEmpty else { - return false // No changes needed - } - - let toDeleteKeys = Array(toDeleteOcIds) - - await performRealmWriteAsync { realm in - let toAdd = remoteMetadatas.filter { toAddOcIds.contains($0.ocId) } - let toDelete = toDeleteKeys.compactMap { - realm.object(ofType: tableMetadata.self, forPrimaryKey: $0) + if status == NCGlobal.shared.metadataStatusNormal { + result?.sessionDate = nil + } else { + result?.sessionDate = Date() + } } - - realm.delete(toDelete) - realm.add(toAdd, update: .modified) + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } - - return true } - // MARK: - Realm Read - - func getAllTableMetadataAsync() async -> [tableMetadata] { - return await performRealmReadAsync { realm in - realm.objects(tableMetadata.self).map { tableMetadata(value: $0) } - } ?? [] - } + // MARK: - GetMetadata func getMetadata(predicate: NSPredicate) -> tableMetadata? { - return performRealmRead { realm in - realm.objects(tableMetadata.self) - .filter(predicate) - .first - .map { $0.detachedCopy() } + do { + let realm = try Realm() + guard let result = realm.objects(tableMetadata.self).filter(predicate).first else { return nil } + return tableMetadata(value: result) + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - } - func getMetadataAsync(predicate: NSPredicate) async -> tableMetadata? { - return await performRealmReadAsync { realm in - realm.objects(tableMetadata.self) - .filter(predicate) - .first - .map { $0.detachedCopy() } - } + return nil } func getMetadatas(predicate: NSPredicate) -> [tableMetadata] { - performRealmRead { realm in - realm.objects(tableMetadata.self) - .filter(predicate) - .map { $0.detachedCopy() } - } ?? [] + do { + let realm = try Realm() + let results = realm.objects(tableMetadata.self).filter(predicate) + return Array(results.map { tableMetadata(value: $0) }) + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") + } + return [] } - func getMetadatas(predicate: NSPredicate, - sortedByKeyPath: String, - ascending: Bool = false) -> [tableMetadata]? { - return performRealmRead { realm in - realm.objects(tableMetadata.self) - .filter(predicate) - .sorted(byKeyPath: sortedByKeyPath, ascending: ascending) - .map { $0.detachedCopy() } + func getMetadatas(predicate: NSPredicate, sortedByKeyPath: String, ascending: Bool = false) -> [tableMetadata]? { + do { + let realm = try Realm() + let results = realm.objects(tableMetadata.self).filter(predicate).sorted(byKeyPath: sortedByKeyPath, ascending: ascending) + return Array(results.map { tableMetadata(value: $0) }) + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } + return nil } - func getMetadatasAsync(predicate: NSPredicate, - sortedByKeyPath: String, - ascending: Bool = false, - limit: Int? = nil) async -> [tableMetadata]? { - return await performRealmReadAsync { realm in - let results = realm.objects(tableMetadata.self) - .filter(predicate) - .sorted(byKeyPath: sortedByKeyPath, - ascending: ascending) - - if let limit { - let sliced = results.prefix(limit) - return sliced.map { $0.detachedCopy() } - } else { - return results.map { $0.detachedCopy() } + func getMetadatas(predicate: NSPredicate, numItems: Int, sorted: String, ascending: Bool) -> [tableMetadata] { + var counter: Int = 0 + var metadatas: [tableMetadata] = [] + + do { + let realm = try Realm() + let results = realm.objects(tableMetadata.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending) + for result in results where counter < numItems { + metadatas.append(tableMetadata(value: result)) + counter += 1 } + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - } - - func getMetadatas(predicate: NSPredicate, - numItems: Int, - sorted: String, - ascending: Bool) -> [tableMetadata] { - return performRealmRead { realm in - let results = realm.objects(tableMetadata.self) - .filter(predicate) - .sorted(byKeyPath: sorted, ascending: ascending) - return results.prefix(numItems) - .map { $0.detachedCopy() } - } ?? [] + return metadatas } func getMetadataFromOcId(_ ocId: String?) -> tableMetadata? { guard let ocId else { return nil } - return performRealmRead { realm in - realm.objects(tableMetadata.self) - .filter("ocId == %@", ocId) - .first - .map { $0.detachedCopy() } - } - } - - func getMetadataFromOcIdAsync(_ ocId: String?) async -> tableMetadata? { + do { + let realm = try Realm() + guard let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first else { return nil } + return tableMetadata(value: result) + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") + } + return nil + } + +// func getMetadataFromOcIdAndocIdTransfer(_ ocId: String?) -> tableMetadata? { +// guard let ocId else { return nil } +// +// do { +// let realm = try Realm() +// if let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first { +// return tableMetadata(value: result) +// } +// if let result = realm.objects(tableMetadata.self).filter("ocIdTransfer == %@", ocId).first { +// return tableMetadata(value: result) +// } +// } catch let error as NSError { +// NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") +// } +// return nil +// } + + func getMetadataFromOcIdAndocIdTransfer(_ ocId: String?) -> tableMetadata? { guard let ocId else { return nil } - return await performRealmReadAsync { realm in - realm.objects(tableMetadata.self) - .filter("ocId == %@", ocId) - .first - .map { $0.detachedCopy() } - } - } - - func getMetadataFromOcIdAndocIdTransferAsync(_ ocId: String?) async -> tableMetadata? { - guard let ocId else { - return nil - } - - return await performRealmReadAsync { realm in + return performRealmRead { realm in realm.objects(tableMetadata.self) .filter("ocId == %@ OR ocIdTransfer == %@", ocId, ocId) .first - .map { $0.detachedCopy() } - } - } - - /// Asynchronously retrieves the metadata for a folder, based on its session and serverUrl. - /// Handles the home directory case rootFileName) and detaches the Realm object before returning. - func getMetadataFolderAsync(session: NCSession.Session, serverUrl: String) async -> tableMetadata? { + .map { tableMetadata(value: $0) } + } + } + +// func getMetadataFromOcIdAndocIdTransfer(_ ocId: String?) -> tableMetadata? { +// guard let ocId else { return nil } +// +// return performRealmRead { realm in +// // First, try to find by ocId +// if let result = realm.objects(tableMetadata.self) +// .filter("ocId == %@", ocId) +// .first { +// return tableMetadata(value: result) +// } +// +// // If not found, try to find by ocIdTransfer +// if let result = realm.objects(tableMetadata.self) +// .filter("ocIdTransfer == %@", ocId) +// .first { +// return tableMetadata(value: result) +// } +// +// // Not found +// return nil +// } +// } + + func getMetadataFolder(session: NCSession.Session, serverUrl: String) -> tableMetadata? { var serverUrl = serverUrl var fileName = "" - let home = utilityFileSystem.getHomeServer(session: session) + let serverUrlHome = utilityFileSystem.getHomeServer(session: session) - if home == serverUrl { - fileName = NextcloudKit.shared.nkCommonInstance.rootFileName + if serverUrlHome == serverUrl { + fileName = "." + serverUrl = ".." } else { fileName = (serverUrl as NSString).lastPathComponent - if let serverDirectoryUp = utilityFileSystem.serverDirectoryUp(serverUrl: serverUrl, home: home) { - serverUrl = serverDirectoryUp + if let path = utilityFileSystem.deleteLastPath(serverUrlPath: serverUrl) { + serverUrl = path } } - return await performRealmReadAsync { realm in - realm.objects(tableMetadata.self) - .filter("account == %@ AND serverUrl == %@ AND fileName == %@", session.account, serverUrl, fileName) - .first - .map { $0.detachedCopy() } + do { + let realm = try Realm() + guard let result = realm.objects(tableMetadata.self).filter("account == %@ AND serverUrl == %@ AND fileName == %@", session.account, serverUrl, fileName).first else { return nil } + return tableMetadata(value: result) + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } + return nil } func getMetadataLivePhoto(metadata: tableMetadata) -> tableMetadata? { - guard metadata.isLivePhoto else { - return nil - } - let detached = metadata.detachedCopy() + guard metadata.isLivePhoto else { return nil } - return performRealmRead { realm in - realm.objects(tableMetadata.self) - .filter(NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileId == %@", - detached.account, - detached.serverUrl, - detached.livePhotoFile)) - .first - .map { $0.detachedCopy() } - } - } - - func getMetadataLivePhotoAsync(metadata: tableMetadata) async -> tableMetadata? { - guard metadata.isLivePhoto else { - return nil - } - let detached = metadata.detachedCopy() - - return await performRealmReadAsync { realm in - realm.objects(tableMetadata.self) - .filter(NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileId == %@", - detached.account, - detached.serverUrl, - detached.livePhotoFile)) - .first - .map { $0.detachedCopy() } + do { + let realm = try Realm() + guard let result = realm.objects(tableMetadata.self).filter(NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileId == %@", + metadata.account, + metadata.serverUrl, + metadata.livePhotoFile)).first else { return nil } + return tableMetadata(value: result) + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } + return nil } func getMetadataConflict(account: String, serverUrl: String, fileNameView: String, nativeFormat: Bool) -> tableMetadata? { @@ -1106,237 +1264,533 @@ extension NCManageDatabase { fileNameConflict)) } - /// Asynchronously retrieves and sorts `tableMetadata` associated with groupfolders for a given session. - /// - Parameters: - /// - session: The `NCSession.Session` containing account and server information. - /// - layoutForView: An optional layout configuration used for sorting. - /// - Returns: An array of sorted and detached `tableMetadata` objects. - func getMetadatasFromGroupfoldersAsync(session: NCSession.Session, layoutForView: NCDBLayoutForView?) async -> [tableMetadata] { - let homeServerUrl = utilityFileSystem.getHomeServer(session: session) + // MARK: - GetResult(s)Metadata + + func getResultsMetadatasPredicate(_ predicate: NSPredicate, layoutForView: NCDBLayoutForView?, directoryOnTop: Bool = true) -> [tableMetadata] { + do { + let realm = try Realm() + var results = realm.objects(tableMetadata.self).filter(predicate).freeze() + let layout: NCDBLayoutForView = layoutForView ?? NCDBLayoutForView() + + if layout.sort == "fileName" { + let sortedResults = results.sorted { + let ordered = layout.ascending ? ComparisonResult.orderedAscending : ComparisonResult.orderedDescending + // 1. favorite order + if $0.favorite == $1.favorite { + // 2. directory order TOP + if directoryOnTop { + if $0.directory == $1.directory { + // 3. natural fileName + return $0.fileNameView.localizedStandardCompare($1.fileNameView) == ordered + } else { + return $0.directory && !$1.directory + } + } else { + return $0.fileNameView.localizedStandardCompare($1.fileNameView) == ordered + } + } else { + return $0.favorite && !$1.favorite + } + } + return sortedResults + } else { + if directoryOnTop { + results = results.sorted(byKeyPath: layout.sort, ascending: layout.ascending).sorted(byKeyPath: "favorite", ascending: false).sorted(byKeyPath: "directory", ascending: false) + } else { + results = results.sorted(byKeyPath: layout.sort, ascending: layout.ascending).sorted(byKeyPath: "favorite", ascending: false) + } + } + return Array(results) + + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") + } + return [] + } + + func getResultsMetadatas(predicate: NSPredicate, sortedByKeyPath: String, ascending: Bool, arraySlice: Int) -> [tableMetadata] { + do { + let realm = try Realm() + let results = realm.objects(tableMetadata.self).filter(predicate).sorted(byKeyPath: sortedByKeyPath, ascending: ascending).prefix(arraySlice) + return Array(results) + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") + } + return [] + } - let detachedMetadatas: [tableMetadata] = await performRealmReadAsync { realm in - var ocIds: [String] = [] + func getResultMetadata(predicate: NSPredicate) -> tableMetadata? { + do { + let realm = try Realm() + return realm.objects(tableMetadata.self).filter(predicate).first + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") + } + return nil + } - // Safely fetch and detach groupfolders - let groupfolders = realm.objects(TableGroupfolders.self) - .filter("account == %@", session.account) - .sorted(byKeyPath: "mountPoint", ascending: true) - .map { TableGroupfolders(value: $0) } + func getResultMetadataFromFileName(_ fileName: String, serverUrl: String, sessionTaskIdentifier: Int) -> tableMetadata? { + do { + let realm = try Realm() + return realm.objects(tableMetadata.self).filter("fileName == %@ AND serverUrl == %@ AND sessionTaskIdentifier == %d", fileName, serverUrl, sessionTaskIdentifier).first + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") + } + return nil + } + + func getResultsMetadatasFromGroupfolders(session: NCSession.Session) -> Results? { + var ocId: [String] = [] + let homeServerUrl = utilityFileSystem.getHomeServer(session: session) + + do { + let realm = try Realm() + let groupfolders = realm.objects(TableGroupfolders.self).filter("account == %@", session.account).sorted(byKeyPath: "mountPoint", ascending: true) for groupfolder in groupfolders { let mountPoint = groupfolder.mountPoint.hasPrefix("/") ? groupfolder.mountPoint : "/" + groupfolder.mountPoint let serverUrlFileName = homeServerUrl + mountPoint - if let directory = realm.objects(tableDirectory.self) - .filter("account == %@ AND serverUrl == %@", session.account, serverUrlFileName) - .first, - let metadata = realm.objects(tableMetadata.self) - .filter("ocId == %@", directory.ocId) - .first { - ocIds.append(metadata.ocId) + if let directory = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", session.account, serverUrlFileName).first, + let result = realm.objects(tableMetadata.self).filter("ocId == %@", directory.ocId).first { + ocId.append(result.ocId) } } - // Fetch and detach the corresponding metadatas - return realm.objects(tableMetadata.self) - .filter("ocId IN %@", ocIds) - .map { $0.detachedCopy() } - } ?? [] + return realm.objects(tableMetadata.self).filter("ocId IN %@", ocId) + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") + } - let sorted = await self.sortedMetadata(layoutForView: layoutForView, account: session.account, metadatas: detachedMetadatas) - return sorted + return nil } - func getRootContainerMetadata(accout: String) -> tableMetadata? { - return performRealmRead { realm in - realm.objects(tableMetadata.self) - .filter("fileName == %@ AND account == %@", NextcloudKit.shared.nkCommonInstance.rootFileName, accout) - .first - .map { $0.detachedCopy() } + func getTableMetadatasDirectoryFavoriteIdentifierRank(account: String) -> [String: NSNumber] { + var listIdentifierRank: [String: NSNumber] = [:] + var counter = 10 as Int64 + + do { + let realm = try Realm() + let results = realm.objects(tableMetadata.self).filter("account == %@ AND directory == true AND favorite == true", account).sorted(byKeyPath: "fileNameView", ascending: true) + for result in results { + counter += 1 + listIdentifierRank[result.ocId] = NSNumber(value: Int64(counter)) + } + + return listIdentifierRank + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } + return listIdentifierRank } - func getRootContainerMetadataAsync(accout: String) async -> tableMetadata? { - return await performRealmReadAsync { realm in - realm.objects(tableMetadata.self) - .filter("fileName == %@ AND account == %@", NextcloudKit.shared.nkCommonInstance.rootFileName, accout) - .first - .map { $0.detachedCopy() } + @objc func clearMetadatasUpload(account: String) { + do { + let realm = try Realm() + try realm.write { + let results = realm.objects(tableMetadata.self).filter("account == %@ AND (status == %d OR status == %d)", account, NCGlobal.shared.metadataStatusWaitUpload, NCGlobal.shared.metadataStatusUploadError) + realm.delete(results) + } + } catch let error { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)") } } - func getMetadatasAsync(predicate: NSPredicate) async -> [tableMetadata] { - await performRealmReadAsync { realm in - realm.objects(tableMetadata.self) - .filter(predicate) - .map { $0.detachedCopy() } - } ?? [] + func getAssetLocalIdentifiersUploadedAsync() async -> [String]? { + return await performRealmReadAsync { realm in + let results = realm.objects(tableMetadata.self).filter("assetLocalIdentifier != ''") + return results.map { $0.assetLocalIdentifier } + } } - func getTableMetadatasDirectoryFavoriteIdentifierRankAsync(account: String) async -> [String: NSNumber] { - let result = await performRealmReadAsync { realm in - var listIdentifierRank: [String: NSNumber] = [:] - var counter = Int64(10) - - let results = realm.objects(tableMetadata.self) - .filter("account == %@ AND directory == true AND favorite == true", account) - .sorted(byKeyPath: "fileNameView", ascending: true) + func getAssetLocalIdentifiersUploaded() -> [String]? { + var assetLocalIdentifiers: [String] = [] - results.forEach { item in - counter += 1 - listIdentifierRank[item.ocId] = NSNumber(value: counter) + do { + let realm = try Realm() + let results = realm.objects(tableMetadata.self).filter("assetLocalIdentifier != ''") + for result in results { + assetLocalIdentifiers.append(result.assetLocalIdentifier) } - - return listIdentifierRank + return assetLocalIdentifiers + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } - return result ?? [:] + return nil } - func getAssetLocalIdentifiersUploadedAsync() async -> [String]? { - return await performRealmReadAsync { realm in - let results = realm.objects(tableMetadata.self).filter("assetLocalIdentifier != ''") - return results.map { $0.assetLocalIdentifier } + func getMetadataFromDirectory(account: String, serverUrl: String) -> Bool { + do { + let realm = try Realm() + guard let directory = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first, + realm.objects(tableMetadata.self).filter("ocId == %@", directory.ocId).first != nil else { return false } + return true + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } + return false } func getMetadataFromFileId(_ fileId: String?) -> tableMetadata? { - guard let fileId else { - return nil + guard let fileId else { return nil } + + do { + let realm = try Realm() + if let result = realm.objects(tableMetadata.self).filter("fileId == %@", fileId).first { + return tableMetadata(value: result) + } + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } + return nil + } - return performRealmRead { realm in - realm.objects(tableMetadata.self) - .filter("fileId == %@", fileId) - .first - .map { $0.detachedCopy() } + func getResultMetadataFromOcId(_ ocId: String?) -> tableMetadata? { + guard let ocId else { return nil } + + do { + let realm = try Realm() + return realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } + return nil } - /// Asynchronously retrieves a `tableMetadata` object matching the given `fileId`, if available. - /// - Parameter fileId: The file identifier used to query the Realm database. - /// - Returns: A detached copy of the `tableMetadata` object, or `nil` if not found. - func getMetadataFromFileIdAsync(_ fileId: String?) async -> tableMetadata? { - guard let fileId else { - return nil + func createMetadatasFolder(assets: [PHAsset], + useSubFolder: Bool, + session: NCSession.Session, completion: @escaping ([tableMetadata]) -> Void) { + var foldersCreated: Set = [] + var metadatas: [tableMetadata] = [] + let serverUrlBase = getAccountAutoUploadDirectory(session: session) + let fileNameBase = getAccountAutoUploadFileName(account: session.account) + let predicate = NSPredicate(format: "account == %@ AND serverUrl BEGINSWITH %@ AND directory == true", session.account, serverUrlBase) + + func createMetadata(serverUrl: String, fileName: String, metadata: tableMetadata?) { + guard !foldersCreated.contains(serverUrl + "/" + fileName) else { + return + } + foldersCreated.insert(serverUrl + "/" + fileName) + + if let metadata { + metadata.status = NCGlobal.shared.metadataStatusWaitCreateFolder + metadata.sessionSelector = NCGlobal.shared.selectorUploadAutoUpload + metadata.sessionDate = Date() + metadatas.append(tableMetadata(value: metadata)) + } else { + let metadata = NCManageDatabase.shared.createMetadata(fileName: fileName, + fileNameView: fileName, + ocId: NSUUID().uuidString, + serverUrl: serverUrl, + url: "", + contentType: "httpd/unix-directory", + directory: true, + session: session, + sceneIdentifier: nil) + metadata.status = NCGlobal.shared.metadataStatusWaitCreateFolder + metadata.sessionSelector = NCGlobal.shared.selectorUploadAutoUpload + metadata.sessionDate = Date() + metadatas.append(metadata) + } } - return await performRealmReadAsync { realm in + let metadatasFolder = getMetadatas(predicate: predicate) + let targetPath = serverUrlBase + "/" + fileNameBase + let metadata = metadatasFolder.first(where: { $0.serverUrl + "/" + $0.fileNameView == targetPath }) + createMetadata(serverUrl: serverUrlBase, fileName: fileNameBase, metadata: metadata) + + if useSubFolder { + let autoUploadServerUrlBase = self.getAccountAutoUploadServerUrlBase(session: session) + let autoUploadSubfolderGranularity = self.getAccountAutoUploadSubfolderGranularity() + let folders = Set(assets.map { self.utilityFileSystem.createGranularityPath(asset: $0) }).sorted() + + for folder in folders { + let componentsDate = folder.split(separator: "/") + let year = componentsDate[0] + let serverUrl = autoUploadServerUrlBase + let fileName = String(year) + let targetPath = serverUrl + "/" + fileName + let metadata = metadatasFolder.first(where: { $0.serverUrl + "/" + $0.fileNameView == targetPath }) + + createMetadata(serverUrl: serverUrl, fileName: fileName, metadata: metadata) + + if autoUploadSubfolderGranularity >= NCGlobal.shared.subfolderGranularityMonthly { + let month = componentsDate[1] + let serverUrl = autoUploadServerUrlBase + "/" + year + let fileName = String(month) + let targetPath = serverUrl + "/" + fileName + let metadata = metadatasFolder.first(where: { $0.serverUrl + "/" + $0.fileNameView == targetPath }) + + createMetadata(serverUrl: serverUrl, fileName: fileName, metadata: metadata) + + if autoUploadSubfolderGranularity == NCGlobal.shared.subfolderGranularityDaily { + let day = componentsDate[2] + let serverUrl = autoUploadServerUrlBase + "/" + year + "/" + month + let fileName = String(day) + let targetPath = serverUrl + "/" + fileName + let metadata = metadatasFolder.first(where: { $0.serverUrl + "/" + $0.fileNameView == targetPath }) + + createMetadata(serverUrl: serverUrl, fileName: fileName, metadata: metadata) + } + } + } + completion(metadatas) + } else { + completion(metadatas) + } + } + + func getMediaMetadatas(predicate: NSPredicate) -> ThreadSafeArray? { + + do { + let realm = try Realm() + let results = realm.objects(tableMetadata.self).filter(predicate).sorted(byKeyPath: "date", ascending: false) + return ThreadSafeArray(results.map { tableMetadata.init(value: $0) }) + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)") + } + + return nil + } + + func getMediaMetadatas(predicate: NSPredicate, sorted: String? = nil, ascending: Bool = false) -> ThreadSafeArray? { + + do { + let realm = try Realm() + if let sorted { + var results: [tableMetadata] = [] + switch NCKeychain().mediaSortDate { + case "date": + results = realm.objects(tableMetadata.self).filter(predicate).sorted { ($0.date as Date) > ($1.date as Date) } + case "creationDate": + results = realm.objects(tableMetadata.self).filter(predicate).sorted { ($0.creationDate as Date) > ($1.creationDate as Date) } + case "uploadDate": + results = realm.objects(tableMetadata.self).filter(predicate).sorted { ($0.uploadDate as Date) > ($1.uploadDate as Date) } + default: + let results = realm.objects(tableMetadata.self).filter(predicate) + return ThreadSafeArray(results.map { tableMetadata.init(value: $0) }) + } + return ThreadSafeArray(results.map { tableMetadata.init(value: $0) }) + } else { + let results = realm.objects(tableMetadata.self).filter(predicate) + return ThreadSafeArray(results.map { tableMetadata.init(value: $0) }) + } + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)") + + return performRealmRead { realm in let object = realm.objects(tableMetadata.self) - .filter("fileId == %@", fileId) + .filter("account == %@ AND serverUrl == %@ AND fileName == %@", account, decodedBaseUrl, fileName) .first return object?.detachedCopy() } + return nil } + + func getAdvancedMetadatas(predicate: NSPredicate, page: Int = 0, limit: Int = 0, sorted: String, ascending: Bool) -> [tableMetadata] { - /// Asynchronously retrieves and sorts `tableMetadata` objects matching a given predicate and layout. - func getMetadatasAsync(predicate: NSPredicate, - withLayout layoutForView: NCDBLayoutForView?, - withAccount account: String) async -> [tableMetadata] { - let detachedMetadatas = await performRealmReadAsync { realm in - realm.objects(tableMetadata.self) - .filter(predicate) - .map { $0.detachedCopy() } - } ?? [] + var metadatas: [tableMetadata] = [] - let sorted = await self.sortedMetadata(layoutForView: layoutForView, account: account, metadatas: detachedMetadatas) - return sorted + do { + let realm = try Realm() + realm.refresh() + let results = realm.objects(tableMetadata.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending) + if !results.isEmpty { + if page == 0 || limit == 0 { + return Array(results.map { tableMetadata.init(value: $0) }) + } else { + let nFrom = (page - 1) * limit + let nTo = nFrom + (limit - 1) + for n in nFrom...nTo { + if n == results.count { + break + } + metadatas.append(tableMetadata.init(value: results[n])) + } + } + } + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)") + } + + return metadatas } - /// Asynchronously retrieves and sorts `tableMetadata` objects matching a given predicate and layout. - func getMetadatasAsyncDataSource(withServerUrl serverUrl: String, - withUserId userId: String, - withAccount account: String, - withLayout layoutForView: NCDBLayoutForView?, - withPreficate predicateSource: NSPredicate? = nil) async -> [tableMetadata] { - var predicate = NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName != %@ AND NOT (status IN %@)", account, serverUrl, NextcloudKit.shared.nkCommonInstance.rootFileName, NCGlobal.shared.metadataStatusHideInView) + func createMetadatasFolder(assets: [PHAsset], + useSubFolder: Bool, + session: NCSession.Session, completion: @escaping ([tableMetadata]) -> Void) { + var foldersCreated: Set = [] + var metadatas: [tableMetadata] = [] + let serverUrlBase = getAccountAutoUploadDirectory(session: session) + let fileNameBase = getAccountAutoUploadFileName(account: session.account) + let predicate = NSPredicate(format: "account == %@ AND serverUrl BEGINSWITH %@ AND directory == true", session.account, serverUrlBase) - if NCPreferences().getPersonalFilesOnly(account: account) { - predicate = NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName != %@ AND (ownerId == %@ || ownerId == '') AND mountType == '' AND NOT (status IN %@)", account, serverUrl, NextcloudKit.shared.nkCommonInstance.rootFileName, userId, NCGlobal.shared.metadataStatusHideInView) - } + func createMetadata(serverUrl: String, fileName: String, metadata: tableMetadata?) { + guard !foldersCreated.contains(serverUrl + "/" + fileName) else { + return + } + foldersCreated.insert(serverUrl + "/" + fileName) - if let predicateSource { - predicate = predicateSource + if let metadata { + metadata.status = NCGlobal.shared.metadataStatusWaitCreateFolder + metadata.sessionSelector = NCGlobal.shared.selectorUploadAutoUpload + metadata.sessionDate = Date() + metadatas.append(tableMetadata(value: metadata)) + } else { + let metadata = NCManageDatabase.shared.createMetadata(fileName: fileName, + fileNameView: fileName, + ocId: NSUUID().uuidString, + serverUrl: serverUrl, + url: "", + contentType: "httpd/unix-directory", + directory: true, + session: session, + sceneIdentifier: nil) + metadata.status = NCGlobal.shared.metadataStatusWaitCreateFolder + metadata.sessionSelector = NCGlobal.shared.selectorUploadAutoUpload + metadata.sessionDate = Date() + metadatas.append(metadata) + } } - let detachedMetadatas = await performRealmReadAsync { realm in - realm.objects(tableMetadata.self) - .filter(predicate) - .map { $0.detachedCopy() } - } ?? [] + let metadatasFolder = getMetadatas(predicate: predicate) + let targetPath = serverUrlBase + "/" + fileNameBase + let metadata = metadatasFolder.first(where: { $0.serverUrl + "/" + $0.fileNameView == targetPath }) + createMetadata(serverUrl: serverUrlBase, fileName: fileNameBase, metadata: metadata) - let cleanedMetadatas = filterAndNormalizeLivePhotos(from: detachedMetadatas) - let sorted = await self.sortedMetadata(layoutForView: layoutForView, account: account, metadatas: cleanedMetadatas) + if useSubFolder { + let autoUploadServerUrlBase = self.getAccountAutoUploadServerUrlBase(session: session) + let autoUploadSubfolderGranularity = self.getAccountAutoUploadSubfolderGranularity() + let folders = Set(assets.map { self.utilityFileSystem.createGranularityPath(asset: $0) }).sorted() - return sorted - } + for folder in folders { + let componentsDate = folder.split(separator: "/") + let year = componentsDate[0] + let serverUrl = autoUploadServerUrlBase + let fileName = String(year) + let targetPath = serverUrl + "/" + fileName + let metadata = metadatasFolder.first(where: { $0.serverUrl + "/" + $0.fileNameView == targetPath }) - func getMetadatasAsync(predicate: NSPredicate, - withSort sortDescriptors: [RealmSwift.SortDescriptor] = [], - withLimit limit: Int? = nil) async -> [tableMetadata]? { - await performRealmReadAsync { realm in - var results = realm.objects(tableMetadata.self) - .filter(predicate) + createMetadata(serverUrl: serverUrl, fileName: fileName, metadata: metadata) - if !sortDescriptors.isEmpty { - results = results.sorted(by: sortDescriptors) - } + if autoUploadSubfolderGranularity >= NCGlobal.shared.subfolderGranularityMonthly { + let month = componentsDate[1] + let serverUrl = autoUploadServerUrlBase + "/" + year + let fileName = String(month) + let targetPath = serverUrl + "/" + fileName + let metadata = metadatasFolder.first(where: { $0.serverUrl + "/" + $0.fileNameView == targetPath }) - if let limit { - let sliced = results.prefix(limit) - return sliced.map { $0.detachedCopy() } + createMetadata(serverUrl: serverUrl, fileName: fileName, metadata: metadata) + + if autoUploadSubfolderGranularity == NCGlobal.shared.subfolderGranularityDaily { + let day = componentsDate[2] + let serverUrl = autoUploadServerUrlBase + "/" + year + "/" + month + let fileName = String(day) + let targetPath = serverUrl + "/" + fileName + let metadata = metadatasFolder.first(where: { $0.serverUrl + "/" + $0.fileNameView == targetPath }) + + createMetadata(serverUrl: serverUrl, fileName: fileName, metadata: metadata) + } + + } + return results + } else { + let results = realm.objects(tableMetadata.self).filter(predicate) + if freeze { + return results.freeze() + } + return results + } + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") + } + return nil + } + + func getCalculateCumulativeHash(for metadatas: [tableMetadata], account: String, serverUrl: String) -> String { + let concatenatedEtags = metadatas.map { $0.etag }.joined(separator: "-") + return sha256Hash(concatenatedEtags) + } + + func getMediaMetadatas(predicate: NSPredicate) -> ThreadSafeArray? { + + do { + let realm = try Realm() + let results = realm.objects(tableMetadata.self).filter(predicate).sorted(byKeyPath: "date", ascending: false) + return ThreadSafeArray(results.map { tableMetadata.init(value: $0) }) + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)") + } + + return nil + } + + func getMediaMetadatas(predicate: NSPredicate, sorted: String? = nil, ascending: Bool = false) -> ThreadSafeArray? { + + do { + let realm = try Realm() + if let sorted { + var results: [tableMetadata] = [] + switch NCKeychain().mediaSortDate { + case "date": + results = realm.objects(tableMetadata.self).filter(predicate).sorted { ($0.date as Date) > ($1.date as Date) } + case "creationDate": + results = realm.objects(tableMetadata.self).filter(predicate).sorted { ($0.creationDate as Date) > ($1.creationDate as Date) } + case "uploadDate": + results = realm.objects(tableMetadata.self).filter(predicate).sorted { ($0.uploadDate as Date) > ($1.uploadDate as Date) } + default: + let results = realm.objects(tableMetadata.self).filter(predicate) + return ThreadSafeArray(results.map { tableMetadata.init(value: $0) }) + } + return ThreadSafeArray(results.map { tableMetadata.init(value: $0) }) } else { - return results.map { $0.detachedCopy() } + let results = realm.objects(tableMetadata.self).filter(predicate) + return ThreadSafeArray(results.map { tableMetadata.init(value: $0) }) } + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)") } + return nil } + + func getAdvancedMetadatas(predicate: NSPredicate, page: Int = 0, limit: Int = 0, sorted: String, ascending: Bool) -> [tableMetadata] { - func hasUploadingMetadataWithChunksOrE2EE() -> Bool { - return performRealmRead { realm in - realm.objects(tableMetadata.self) - .filter("status == %d AND (chunk > 0 OR e2eEncrypted == true)", NCGlobal.shared.metadataStatusUploading) - .first != nil - } ?? false - } + var metadatas: [tableMetadata] = [] - func getMetadataDirectoryAsync(serverUrl: String, account: String) async -> tableMetadata? { - guard let url = URL(string: serverUrl) else { - return nil - } - let fileName = url.lastPathComponent - var baseUrl = url.deletingLastPathComponent().absoluteString - if baseUrl.hasSuffix("/") { - baseUrl.removeLast() - } - guard let decodedBaseUrl = baseUrl.removingPercentEncoding else { - return nil + do { + let realm = try Realm() + realm.refresh() + let results = realm.objects(tableMetadata.self).filter(predicate).sorted(byKeyPath: sorted, ascending: ascending) + if !results.isEmpty { + if page == 0 || limit == 0 { + return Array(results.map { tableMetadata.init(value: $0) }) + } else { + let nFrom = (page - 1) * limit + let nTo = nFrom + (limit - 1) + for n in nFrom...nTo { + if n == results.count { + break + } + metadatas.append(tableMetadata.init(value: results[n])) + } + } + } + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("Could not access database: \(error)") } - return await performRealmReadAsync { realm in - let object = realm.objects(tableMetadata.self) - .filter("account == %@ AND serverUrl == %@ AND fileName == %@", account, decodedBaseUrl, fileName) - .first - return object?.detachedCopy() - } + return metadatas } + + func getResultMetadataFromFileId(_ fileId: String?) -> tableMetadata? { + guard let fileId else { return nil } - func getMetadataDirectory(serverUrl: String, account: String) -> tableMetadata? { - guard let url = URL(string: serverUrl) else { - return nil - } - let fileName = url.lastPathComponent - var baseUrl = url.deletingLastPathComponent().absoluteString - if baseUrl.hasSuffix("/") { - baseUrl.removeLast() - } - guard let decodedBaseUrl = baseUrl.removingPercentEncoding else { - return nil - } - - return performRealmRead { realm in - let object = realm.objects(tableMetadata.self) - .filter("account == %@ AND serverUrl == %@ AND fileName == %@", account, decodedBaseUrl, fileName) - .first - return object?.detachedCopy() + do { + let realm = try Realm() + return realm.objects(tableMetadata.self).filter("fileId == %@", fileId).first + } catch let error as NSError { + NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)") } + return nil } } diff --git a/iOSClient/EmptyView/NCEmptyDataSet.swift b/iOSClient/EmptyView/NCEmptyDataSet.swift new file mode 100644 index 0000000000..389a11d651 --- /dev/null +++ b/iOSClient/EmptyView/NCEmptyDataSet.swift @@ -0,0 +1,129 @@ +// +// NCEmptyDataSet.swift +// Nextcloud +// +// Created by Marino Faggiana on 19/10/2020. +// Copyright © 2020 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +import UIKit + +public protocol NCEmptyDataSetDelegate: AnyObject { + func emptyDataSetView(_ view: NCEmptyView) +} + +// optional func +public extension NCEmptyDataSetDelegate { + func emptyDataSetView(_ view: NCEmptyView) {} +} + +class NCEmptyDataSet: NSObject { + + private var emptyView: NCEmptyView? + private var timer: Timer? + private var numberItemsForSections: Int = 0 + private weak var delegate: NCEmptyDataSetDelegate? + + private var fillBackgroundName: String = "" + private var fillBackgroundView = UIImageView() + + private var centerXAnchor: NSLayoutConstraint? + private var centerYAnchor: NSLayoutConstraint? + + init(view: UIView, offset: CGFloat = 0, delegate: NCEmptyDataSetDelegate?) { + super.init() + + guard let emptyView = NCEmptyView.fromNib().instantiate(withOwner: self, options: nil).first as? NCEmptyView else { return } + + self.delegate = delegate + self.emptyView = emptyView + + emptyView.isHidden = true + emptyView.translatesAutoresizingMaskIntoConstraints = false + + view.addSubview(emptyView) + + emptyView.widthAnchor.constraint(equalToConstant: 350).isActive = true + emptyView.heightAnchor.constraint(equalToConstant: 250).isActive = true + + if let view = view.superview { + centerXAnchor = emptyView.centerXAnchor.constraint(equalTo: view.centerXAnchor) + centerYAnchor = emptyView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: offset) + } else { + centerXAnchor = emptyView.centerXAnchor.constraint(equalTo: view.centerXAnchor) + centerYAnchor = emptyView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: offset) + } + + centerXAnchor?.isActive = true + centerYAnchor?.isActive = true + + } + + func setOffset(_ offset: CGFloat) { + + centerYAnchor?.constant = offset + } + + func numberOfItemsInSection(_ num: Int, section: Int) { + + if section == 0 { + numberItemsForSections = num + } else { + numberItemsForSections += num + } + + if let emptyView = emptyView { + + self.delegate?.emptyDataSetView(emptyView) + + if !(timer?.isValid ?? false) && emptyView.isHidden == true { + timer = Timer.scheduledTimer(timeInterval: 0.3, target: self, selector: #selector(timerHandler(_:)), userInfo: nil, repeats: false) + } + + if numberItemsForSections > 0 { + self.emptyView?.isHidden = true + } + } + } + + @objc func timerHandler(_ timer: Timer) { + + if numberItemsForSections == 0 { + self.emptyView?.isHidden = false + } else { + self.emptyView?.isHidden = true + } + } +} + +public class NCEmptyView: UIView { + + @IBOutlet weak var emptyImage: UIImageView! + @IBOutlet weak var emptyTitle: UILabel! + @IBOutlet weak var emptyDescription: UILabel! + + static func fromNib() -> UINib { + return UINib(nibName: "NCEmptyView", bundle: nil) + } + + public override func awakeFromNib() { + super.awakeFromNib() + + emptyTitle.textColor = .label + } +} diff --git a/iOSClient/EmptyView/NCEmptyView.xib b/iOSClient/EmptyView/NCEmptyView.xib new file mode 100644 index 0000000000..0b5ebbe133 --- /dev/null +++ b/iOSClient/EmptyView/NCEmptyView.xib @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOSClient/Extensions/DateFormatter+Extension.swift b/iOSClient/Extensions/DateFormatter+Extension.swift index dceb24e7e7..2344faac6c 100644 --- a/iOSClient/Extensions/DateFormatter+Extension.swift +++ b/iOSClient/Extensions/DateFormatter+Extension.swift @@ -28,7 +28,21 @@ extension DateFormatter { static let shareExpDate: DateFormatter = { let dateFormatter = DateFormatter() dateFormatter.formatterBehavior = .behavior10_4 +// dateFormatter.locale = Locale.current dateFormatter.dateStyle = .medium + dateFormatter.dateFormat = NCShareAdvancePermission.displayDateFormat return dateFormatter }() } + +extension Date { + static var tomorrow: Date { return Date().dayAfter } + static var today: Date {return Date()} + static var dayAfterYear: Date { return Date().dateAfterYear } + var dayAfter: Date { + return Calendar.current.date(byAdding: .day, value: 1, to: Date())! + } + var dateAfterYear: Date { + return Calendar.current.date(byAdding: .year, value: 1, to: Date())! + } +} diff --git a/iOSClient/Extensions/UIButton+Extension.swift b/iOSClient/Extensions/UIButton+Extension.swift index 8050c15444..3f51b3e365 100644 --- a/iOSClient/Extensions/UIButton+Extension.swift +++ b/iOSClient/Extensions/UIButton+Extension.swift @@ -25,12 +25,21 @@ extension UIButton { } func hideSpinnerAndShowButton() { - let spinnerTag = Int(bitPattern: Unmanaged.passUnretained(self).toOpaque()) - let spinner = self.superview?.subviews.first(where: { view -> Bool in - return view.isKind(of: UIActivityIndicatorView.self) && view.tag == spinnerTag - }) + let spinnerTag = Int(bitPattern: Unmanaged.passUnretained(self).toOpaque()) + let spinner = self.superview?.subviews.first(where: { view -> Bool in + return view.isKind(of: UIActivityIndicatorView.self) && view.tag == spinnerTag + }) - spinner?.removeFromSuperview() - self.isHidden = false - } + spinner?.removeFromSuperview() + self.isHidden = false + } + + func setBackgroundColor(_ color: UIColor, for forState: UIControl.State) { + UIGraphicsBeginImageContext(CGSize(width: 1, height: 1)) + UIGraphicsGetCurrentContext()!.setFillColor(color.cgColor) + UIGraphicsGetCurrentContext()!.fill(CGRect(x: 0, y: 0, width: 1, height: 1)) + let colorImage = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + self.setBackgroundImage(colorImage, for: forState) + } } diff --git a/iOSClient/Extensions/UIImage+Extension.swift b/iOSClient/Extensions/UIImage+Extension.swift index 0502b7f08a..f6e4ed37fb 100644 --- a/iOSClient/Extensions/UIImage+Extension.swift +++ b/iOSClient/Extensions/UIImage+Extension.swift @@ -25,7 +25,7 @@ import Foundation import UIKit import Accelerate -extension UIImage { +extension UIImage: @unchecked Sendable { func resizeImage(size: CGSize, isAspectRation: Bool = true) -> UIImage? { let originRatio = self.size.width / self.size.height let newRatio = size.width / size.height @@ -171,6 +171,7 @@ extension UIImage { /// - pointSize: The target point size /// - scale: The point to pixel scale (Pixeld per point) /// - Returns: The downsampled image, if successful + @MainActor static func downsample(imageAt imageURL: URL, to pointSize: CGSize, scale: CGFloat = UIScreen.main.scale) -> UIImage? { // Create an CGImageSource that represent an image @@ -218,13 +219,14 @@ extension UIImage { return newImage } - func colorizeFolder(metadata: tableMetadata, tblDirectory: tableDirectory? = nil) -> UIImage { + func colorizeFolder(metadata: tableMetadata, tableDirectory: tableDirectory? = nil) -> UIImage { + let serverUrl = metadata.serverUrl + "/" + metadata.fileName var image = self - if let tblDirectory { - if let hex = tblDirectory.colorFolder, let color = UIColor(hex: hex) { + if let tableDirectory = tableDirectory { + if let hex = tableDirectory.colorFolder, let color = UIColor(hex: hex) { image = self.withTintColor(color, renderingMode: .alwaysOriginal) } - } else if let tblDirectory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, metadata.serverUrlFileName)), let hex = tblDirectory.colorFolder, let color = UIColor(hex: hex) { + } else if let tableDirectory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, serverUrl)), let hex = tableDirectory.colorFolder, let color = UIColor(hex: hex) { image = self.withTintColor(color, renderingMode: .alwaysOriginal) } return image @@ -243,6 +245,17 @@ extension UIImage { guard CGImageDestinationFinalize(destination) else { return nil } return mutableData as Data } + + func imageColor(_ color: UIColor) -> UIImage { + if #available(iOS 13.0, *) { + return self.withTintColor(color, renderingMode: .alwaysOriginal) + } else { + return UIGraphicsImageRenderer(size: size, format: imageRendererFormat).image { _ in + color.set() + withRenderingMode(.alwaysTemplate).draw(at: .zero) + } + } + } } extension CGImagePropertyOrientation { @@ -261,3 +274,58 @@ extension CGImagePropertyOrientation { } } } + +// https://stackoverflow.com/questions/16278463/darken-an-uiimage +public extension UIImage { + + private enum BlendMode { + case multiply // This results in colors that are at least as dark as either of the two contributing sample colors + case screen // This results in colors that are at least as light as either of the two contributing sample colors + } + + // A level of zero yeilds the original image, a level of 1 results in black + func darken(level: CGFloat = 0.5) -> UIImage? { + return blend(mode: .multiply, level: level) + } + + // A level of zero yeilds the original image, a level of 1 results in white + func lighten(level: CGFloat = 0.5) -> UIImage? { + return blend(mode: .screen, level: level) + } + + private func blend(mode: BlendMode, level: CGFloat) -> UIImage? { + let context = CIContext(options: nil) + + var level = level + if level < 0 { + level = 0 + } else if level > 1 { + level = 1 + } + + let filterName: String + switch mode { + case .multiply: // As the level increases we get less white + level = abs(level - 1.0) + filterName = "CIMultiplyBlendMode" + case .screen: // As the level increases we get more white + filterName = "CIScreenBlendMode" + } + + let blender = CIFilter(name: filterName)! + let backgroundColor = CIColor(color: UIColor(white: level, alpha: 1)) + + guard let inputImage = CIImage(image: self) else { return nil } + blender.setValue(inputImage, forKey: kCIInputImageKey) + + guard let backgroundImageGenerator = CIFilter(name: "CIConstantColorGenerator") else { return nil } + backgroundImageGenerator.setValue(backgroundColor, forKey: kCIInputColorKey) + guard let backgroundImage = backgroundImageGenerator.outputImage?.cropped(to: CGRect(origin: CGPoint.zero, size: self.size)) else { return nil } + blender.setValue(backgroundImage, forKey: kCIInputBackgroundImageKey) + + guard let blendedImage = blender.outputImage else { return nil } + + guard let cgImage = context.createCGImage(blendedImage, from: blendedImage.extent) else { return nil } + return UIImage(cgImage: cgImage) + } +} diff --git a/iOSClient/Extensions/UIToolbar+Extension.swift b/iOSClient/Extensions/UIToolbar+Extension.swift index 1cf1f6f86b..ac403c9791 100644 --- a/iOSClient/Extensions/UIToolbar+Extension.swift +++ b/iOSClient/Extensions/UIToolbar+Extension.swift @@ -37,7 +37,7 @@ extension UIToolbar { buttons.append(clearButton) } buttons.append(UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)) - let doneButton = UIBarButtonItem(title: NSLocalizedString("_done_", comment: ""), style: .plain) { + let doneButton = UIBarButtonItem(title: NSLocalizedString("_done_", comment: ""), style: .done) { onDone() } buttons.append(doneButton) @@ -58,6 +58,20 @@ extension UIToolbar { ]) return view } + + static func doneToolbar(completion: @escaping () -> Void) -> UIToolbar { + let doneToolbar: UIToolbar = UIToolbar(frame: CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50)) + doneToolbar.barStyle = .default + + let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) + let done: UIBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_done_", comment: ""), style: .done) { + completion() + } + let items = [flexSpace, done] + doneToolbar.items = items + doneToolbar.sizeToFit() + return doneToolbar + } } // https://stackoverflow.com/a/67985180/9506784 diff --git a/iOSClient/Extensions/UIView+Extension.swift b/iOSClient/Extensions/UIView+Extension.swift index c2107d1067..5574e654ac 100644 --- a/iOSClient/Extensions/UIView+Extension.swift +++ b/iOSClient/Extensions/UIView+Extension.swift @@ -24,6 +24,11 @@ import Foundation import UIKit +enum VerticalLocation: String { + case bottom + case top +} + extension UIView { // Source @@ -51,15 +56,21 @@ extension UIView { self.layer.cornerRadius = self.frame.size.width / 2 self.layer.masksToBounds = true } - - var parentTabBarController: UITabBarController? { - var responder: UIResponder? = self - while let nextResponder = responder?.next { - if let tabBarController = nextResponder as? UITabBarController { - return tabBarController - } - responder = nextResponder + + func addShadow(location: VerticalLocation, height: CGFloat = 2, color: UIColor = NCBrandColor.shared.customerDarkGrey, opacity: Float = 0.4, radius: CGFloat = 2) { + switch location { + case .bottom: + addShadow(offset: CGSize(width: 0, height: height), color: color, opacity: opacity, radius: radius) + case .top: + addShadow(offset: CGSize(width: 0, height: -height), color: color, opacity: opacity, radius: radius) } - return nil + } + + func addShadow(offset: CGSize, color: UIColor = .black, opacity: Float = 0.5, radius: CGFloat = 5.0) { + self.layer.masksToBounds = false + self.layer.shadowColor = color.cgColor + self.layer.shadowOffset = offset + self.layer.shadowOpacity = opacity + self.layer.shadowRadius = radius } } diff --git a/iOSClient/Favorites/NCFavorite.swift b/iOSClient/Favorites/NCFavorite.swift index 53c6ef1d06..614670d826 100644 --- a/iOSClient/Favorites/NCFavorite.swift +++ b/iOSClient/Favorites/NCFavorite.swift @@ -12,6 +12,7 @@ class NCFavorite: NCCollectionViewCommon { titleCurrentFolder = NSLocalizedString("_favorites_", comment: "") layoutKey = NCGlobal.shared.layoutViewFavorite enableSearchBar = false + headerMenuButtonsView = true headerRichWorkspaceDisable = true emptyImageName = "star.fill" emptyImageColors = [NCBrandColor.shared.yellowFavorite] diff --git a/iOSClient/Files/NCFiles.swift b/iOSClient/Files/NCFiles.swift index bc379253ee..49d8e7d89e 100644 --- a/iOSClient/Files/NCFiles.swift +++ b/iOSClient/Files/NCFiles.swift @@ -1,6 +1,25 @@ -// SPDX-FileCopyrightText: Nextcloud GmbH -// SPDX-FileCopyrightText: 2020 Marino Faggiana -// SPDX-License-Identifier: GPL-3.0-or-later +// +// NCFiles.swift +// Nextcloud +// +// Created by Marino Faggiana on 26/09/2020. +// Copyright © 2020 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// import UIKit import NextcloudKit @@ -8,15 +27,18 @@ import RealmSwift import SwiftUI class NCFiles: NCCollectionViewCommon { + @IBOutlet weak var plusButton: UIButton! + internal var fileNameBlink: String? internal var fileNameOpen: String? + internal var matadatasHash: String = "" + internal var semaphoreReloadDataSource = DispatchSemaphore(value: 1) + private var timerProcess: Timer? internal var lastOffsetY: CGFloat = 0 internal var lastScrollTime: TimeInterval = 0 internal var accumulatedScrollDown: CGFloat = 0 - internal var syncMetadatasTask: Task? - required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) @@ -33,76 +55,79 @@ class NCFiles: NCCollectionViewCommon { override func viewDidLoad() { super.viewDidLoad() - NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil, queue: nil) { notification in - Task { @MainActor in - if let userInfo = notification.userInfo, - let account = userInfo["account"] as? String, - self.controller?.account == account { - let color = NCBrandColor.shared.getElement(account: account) - self.mainNavigationController?.menuToolbar.items?.forEach { $0.tintColor = color } - } + /// Plus Button + let image = UIImage(systemName: "plus", withConfiguration: UIImage.SymbolConfiguration(scale: .large))?.applyingSymbolConfiguration(UIImage.SymbolConfiguration(paletteColors: [.white])) + + plusButton.setTitle("", for: .normal) + plusButton.setImage(image, for: .normal) + plusButton.backgroundColor = NCBrandColor.shared.getElement(account: session.account) + plusButton.accessibilityLabel = NSLocalizedString("_accessibility_add_upload_", comment: "") + plusButton.layer.cornerRadius = plusButton.frame.size.width / 2.0 + plusButton.layer.masksToBounds = false + plusButton.layer.shadowOffset = CGSize(width: 0, height: 0) + plusButton.layer.shadowRadius = 3.0 + plusButton.layer.shadowOpacity = 0.5 + + NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil, queue: nil) { _ in + if let activeTableAccount = NCManageDatabase.shared.getActiveTableAccount() { + self.plusButton.backgroundColor = NCBrandColor.shared.getElement(account: activeTableAccount.account) } } - - NotificationCenter.default.addObserver(forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: nil) { _ in - self.stopSyncMetadata() - } - + if self.serverUrl.isEmpty { - // - // Set ServerURL when start (isEmpty) - // + + /// + /// Set ServerURL when start (isEmpty) + /// self.serverUrl = utilityFileSystem.getHomeServer(session: session) self.titleCurrentFolder = getNavigationTitle() NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeUser), object: nil, queue: nil) { notification in - Task { @MainActor in - if let userInfo = notification.userInfo, - let controller = userInfo["controller"] as? NCMainTabBarController { - guard controller == self.controller else { - return - } - } - if let userInfo = notification.userInfo, - let account = userInfo["account"] as? String { - let color = NCBrandColor.shared.getElement(account: account) - self.mainNavigationController?.menuToolbar.items?.forEach { - $0.tintColor = color - } + if let userInfo = notification.userInfo, let account = userInfo["account"] as? String { + if let controller = userInfo["controller"] as? NCMainTabBarController, + controller == self.controller { + controller.account = account + controller.availableNotifications = false + } else { + return } + } - self.navigationController?.popToRootViewController(animated: false) - self.serverUrl = self.utilityFileSystem.getHomeServer(session: self.session) - self.isSearchingMode = false - self.isEditMode = false - self.fileSelect.removeAll() - self.layoutForView = self.database.getLayoutForView(account: self.session.account, key: self.layoutKey, serverUrl: self.serverUrl) - - if self.isLayoutList { - self.collectionView?.collectionViewLayout = self.listLayout - } else if self.isLayoutGrid { - self.collectionView?.collectionViewLayout = self.gridLayout - } else if self.isLayoutPhoto { - self.collectionView?.collectionViewLayout = self.mediaLayout - } + self.navigationController?.popToRootViewController(animated: false) + self.serverUrl = self.utilityFileSystem.getHomeServer(session: self.session) + self.isSearchingMode = false + self.isEditMode = false + self.fileSelect.removeAll() + self.layoutForView = self.database.getLayoutForView(account: self.session.account, key: self.layoutKey, serverUrl: self.serverUrl) + self.gridLayout.column = CGFloat(self.layoutForView?.columnGrid ?? 3) + + if self.isLayoutList { + self.collectionView?.collectionViewLayout = self.listLayout + } else if self.isLayoutGrid { + self.collectionView?.collectionViewLayout = self.gridLayout + } else if self.isLayoutPhoto { + self.collectionView?.collectionViewLayout = self.mediaLayout + } - self.titleCurrentFolder = self.getNavigationTitle() - self.navigationItem.title = self.titleCurrentFolder + self.titleCurrentFolder = self.getNavigationTitle() + ///Magentacloud branding changes hide user account button on left navigation bar +// self.setNavigationLeftItems() - await (self.navigationController as? NCMainNavigationController)?.setNavigationLeftItems() - await self.reloadDataSource() - await self.getServerData() - } + self.dataSource.removeAll() + self.reloadDataSource() + self.getServerData() } } + self.timerProcess = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { _ in + self.setNavigationRightItems(enableMenu: false) + }) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - Task { - await self.reloadDataSource() - } + resetPlusButtonAlpha() + reloadDataSource() } override func viewDidAppear(_ animated: Bool) { @@ -124,15 +149,8 @@ class NCFiles: NCCollectionViewCommon { await getServerData() } } - } - - override func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated) - stopSyncMetadata() - Task { - await NCNetworking.shared.networkingTasks.cancel(identifier: "\(self.serverUrl)_NCFiles") - } + self.showTipAutoUpload() } override func viewDidDisappear(_ animated: Bool) { @@ -142,225 +160,223 @@ class NCFiles: NCCollectionViewCommon { fileNameOpen = nil } + // MARK: - Action + + @IBAction func plusButtonAction(_ sender: UIButton) { + resetPlusButtonAlpha() + if let controller = UIApplication.shared.firstWindow?.rootViewController as? NCMainTabBarController { + let serverUrl = controller.currentServerUrl() + if let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", NCSession.shared.getSession(controller: controller).account, serverUrl)) { + if !directory.permissions.contains("CK") { + let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_no_permission_add_file_") + NCContentPresenter().showWarning(error: error) + return + } + } + + let fileFolderPath = NCUtilityFileSystem().getFileNamePath("", serverUrl: serverUrl, session: NCSession.shared.getSession(controller: controller)) + let fileFolderName = (serverUrl as NSString).lastPathComponent + + if !FileNameValidator.checkFolderPath(fileFolderPath, account: controller.account) { + controller.present(UIAlertController.warning(message: "\(String(format: NSLocalizedString("_file_name_validator_error_reserved_name_", comment: ""), fileFolderName)) \(NSLocalizedString("_please_rename_file_", comment: ""))"), animated: true) + + return + } + + self.appDelegate.toggleMenu(controller: controller) + } + + } + // MARK: - DataSource - override func reloadDataSource() async { - guard !isSearchingMode else { - await super.reloadDataSource() - return + override func reloadDataSource() { + guard !isSearchingMode + else { + return super.reloadDataSource() } - self.metadataFolder = await self.database.getMetadataFolderAsync(session: self.session, serverUrl: self.serverUrl) - if let tblDirectory = await self.database.getTableDirectoryAsync(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.session.account, self.serverUrl)) { - self.richWorkspaceText = tblDirectory.richWorkspace + // Watchdog: this is only a fail safe "dead lock", I don't think the timeout will ever be called but at least nothing gets stuck, if after 5 sec. (which is a long time in this routine), the semaphore is still locked + // + if self.semaphoreReloadDataSource.wait(timeout: .now() + 5) == .timedOut { + self.semaphoreReloadDataSource.signal() } - if let metadataFolder { - nkLog(info: "Inside metadata folder \(metadataFolder.fileName) with permissions: \(metadataFolder.permissions)") - // disable + button if no create permission - let color = NCBrandColor.shared.getElement(account: self.session.account) + var predicate = self.defaultPredicate + let predicateDirectory = NSPredicate(format: "account == %@ AND serverUrl == %@", session.account, self.serverUrl) + let dataSourceMetadatas = self.dataSource.getMetadatas() - if let items = self.mainNavigationController?.menuToolbar.items { - for item in items { - item.isEnabled = metadataFolder.isCreatable - item.tintColor = metadataFolder.isCreatable ? color : .lightGray - } - } + if NCKeychain().getPersonalFilesOnly(account: session.account) { + predicate = self.personalFilesOnlyPredicate } - let metadatas = await self.database.getMetadatasAsyncDataSource(withServerUrl: self.serverUrl, - withUserId: self.session.userId, - withAccount: self.session.account, - withLayout: self.layoutForView) + self.metadataFolder = database.getMetadataFolder(session: session, serverUrl: self.serverUrl) + self.richWorkspaceText = database.getTableDirectory(predicate: predicateDirectory)?.richWorkspace - self.dataSource = NCCollectionViewDataSource(metadatas: metadatas, - layoutForView: layoutForView, - account: session.account) - await super.reloadDataSource() + let metadatas = self.database.getResultsMetadatasPredicate(predicate, layoutForView: layoutForView) + self.dataSource = NCCollectionViewDataSource(metadatas: metadatas, layoutForView: layoutForView) - cachingAsync(metadatas: metadatas) - } - - override func getServerData(forced: Bool = false) async { - defer { - restoreDefaultTitle() - startSyncMetadata(metadatas: self.dataSource.getMetadatas()) + if metadatas.isEmpty { + self.semaphoreReloadDataSource.signal() + return super.reloadDataSource() } - Task { - await networking.networkingTasks.cancel(identifier: "\(self.serverUrl)_NCFiles") + self.dataSource.caching(metadatas: metadatas, dataSourceMetadatas: dataSourceMetadatas) { + self.semaphoreReloadDataSource.signal() + super.reloadDataSource() } + } + override func getServerData() { + if UIApplication.shared.applicationState == .background { + NextcloudKit.shared.nkCommonInstance.writeLog("[DEBUG] Files not reload datasource network with the application in background") + return + } guard !isSearchingMode else { return networkSearch() } - func downloadMetadata(_ metadata: tableMetadata) async -> Bool { - let fileSize = utilityFileSystem.fileProviderStorageSize(metadata.ocId, - fileName: metadata.fileNameView, - userId: metadata.userId, - urlBase: metadata.urlBase) + func downloadMetadata(_ metadata: tableMetadata) -> Bool { + let fileSize = utilityFileSystem.fileProviderStorageSize(metadata.ocId, fileNameView: metadata.fileNameView) guard fileSize > 0 else { return false } - if let tblLocalFile = await database.getTableLocalFileAsync(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) { - if tblLocalFile.etag != metadata.etag { + if let localFile = database.getResultsTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))?.first { + if localFile.etag != metadata.etag { return true } } return false } - let resultsReadFolder = await networkReadFolderAsync(serverUrl: self.serverUrl, forced: forced) - guard resultsReadFolder.error == .success, resultsReadFolder.reloadRequired else { - return - } + DispatchQueue.global().async { + self.networkReadFolder { metadatas, isChanged, error in + DispatchQueue.main.async { + self.refreshControl.endRefreshing() - let metadatasForDownload: [tableMetadata] = resultsReadFolder.metadatas ?? self.dataSource.getMetadatas() - Task.detached(priority: .utility) { - for metadata in metadatasForDownload where !metadata.directory { - if await downloadMetadata(metadata) { - if let metadata = await self.database.setMetadataSessionInWaitDownloadAsync(ocId: metadata.ocId, - session: NCNetworking.shared.sessionDownload, - selector: NCGlobal.shared.selectorDownloadFile, - sceneIdentifier: self.controller?.sceneIdentifier) { - await NCNetworking.shared.downloadFile(metadata: metadata) + if isChanged || self.isNumberOfItemsInAllSectionsNull { + self.reloadDataSource() + } + } + + if error == .success { + let metadatas: [tableMetadata] = metadatas ?? self.dataSource.getMetadatas() + for metadata in metadatas where !metadata.directory && downloadMetadata(metadata) { + self.database.setMetadatasSessionInWaitDownload(metadatas: [metadata], + session: NCNetworking.shared.sessionDownload, + selector: NCGlobal.shared.selectorDownloadFile, + sceneIdentifier: self.controller?.sceneIdentifier) + NCNetworking.shared.download(metadata: metadata, withNotificationProgressTask: true) + } + /// Recommendation + if self.isRecommendationActived { + Task.detached { + await NCNetworking.shared.createRecommendations(session: self.session) + } } } } } - - await self.reloadDataSource() } - private func networkReadFolderAsync(serverUrl: String, forced: Bool) async -> (metadatas: [tableMetadata]?, error: NKError, reloadRequired: Bool) { - var reloadRequired: Bool = false - let resultsReadFile = await NCNetworking.shared.readFileAsync(serverUrlFileName: serverUrl, account: session.account) { task in - Task { - await NCNetworking.shared.networkingTasks.track(identifier: "\(self.serverUrl)_NCFiles", task: task) - } + private func networkReadFolder(completion: @escaping (_ metadatas: [tableMetadata]?, _ isDataChanged: Bool, _ error: NKError) -> Void) { + NCNetworking.shared.readFile(serverUrlFileName: serverUrl, account: session.account) { task in + self.dataSourceTask = task if self.dataSource.isEmpty() { self.collectionView.reloadData() } - } - guard resultsReadFile.error == .success, - let metadata = resultsReadFile.metadata else { - return(nil, resultsReadFile.error, reloadRequired) - } - let e2eEncrypted = metadata.e2eEncrypted - let ocId = metadata.ocId - - await self.database.updateDirectoryRichWorkspaceAsync(metadata.richWorkspace, account: resultsReadFile.account, serverUrl: serverUrl) - let tableDirectory = await self.database.getTableDirectoryAsync(ocId: metadata.ocId) - - // Verify LivePhoto - // - reloadRequired = await networking.setLivePhoto(account: resultsReadFile.account) - await NCManageDatabase.shared.deleteLivePhotoError() - - let shouldSkipUpdate: Bool = ( - !forced && - tableDirectory?.etag == metadata.etag && - !metadata.e2eEncrypted && - !self.dataSource.isEmpty() - ) - - if shouldSkipUpdate { - return (nil, NKError(), reloadRequired) - } - - showLoadingTitle() - - let options = NKRequestOptions(timeout: 180) - let (account, metadataFolder, metadatas, error) = await NCNetworking.shared.readFolderAsync(serverUrl: serverUrl, - account: session.account, - options: options) { task in - Task { - await NCNetworking.shared.networkingTasks.track(identifier: "\(self.serverUrl)_NCFiles", task: task) + } completion: { account, metadata, error in + let isDirectoryE2EE = NCUtilityFileSystem().isDirectoryE2EE(session: self.session, serverUrl: self.serverUrl) + guard error == .success, let metadata else { + return completion(nil, false, error) } - if self.dataSource.isEmpty() { - self.collectionView.reloadData() + /// Check change eTag or E2EE or DataSource empty + self.database.updateDirectoryRichWorkspace(metadata.richWorkspace, account: account, serverUrl: self.serverUrl) + let tableDirectory = self.database.getTableDirectory(ocId: metadata.ocId) + guard tableDirectory?.etag != metadata.etag || metadata.e2eEncrypted || self.dataSource.isEmpty() else { + return completion(nil, false, NKError()) } - } - - guard error == .success else { - return(nil, error, reloadRequired) - } - reloadRequired = true - - if let metadataFolder { - self.metadataFolder = metadataFolder.detachedCopy() - self.richWorkspaceText = metadataFolder.richWorkspace - } - - // - // E2EE section - // - - guard e2eEncrypted, - let metadatas, - !metadatas.isEmpty, - NCPreferences().isEndToEndEnabled(account: account), - await !NCNetworkingE2EE().isInUpload(account: account, serverUrl: serverUrl) else { - return(metadatas, error, reloadRequired) - } - - let lock = await self.database.getE2ETokenLockAsync(account: account, serverUrl: serverUrl) - if let e2eToken = lock?.e2eToken { - nkLog(tag: self.global.logTagE2EE, message: "Tocken: \(e2eToken)", minimumLogLevel: .verbose) - } - - let results = await NCNetworkingE2EE().getMetadata(fileId: ocId, e2eToken: lock?.e2eToken, account: account) - - nkLog(tag: self.global.logTagE2EE, message: "Get metadata with error: \(results.error.errorCode)") - nkLog(tag: self.global.logTagE2EE, message: "Get metadata with metadata: \(results.e2eMetadata ?? ""), signature: \(results.signature ?? ""), version \(results.version ?? "")", minimumLogLevel: .verbose) - - guard results.error == .success, - let e2eMetadata = results.e2eMetadata, - let version = results.version else { - - // No metadata fount, re-send it - if results.error.errorCode == NCGlobal.shared.errorResourceNotFound { - NCContentPresenter().showInfo(description: "Metadata not found") - let error = await NCNetworkingE2EE().uploadMetadata(serverUrl: serverUrl, account: account) - if error != .success { - NCContentPresenter().showError(error: error) - } - } else { - // show error - NCContentPresenter().showError(error: results.error) + /// Check Response DataChanged + var checkResponseDataChanged = true + if tableDirectory?.etag.isEmpty ?? true || isDirectoryE2EE || self.dataSource.isEmpty() { + checkResponseDataChanged = false } - return(metadatas, error, reloadRequired) - } - - let errorDecodeMetadata = await NCEndToEndMetadata().decodeMetadata(e2eMetadata, signature: results.signature, serverUrl: serverUrl, session: self.session) - nkLog(debug: "Decode e2ee metadata with error: \(errorDecodeMetadata.errorCode)") + NCNetworking.shared.readFolder(serverUrl: self.serverUrl, + account: metadata.account, + checkResponseDataChanged: checkResponseDataChanged, + queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue) { task in + self.dataSourceTask = task + if self.dataSource.isEmpty() { + self.collectionView.reloadData() + } + } completion: { account, metadataFolder, metadatas, isDataChanged, error in + /// Error + guard error == .success else { + return completion(nil, false, error) + } + /// Updata folder + if let metadataFolder { + self.metadataFolder = metadataFolder + self.richWorkspaceText = metadataFolder.richWorkspace + } + /// check Response Data Changed + if !isDataChanged { + return completion(nil, false, error) + } - if errorDecodeMetadata == .success { - let capabilities = await NKCapabilities.shared.getCapabilities(for: self.session.account) - if version == "v1", capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV20 { - NCContentPresenter().showInfo(description: "Conversion metadata v1 to v2 required, please wait...") - nkLog(tag: self.global.logTagE2EE, message: "Conversion v1 to v2") - NCActivityIndicator.shared.start() + guard let metadataFolder, + isDirectoryE2EE, + NCKeychain().isEndToEndEnabled(account: account), + !NCNetworkingE2EE().isInUpload(account: account, serverUrl: self.serverUrl) else { + return completion(metadatas, true, error) + } - let error = await NCNetworkingE2EE().uploadMetadata(serverUrl: serverUrl, updateVersionV1V2: true, account: account) - if error != .success { - NCContentPresenter().showError(error: error) + /// E2EE + let lock = self.database.getE2ETokenLock(account: account, serverUrl: self.serverUrl) + NCNetworkingE2EE().getMetadata(fileId: metadataFolder.ocId, e2eToken: lock?.e2eToken, account: account) { account, version, e2eMetadata, signature, _, error in + + if error == .success, let e2eMetadata = e2eMetadata { + let error = NCEndToEndMetadata().decodeMetadata(e2eMetadata, signature: signature, serverUrl: self.serverUrl, session: self.session) + + if error == .success { + if version == "v1", NCCapabilities.shared.getCapabilities(account: account).capabilityE2EEApiVersion == NCGlobal.shared.e2eeVersionV20 { + NextcloudKit.shared.nkCommonInstance.writeLog("[E2EE] Conversion v1 to v2") + NCActivityIndicator.shared.start() + Task { + let serverUrl = metadataFolder.serverUrl + "/" + metadataFolder.fileName + let error = await NCNetworkingE2EE().uploadMetadata(serverUrl: serverUrl, updateVersionV1V2: true, account: account) + if error != .success { + NCContentPresenter().showError(error: error) + } + NCActivityIndicator.shared.stop() + } + } + } else { + // Client Diagnostic + self.database.addDiagnostic(account: account, issue: NCGlobal.shared.diagnosticIssueE2eeErrors) + NCContentPresenter().showError(error: error) + } + } else if error.errorCode == NCGlobal.shared.errorResourceNotFound { + // no metadata found, send a new metadata + Task { + let serverUrl = metadataFolder.serverUrl + "/" + metadataFolder.fileName + let error = await NCNetworkingE2EE().uploadMetadata(serverUrl: serverUrl, account: account) + if error != .success { + NCContentPresenter().showError(error: error) + } + } + } else { + NCContentPresenter().showError(error: NKError(errorCode: NCGlobal.shared.errorE2EEKeyDecodeMetadata, errorDescription: "_e2e_error_")) + } + completion(metadatas, true, error) } - NCActivityIndicator.shared.stop() } - } else { - // Client Diagnostic - await self.database.addDiagnosticAsync(account: account, issue: NCGlobal.shared.diagnosticIssueE2eeErrors) - NCContentPresenter().showError(error: error) } - - return (metadatas, error, reloadRequired) } func blinkCell(fileName: String?) { if let fileName = fileName, let metadata = database.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", session.account, self.serverUrl, fileName)) { - let indexPath = self.dataSource.getIndexPathMetadata(ocId: metadata.ocId) + let indexPath = self.dataSource.getIndexPathMetadata(ocId: metadata.ocId).indexPath if let indexPath = indexPath { DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { UIView.animate(withDuration: 0.3) { @@ -380,7 +396,7 @@ class NCFiles: NCCollectionViewCommon { func openFile(fileName: String?) { if let fileName = fileName, let metadata = database.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", session.account, self.serverUrl, fileName)) { - let indexPath = self.dataSource.getIndexPathMetadata(ocId: metadata.ocId) + let indexPath = self.dataSource.getIndexPathMetadata(ocId: metadata.ocId).indexPath if let indexPath = indexPath { DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { self.collectionView(self.collectionView, didSelectItemAt: indexPath) @@ -388,33 +404,54 @@ class NCFiles: NCCollectionViewCommon { } } } + + override func resetPlusButtonAlpha(animated: Bool = true) { + accumulatedScrollDown = 0 + let update = { + self.plusButton.alpha = 1.0 + } + + if animated { + UIView.animate(withDuration: 0.3, animations: update) + } else { + update() + } + } + + override func isHiddenPlusButton(_ isHidden: Bool) { + if isHidden { + UIView.animate(withDuration: 0.5, delay: 0.0, options: [], animations: { + self.plusButton.transform = CGAffineTransform(translationX: 100, y: 0) + self.plusButton.alpha = 0 + }) + } else { + plusButton.transform = CGAffineTransform(translationX: 100, y: 0) + plusButton.alpha = 0 + + UIView.animate(withDuration: 0.5, delay: 0.3, options: [], animations: { + self.plusButton.transform = .identity + self.plusButton.alpha = 1 + }) + } + } // MARK: - NCAccountSettingsModelDelegate - override func accountSettingsDidDismiss(tblAccount: tableAccount?, controller: NCMainTabBarController?) { + override func accountSettingsDidDismiss(tableAccount: tableAccount?, controller: NCMainTabBarController?) { let currentAccount = session.account if database.getAllTableAccount().isEmpty { - let navigationController: UINavigationController? - - if NCBrandOptions.shared.disable_intro, let viewController = UIStoryboard(name: "NCLogin", bundle: nil).instantiateViewController(withIdentifier: "NCLogin") as? NCLogin { - navigationController = UINavigationController(rootViewController: viewController) - } else { - navigationController = UIStoryboard(name: "NCIntro", bundle: nil).instantiateInitialViewController() as? UINavigationController - } - - UIApplication.shared.firstWindow?.rootViewController = navigationController - } else if let account = tblAccount?.account, account != currentAccount { - Task { - await NCAccount().changeAccount(account, userProfile: nil, controller: controller) + if let navigationController = UIStoryboard(name: "NCIntro", bundle: nil).instantiateInitialViewController() as? UINavigationController { + navigationController.modalPresentationStyle = .fullScreen + self.present(navigationController, animated: true) } + } else if let account = tableAccount?.account, account != currentAccount { + NCAccount().changeAccount(account, userProfile: nil, controller: controller) { } } else if self.serverUrl == self.utilityFileSystem.getHomeServer(session: self.session) { self.titleCurrentFolder = getNavigationTitle() navigationItem.title = self.titleCurrentFolder } - Task { - await (self.navigationController as? NCMainNavigationController)?.setNavigationLeftItems() - } +// (self.navigationController as? NCMainNavigationController)?.setNavigationLeftItems() } } diff --git a/iOSClient/Helper/AdjustHelper.h b/iOSClient/Helper/AdjustHelper.h new file mode 100644 index 0000000000..9b63269a17 --- /dev/null +++ b/iOSClient/Helper/AdjustHelper.h @@ -0,0 +1,48 @@ +// +// AdjustHelper.h +// Nextcloud +// +// Created by A200073704 on 17/05/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// +#import +//#import +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef enum : NSUInteger { + Login, + LoginSuccessful, + Sharing, + CreateLink, + DocumentScan, + CameraUpload, + FileUpload, + UseCamera, + Logout, + ResetsApp, + AutomaticUploadPhotosOn, + AutomaticUploadPhotosOff, + ManualBackup, + AutomaticBackup +} TriggerEvent; + +@interface AdjustHelper : NSObject + +@property (nonatomic, strong) NSString *yourAppToken; +@property (nonatomic, strong) NSString *environment; +@property (nonatomic, strong) ADJConfig *adjustConfig; +@property (nonatomic, strong) ADJEvent *eventLogin; +@property (nonatomic, strong) ADJEvent *event; +@property (nonatomic, assign) TriggerEvent triggerEvent; + +-(void)configAdjust; +-(void)subsessionEnd; +-(void)subsessionStart; +-(void)trackLogin; +-(void)trackEvent:(TriggerEvent)event; + +@end + +NS_ASSUME_NONNULL_END diff --git a/iOSClient/Helper/AdjustHelper.m b/iOSClient/Helper/AdjustHelper.m new file mode 100644 index 0000000000..5556a35d13 --- /dev/null +++ b/iOSClient/Helper/AdjustHelper.m @@ -0,0 +1,153 @@ +// +// AdjustHelper.m +// Nextcloud +// +// Created by A200073704 on 17/05/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +#import "AdjustHelper.h" +//#import + +@implementation AdjustHelper + +-(void)configAdjust { + self.yourAppToken = @"1zfaxn19pd7k"; + self.environment = ADJEnvironmentProduction; + self.adjustConfig = [[ADJConfig alloc] initWithAppToken:self.yourAppToken + environment:self.environment]; + [self.adjustConfig setLogLevel:ADJLogLevelVerbose]; + [Adjust initSdk:self.adjustConfig]; +} + +-(void)subsessionEnd { + [Adjust trackSubsessionEnd]; +} + +-(void)subsessionStart { + [Adjust trackSubsessionStart]; +} + +- (void)trackLogin { + self.eventLogin = [[ADJEvent alloc] initWithEventToken:@"p8hl78"]; +// self.eventLogin = [ADJEvent eventWithEventToken:@"p8hl78"]; + [Adjust trackEvent: self.eventLogin]; +} + +-(void)trackEvent:(TriggerEvent)event { +// self.event = [ADJEvent eventWithEventToken:@"gb97gb"]; + BOOL track = [[NSUserDefaults standardUserDefaults] valueForKey:@"isAnalysisDataCollectionSwitchOn"]; + if (!track) { + return; + } + + switch(event){ + case Login: + { + ADJEvent *event = [[ADJEvent alloc] initWithEventToken:@"p8hl78"]; +// event = [ADJEvent eventWithEventToken:@"gb97gb"]; +// self.event = [ADJEvent eventWithEventToken:@"gb97gb"]; + [Adjust trackEvent:event]; + } + break; + case LoginSuccessful: + { + ADJEvent *event = [[ADJEvent alloc] initWithEventToken:@"dowf81"]; + // event = [ADJEvent eventWithEventToken:@"gb97gb"]; + // self.event = [ADJEvent eventWithEventToken:@"gb97gb"]; + [Adjust trackEvent:event]; + } + break; + case Sharing: + { + ADJEvent *event = [[ADJEvent alloc] initWithEventToken:@"mbeoyd"]; + [Adjust trackEvent:event]; + NSLog(@"%@", [event debugDescription]); + } +// self.event = [ADJEvent eventWithEventToken:@"fqtiu7"]; + break; + case CreateLink: + { + ADJEvent *event = [[ADJEvent alloc] initWithEventToken:@"29b333"]; + [Adjust trackEvent:event]; + } +// self.event = [ADJEvent eventWithEventToken:@"qeyql3"]; + break; + case DocumentScan: + { + ADJEvent *event = [[ADJEvent alloc] initWithEventToken:@"im963g"]; + [Adjust trackEvent:event]; + } +// self.event = [ADJEvent eventWithEventToken:@"7fec8n"]; + break; + case CameraUpload: + { + ADJEvent *event = [[ADJEvent alloc] initWithEventToken:@"hf9paq"]; + [Adjust trackEvent:event]; + } +// self.event = [ADJEvent eventWithEventToken:@"v1g6ly"]; + break; + case FileUpload: + { + ADJEvent *event = [[ADJEvent alloc] initWithEventToken:@"hsbk2m"]; + [Adjust trackEvent:event]; + } +// self.event = [ADJEvent eventWithEventToken:@"4rd8r4"]; + break; + case UseCamera: + { + ADJEvent *event = [[ADJEvent alloc] initWithEventToken:@"3czack"]; + [Adjust trackEvent:event]; + } +// self.event = [ADJEvent eventWithEventToken:@"3czack"]; + break; + case Logout: + { + ADJEvent *event = [[ADJEvent alloc] initWithEventToken:@"n5q2qu"]; + [Adjust trackEvent:event]; + } +// self.event = [ADJEvent eventWithEventToken:@"g6mj9y"]; + break; + case ResetsApp: + { + ADJEvent *event = [[ADJEvent alloc] initWithEventToken:@"3sj1xp"]; + [Adjust trackEvent:event]; + } +// self.event = [ADJEvent eventWithEventToken:@"zi18r0"]; + break; + case AutomaticUploadPhotosOn: + { + ADJEvent *event = [[ADJEvent alloc] initWithEventToken:@"5lxz6h"]; + [Adjust trackEvent:event]; + } +// self.event = [ADJEvent eventWithEventToken:@"vwd9yk"]; + break; + case AutomaticUploadPhotosOff: + { + ADJEvent *event = [[ADJEvent alloc] initWithEventToken:@"176496"]; + [Adjust trackEvent:event]; + } +// self.event = [ADJEvent eventWithEventToken:@"e95w5t"]; + break; + case ManualBackup: + { + ADJEvent *event = [[ADJEvent alloc] initWithEventToken:@"oojr4y"]; + [Adjust trackEvent:event]; + } +// self.event = [ADJEvent eventWithEventToken:@"oojr4y"]; + break; + case AutomaticBackup: + { + ADJEvent *event = [[ADJEvent alloc] initWithEventToken:@"7dkhkx"]; + [Adjust trackEvent:event]; + } +// self.event = [ADJEvent eventWithEventToken:@"7dkhkx"]; + break; + + default : + break; + } +// [Adjust trackEvent: self.event]; +} + +@end diff --git a/iOSClient/Helper/TealiumHelper.swift b/iOSClient/Helper/TealiumHelper.swift new file mode 100644 index 0000000000..6d4065b5ea --- /dev/null +++ b/iOSClient/Helper/TealiumHelper.swift @@ -0,0 +1,55 @@ +// +// TealiumHelper.swift +// Nextcloud +// +// Created by A200073704 on 17/05/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// +import TealiumCore +import TealiumLifecycle +import TealiumAutotracking +import TealiumLocation +import TealiumRemoteCommands +import TealiumTagManagement +import TealiumVisitorService +import Foundation + +class TealiumHelper: NSObject { + static let shared = TealiumHelper() + let config = TealiumConfig(account: "telekom", + profile: "magentacloud-app", + environment: "dev") + var tealium: Tealium? + + @objc override init() { + + config.batchingEnabled = true + config.logLevel = .debug + + config.collectors = [Collectors.Lifecycle, + Collectors.Location, + Collectors.VisitorService] + + config.dispatchers = [Dispatchers.TagManagement, + Dispatchers.RemoteCommands] + + tealium = Tealium(config: config, enableCompletion: {value in + print(value) + } + ) + } + + func start() { + _ = TealiumHelper.shared + } + + @objc func trackView(title: String, data: [String: Any]?) { + let tealView = TealiumView(title, dataLayer: data) + TealiumHelper.shared.tealium?.track(tealView) + } + + @objc func trackEvent(title: String, data: [String: Any]?) { + let tealEvent = TealiumEvent(title, dataLayer: data) + TealiumHelper.shared.tealium?.track(tealEvent) + } +} diff --git a/iOSClient/Images.xcassets/Image.imageset/Contents.json b/iOSClient/Images.xcassets/Image.imageset/Contents.json new file mode 100644 index 0000000000..3dcbc3dd3b --- /dev/null +++ b/iOSClient/Images.xcassets/Image.imageset/Contents.json @@ -0,0 +1,9 @@ +{ + "images" : [ + + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/InfoNetwork.imageset/Contents.json b/iOSClient/Images.xcassets/InfoNetwork.imageset/Contents.json index e8722c72c9..a946785164 100644 --- a/iOSClient/Images.xcassets/InfoNetwork.imageset/Contents.json +++ b/iOSClient/Images.xcassets/InfoNetwork.imageset/Contents.json @@ -8,5 +8,8 @@ "info" : { "author" : "xcode", "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true } } diff --git a/iOSClient/Images.xcassets/MenuGroupByAlphabetic.imageset/Contents.json b/iOSClient/Images.xcassets/MenuGroupByAlphabetic.imageset/Contents.json new file mode 100644 index 0000000000..f2f2fc305c --- /dev/null +++ b/iOSClient/Images.xcassets/MenuGroupByAlphabetic.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "MenuGroupByAlphabetic.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "MenuGroupByAlphabetic@3x-1.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "MenuGroupByAlphabetic@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/MenuGroupByAlphabetic.imageset/MenuGroupByAlphabetic.png b/iOSClient/Images.xcassets/MenuGroupByAlphabetic.imageset/MenuGroupByAlphabetic.png new file mode 100644 index 0000000000..6021496449 Binary files /dev/null and b/iOSClient/Images.xcassets/MenuGroupByAlphabetic.imageset/MenuGroupByAlphabetic.png differ diff --git a/iOSClient/Images.xcassets/MenuGroupByAlphabetic.imageset/MenuGroupByAlphabetic@3x-1.png b/iOSClient/Images.xcassets/MenuGroupByAlphabetic.imageset/MenuGroupByAlphabetic@3x-1.png new file mode 100644 index 0000000000..06b658f763 Binary files /dev/null and b/iOSClient/Images.xcassets/MenuGroupByAlphabetic.imageset/MenuGroupByAlphabetic@3x-1.png differ diff --git a/iOSClient/Images.xcassets/MenuGroupByAlphabetic.imageset/MenuGroupByAlphabetic@3x.png b/iOSClient/Images.xcassets/MenuGroupByAlphabetic.imageset/MenuGroupByAlphabetic@3x.png new file mode 100644 index 0000000000..635addc77c Binary files /dev/null and b/iOSClient/Images.xcassets/MenuGroupByAlphabetic.imageset/MenuGroupByAlphabetic@3x.png differ diff --git a/iOSClient/Images.xcassets/MenuGroupByDate.imageset/Contents.json b/iOSClient/Images.xcassets/MenuGroupByDate.imageset/Contents.json new file mode 100644 index 0000000000..a3852fbd0c --- /dev/null +++ b/iOSClient/Images.xcassets/MenuGroupByDate.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "MenuGroupByDate.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "MenuGroupByDate@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "MenuGroupByDate@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/MenuGroupByDate.imageset/MenuGroupByDate.png b/iOSClient/Images.xcassets/MenuGroupByDate.imageset/MenuGroupByDate.png new file mode 100644 index 0000000000..336b9c51b4 Binary files /dev/null and b/iOSClient/Images.xcassets/MenuGroupByDate.imageset/MenuGroupByDate.png differ diff --git a/iOSClient/Images.xcassets/MenuGroupByDate.imageset/MenuGroupByDate@2x.png b/iOSClient/Images.xcassets/MenuGroupByDate.imageset/MenuGroupByDate@2x.png new file mode 100644 index 0000000000..74e1ebfa6a Binary files /dev/null and b/iOSClient/Images.xcassets/MenuGroupByDate.imageset/MenuGroupByDate@2x.png differ diff --git a/iOSClient/Images.xcassets/MenuGroupByDate.imageset/MenuGroupByDate@3x.png b/iOSClient/Images.xcassets/MenuGroupByDate.imageset/MenuGroupByDate@3x.png new file mode 100644 index 0000000000..2fe97b2405 Binary files /dev/null and b/iOSClient/Images.xcassets/MenuGroupByDate.imageset/MenuGroupByDate@3x.png differ diff --git a/iOSClient/Images.xcassets/MenuGroupByFile.imageset/Contents.json b/iOSClient/Images.xcassets/MenuGroupByFile.imageset/Contents.json new file mode 100644 index 0000000000..0b82de579d --- /dev/null +++ b/iOSClient/Images.xcassets/MenuGroupByFile.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "MenuGroupByFile.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "MenuGroupByFile@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "MenuGroupByFile@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/MenuGroupByFile.imageset/MenuGroupByFile.png b/iOSClient/Images.xcassets/MenuGroupByFile.imageset/MenuGroupByFile.png new file mode 100644 index 0000000000..6b04ce66ba Binary files /dev/null and b/iOSClient/Images.xcassets/MenuGroupByFile.imageset/MenuGroupByFile.png differ diff --git a/iOSClient/Images.xcassets/MenuGroupByFile.imageset/MenuGroupByFile@2x.png b/iOSClient/Images.xcassets/MenuGroupByFile.imageset/MenuGroupByFile@2x.png new file mode 100644 index 0000000000..3b31a4482a Binary files /dev/null and b/iOSClient/Images.xcassets/MenuGroupByFile.imageset/MenuGroupByFile@2x.png differ diff --git a/iOSClient/Images.xcassets/MenuGroupByFile.imageset/MenuGroupByFile@3x.png b/iOSClient/Images.xcassets/MenuGroupByFile.imageset/MenuGroupByFile@3x.png new file mode 100644 index 0000000000..a90dfd79eb Binary files /dev/null and b/iOSClient/Images.xcassets/MenuGroupByFile.imageset/MenuGroupByFile@3x.png differ diff --git a/iOSClient/Images.xcassets/MenuOrderByFileName.imageset/Contents.json b/iOSClient/Images.xcassets/MenuOrderByFileName.imageset/Contents.json new file mode 100644 index 0000000000..808b6665c3 --- /dev/null +++ b/iOSClient/Images.xcassets/MenuOrderByFileName.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "MenuOrderByFileName.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "MenuOrderByFileName@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "MenuOrderByFileName@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/MenuOrderByFileName.imageset/MenuOrderByFileName.png b/iOSClient/Images.xcassets/MenuOrderByFileName.imageset/MenuOrderByFileName.png new file mode 100644 index 0000000000..a35bd06791 Binary files /dev/null and b/iOSClient/Images.xcassets/MenuOrderByFileName.imageset/MenuOrderByFileName.png differ diff --git a/iOSClient/Images.xcassets/MenuOrderByFileName.imageset/MenuOrderByFileName@2x.png b/iOSClient/Images.xcassets/MenuOrderByFileName.imageset/MenuOrderByFileName@2x.png new file mode 100644 index 0000000000..56c20ff42b Binary files /dev/null and b/iOSClient/Images.xcassets/MenuOrderByFileName.imageset/MenuOrderByFileName@2x.png differ diff --git a/iOSClient/Images.xcassets/MenuOrderByFileName.imageset/MenuOrderByFileName@3x.png b/iOSClient/Images.xcassets/MenuOrderByFileName.imageset/MenuOrderByFileName@3x.png new file mode 100644 index 0000000000..507d4b99d0 Binary files /dev/null and b/iOSClient/Images.xcassets/MenuOrderByFileName.imageset/MenuOrderByFileName@3x.png differ diff --git a/iOSClient/Images.xcassets/MenuOrdeyByDate.imageset/Contents.json b/iOSClient/Images.xcassets/MenuOrdeyByDate.imageset/Contents.json new file mode 100644 index 0000000000..585e3e21f4 --- /dev/null +++ b/iOSClient/Images.xcassets/MenuOrdeyByDate.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "MenuOrdeyByDate.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "MenuOrdeyByDate@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "MenuOrdeyByDate@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/MenuOrdeyByDate.imageset/MenuOrdeyByDate.png b/iOSClient/Images.xcassets/MenuOrdeyByDate.imageset/MenuOrdeyByDate.png new file mode 100644 index 0000000000..26cc076d0b Binary files /dev/null and b/iOSClient/Images.xcassets/MenuOrdeyByDate.imageset/MenuOrdeyByDate.png differ diff --git a/iOSClient/Images.xcassets/MenuOrdeyByDate.imageset/MenuOrdeyByDate@2x.png b/iOSClient/Images.xcassets/MenuOrdeyByDate.imageset/MenuOrdeyByDate@2x.png new file mode 100644 index 0000000000..e5bcfd733c Binary files /dev/null and b/iOSClient/Images.xcassets/MenuOrdeyByDate.imageset/MenuOrdeyByDate@2x.png differ diff --git a/iOSClient/Images.xcassets/MenuOrdeyByDate.imageset/MenuOrdeyByDate@3x.png b/iOSClient/Images.xcassets/MenuOrdeyByDate.imageset/MenuOrdeyByDate@3x.png new file mode 100644 index 0000000000..b59790550a Binary files /dev/null and b/iOSClient/Images.xcassets/MenuOrdeyByDate.imageset/MenuOrdeyByDate@3x.png differ diff --git a/iOSClient/Images.xcassets/MenuOrdinamentoAscendente.imageset/Contents.json b/iOSClient/Images.xcassets/MenuOrdinamentoAscendente.imageset/Contents.json new file mode 100644 index 0000000000..58efb22821 --- /dev/null +++ b/iOSClient/Images.xcassets/MenuOrdinamentoAscendente.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "MenuOrdinamentoAscendente.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "MenuOrdinamentoAscendente@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "MenuOrdinamentoAscendente@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/MenuOrdinamentoAscendente.imageset/MenuOrdinamentoAscendente.png b/iOSClient/Images.xcassets/MenuOrdinamentoAscendente.imageset/MenuOrdinamentoAscendente.png new file mode 100644 index 0000000000..2314f6244a Binary files /dev/null and b/iOSClient/Images.xcassets/MenuOrdinamentoAscendente.imageset/MenuOrdinamentoAscendente.png differ diff --git a/iOSClient/Images.xcassets/MenuOrdinamentoAscendente.imageset/MenuOrdinamentoAscendente@2x.png b/iOSClient/Images.xcassets/MenuOrdinamentoAscendente.imageset/MenuOrdinamentoAscendente@2x.png new file mode 100644 index 0000000000..075545e1ae Binary files /dev/null and b/iOSClient/Images.xcassets/MenuOrdinamentoAscendente.imageset/MenuOrdinamentoAscendente@2x.png differ diff --git a/iOSClient/Images.xcassets/MenuOrdinamentoAscendente.imageset/MenuOrdinamentoAscendente@3x.png b/iOSClient/Images.xcassets/MenuOrdinamentoAscendente.imageset/MenuOrdinamentoAscendente@3x.png new file mode 100644 index 0000000000..62112d98c9 Binary files /dev/null and b/iOSClient/Images.xcassets/MenuOrdinamentoAscendente.imageset/MenuOrdinamentoAscendente@3x.png differ diff --git a/iOSClient/Images.xcassets/MenuOrdinamentoDiscendente.imageset/Contents.json b/iOSClient/Images.xcassets/MenuOrdinamentoDiscendente.imageset/Contents.json new file mode 100644 index 0000000000..393a100166 --- /dev/null +++ b/iOSClient/Images.xcassets/MenuOrdinamentoDiscendente.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "MenuOrdinamentoDiscendente.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "MenuOrdinamentoDiscendente@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "MenuOrdinamentoDiscendente@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/MenuOrdinamentoDiscendente.imageset/MenuOrdinamentoDiscendente.png b/iOSClient/Images.xcassets/MenuOrdinamentoDiscendente.imageset/MenuOrdinamentoDiscendente.png new file mode 100644 index 0000000000..edbddbffc3 Binary files /dev/null and b/iOSClient/Images.xcassets/MenuOrdinamentoDiscendente.imageset/MenuOrdinamentoDiscendente.png differ diff --git a/iOSClient/Images.xcassets/MenuOrdinamentoDiscendente.imageset/MenuOrdinamentoDiscendente@2x.png b/iOSClient/Images.xcassets/MenuOrdinamentoDiscendente.imageset/MenuOrdinamentoDiscendente@2x.png new file mode 100644 index 0000000000..f698700156 Binary files /dev/null and b/iOSClient/Images.xcassets/MenuOrdinamentoDiscendente.imageset/MenuOrdinamentoDiscendente@2x.png differ diff --git a/iOSClient/Images.xcassets/MenuOrdinamentoDiscendente.imageset/MenuOrdinamentoDiscendente@3x.png b/iOSClient/Images.xcassets/MenuOrdinamentoDiscendente.imageset/MenuOrdinamentoDiscendente@3x.png new file mode 100644 index 0000000000..d53cff0361 Binary files /dev/null and b/iOSClient/Images.xcassets/MenuOrdinamentoDiscendente.imageset/MenuOrdinamentoDiscendente@3x.png differ diff --git a/iOSClient/Images.xcassets/WiFiSmall.imageset/Contents.json b/iOSClient/Images.xcassets/WiFiSmall.imageset/Contents.json new file mode 100644 index 0000000000..0d044c1a4c --- /dev/null +++ b/iOSClient/Images.xcassets/WiFiSmall.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "WiFiSmall.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "WiFiSmall@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "WiFiSmall@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/WiFiSmall.imageset/WiFiSmall.png b/iOSClient/Images.xcassets/WiFiSmall.imageset/WiFiSmall.png new file mode 100644 index 0000000000..3bc239ccf9 Binary files /dev/null and b/iOSClient/Images.xcassets/WiFiSmall.imageset/WiFiSmall.png differ diff --git a/iOSClient/Images.xcassets/WiFiSmall.imageset/WiFiSmall@2x.png b/iOSClient/Images.xcassets/WiFiSmall.imageset/WiFiSmall@2x.png new file mode 100644 index 0000000000..485b92a256 Binary files /dev/null and b/iOSClient/Images.xcassets/WiFiSmall.imageset/WiFiSmall@2x.png differ diff --git a/iOSClient/Images.xcassets/WiFiSmall.imageset/WiFiSmall@3x.png b/iOSClient/Images.xcassets/WiFiSmall.imageset/WiFiSmall@3x.png new file mode 100644 index 0000000000..fa487ba8ea Binary files /dev/null and b/iOSClient/Images.xcassets/WiFiSmall.imageset/WiFiSmall@3x.png differ diff --git a/iOSClient/Images.xcassets/actionSheetModify.imageset/Contents.json b/iOSClient/Images.xcassets/actionSheetModify.imageset/Contents.json new file mode 100644 index 0000000000..da6627652c --- /dev/null +++ b/iOSClient/Images.xcassets/actionSheetModify.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "actionSheetModify.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "actionSheetModify@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "actionSheetModify@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/actionSheetModify.imageset/actionSheetModify.png b/iOSClient/Images.xcassets/actionSheetModify.imageset/actionSheetModify.png new file mode 100644 index 0000000000..d8967d1de6 Binary files /dev/null and b/iOSClient/Images.xcassets/actionSheetModify.imageset/actionSheetModify.png differ diff --git a/iOSClient/Images.xcassets/actionSheetModify.imageset/actionSheetModify@2x.png b/iOSClient/Images.xcassets/actionSheetModify.imageset/actionSheetModify@2x.png new file mode 100644 index 0000000000..17b56ef130 Binary files /dev/null and b/iOSClient/Images.xcassets/actionSheetModify.imageset/actionSheetModify@2x.png differ diff --git a/iOSClient/Images.xcassets/actionSheetModify.imageset/actionSheetModify@3x.png b/iOSClient/Images.xcassets/actionSheetModify.imageset/actionSheetModify@3x.png new file mode 100644 index 0000000000..f6a3f257db Binary files /dev/null and b/iOSClient/Images.xcassets/actionSheetModify.imageset/actionSheetModify@3x.png differ diff --git a/iOSClient/Images.xcassets/activityTypeFailure.imageset/Contents.json b/iOSClient/Images.xcassets/activityTypeFailure.imageset/Contents.json new file mode 100644 index 0000000000..85b2321170 --- /dev/null +++ b/iOSClient/Images.xcassets/activityTypeFailure.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "activityTypeFailure.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "activityTypeFailure@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "activityTypeFailure@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/activityTypeFailure.imageset/activityTypeFailure.png b/iOSClient/Images.xcassets/activityTypeFailure.imageset/activityTypeFailure.png new file mode 100644 index 0000000000..1d37484fd7 Binary files /dev/null and b/iOSClient/Images.xcassets/activityTypeFailure.imageset/activityTypeFailure.png differ diff --git a/iOSClient/Images.xcassets/activityTypeFailure.imageset/activityTypeFailure@2x.png b/iOSClient/Images.xcassets/activityTypeFailure.imageset/activityTypeFailure@2x.png new file mode 100644 index 0000000000..69be6ad1b1 Binary files /dev/null and b/iOSClient/Images.xcassets/activityTypeFailure.imageset/activityTypeFailure@2x.png differ diff --git a/iOSClient/Images.xcassets/activityTypeFailure.imageset/activityTypeFailure@3x.png b/iOSClient/Images.xcassets/activityTypeFailure.imageset/activityTypeFailure@3x.png new file mode 100644 index 0000000000..770e66bc5a Binary files /dev/null and b/iOSClient/Images.xcassets/activityTypeFailure.imageset/activityTypeFailure@3x.png differ diff --git a/iOSClient/Images.xcassets/activityTypeInfo.imageset/Contents.json b/iOSClient/Images.xcassets/activityTypeInfo.imageset/Contents.json new file mode 100644 index 0000000000..273f51bf48 --- /dev/null +++ b/iOSClient/Images.xcassets/activityTypeInfo.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "activityTypeInfo.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "activityTypeInfo@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "activityTypeInfo@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/activityTypeInfo.imageset/activityTypeInfo.png b/iOSClient/Images.xcassets/activityTypeInfo.imageset/activityTypeInfo.png new file mode 100644 index 0000000000..527ac1b7e9 Binary files /dev/null and b/iOSClient/Images.xcassets/activityTypeInfo.imageset/activityTypeInfo.png differ diff --git a/iOSClient/Images.xcassets/activityTypeInfo.imageset/activityTypeInfo@2x.png b/iOSClient/Images.xcassets/activityTypeInfo.imageset/activityTypeInfo@2x.png new file mode 100644 index 0000000000..6cb5f15a34 Binary files /dev/null and b/iOSClient/Images.xcassets/activityTypeInfo.imageset/activityTypeInfo@2x.png differ diff --git a/iOSClient/Images.xcassets/activityTypeInfo.imageset/activityTypeInfo@3x.png b/iOSClient/Images.xcassets/activityTypeInfo.imageset/activityTypeInfo@3x.png new file mode 100644 index 0000000000..b361ee0b85 Binary files /dev/null and b/iOSClient/Images.xcassets/activityTypeInfo.imageset/activityTypeInfo@3x.png differ diff --git a/iOSClient/Images.xcassets/activityTypeInfoServer.imageset/Contents.json b/iOSClient/Images.xcassets/activityTypeInfoServer.imageset/Contents.json new file mode 100644 index 0000000000..5c7837e197 --- /dev/null +++ b/iOSClient/Images.xcassets/activityTypeInfoServer.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "activityTypeInfoServer.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "activityTypeInfoServer@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "activityTypeInfoServer@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/activityTypeInfoServer.imageset/activityTypeInfoServer.png b/iOSClient/Images.xcassets/activityTypeInfoServer.imageset/activityTypeInfoServer.png new file mode 100644 index 0000000000..72e74ae5b8 Binary files /dev/null and b/iOSClient/Images.xcassets/activityTypeInfoServer.imageset/activityTypeInfoServer.png differ diff --git a/iOSClient/Images.xcassets/activityTypeInfoServer.imageset/activityTypeInfoServer@2x.png b/iOSClient/Images.xcassets/activityTypeInfoServer.imageset/activityTypeInfoServer@2x.png new file mode 100644 index 0000000000..2bc1443c19 Binary files /dev/null and b/iOSClient/Images.xcassets/activityTypeInfoServer.imageset/activityTypeInfoServer@2x.png differ diff --git a/iOSClient/Images.xcassets/activityTypeInfoServer.imageset/activityTypeInfoServer@3x.png b/iOSClient/Images.xcassets/activityTypeInfoServer.imageset/activityTypeInfoServer@3x.png new file mode 100644 index 0000000000..a48d98b9f4 Binary files /dev/null and b/iOSClient/Images.xcassets/activityTypeInfoServer.imageset/activityTypeInfoServer@3x.png differ diff --git a/iOSClient/Images.xcassets/activityTypeSuccess.imageset/Contents.json b/iOSClient/Images.xcassets/activityTypeSuccess.imageset/Contents.json new file mode 100644 index 0000000000..d3c47f9815 --- /dev/null +++ b/iOSClient/Images.xcassets/activityTypeSuccess.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "activityTypeSuccess.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "activityTypeSucces@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "activityTypeSuccess@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/activityTypeSuccess.imageset/activityTypeSucces@2x.png b/iOSClient/Images.xcassets/activityTypeSuccess.imageset/activityTypeSucces@2x.png new file mode 100644 index 0000000000..28e57fa267 Binary files /dev/null and b/iOSClient/Images.xcassets/activityTypeSuccess.imageset/activityTypeSucces@2x.png differ diff --git a/iOSClient/Images.xcassets/activityTypeSuccess.imageset/activityTypeSuccess.png b/iOSClient/Images.xcassets/activityTypeSuccess.imageset/activityTypeSuccess.png new file mode 100644 index 0000000000..f9c151a727 Binary files /dev/null and b/iOSClient/Images.xcassets/activityTypeSuccess.imageset/activityTypeSuccess.png differ diff --git a/iOSClient/Images.xcassets/activityTypeSuccess.imageset/activityTypeSuccess@3x.png b/iOSClient/Images.xcassets/activityTypeSuccess.imageset/activityTypeSuccess@3x.png new file mode 100644 index 0000000000..6cfba6c4fd Binary files /dev/null and b/iOSClient/Images.xcassets/activityTypeSuccess.imageset/activityTypeSuccess@3x.png differ diff --git a/iOSClient/Images.xcassets/addFolder.imageset/Contents.json b/iOSClient/Images.xcassets/addFolder.imageset/Contents.json new file mode 100644 index 0000000000..c3efac3643 --- /dev/null +++ b/iOSClient/Images.xcassets/addFolder.imageset/Contents.json @@ -0,0 +1,56 @@ +{ + "images" : [ + { + "filename" : "addFolder.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "addFolderDark.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "addFolder@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "addFolderDark@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "addFolder@3x.png", + "idiom" : "universal", + "scale" : "3x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "addFolderDark@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/addFolder.imageset/addFolder.png b/iOSClient/Images.xcassets/addFolder.imageset/addFolder.png new file mode 100644 index 0000000000..01b4edc846 Binary files /dev/null and b/iOSClient/Images.xcassets/addFolder.imageset/addFolder.png differ diff --git a/iOSClient/Images.xcassets/addFolder.imageset/addFolder@2x.png b/iOSClient/Images.xcassets/addFolder.imageset/addFolder@2x.png new file mode 100644 index 0000000000..36b5f67ed9 Binary files /dev/null and b/iOSClient/Images.xcassets/addFolder.imageset/addFolder@2x.png differ diff --git a/iOSClient/Images.xcassets/addFolder.imageset/addFolder@3x.png b/iOSClient/Images.xcassets/addFolder.imageset/addFolder@3x.png new file mode 100644 index 0000000000..63f36fef80 Binary files /dev/null and b/iOSClient/Images.xcassets/addFolder.imageset/addFolder@3x.png differ diff --git a/iOSClient/Images.xcassets/addFolder.imageset/addFolderDark.png b/iOSClient/Images.xcassets/addFolder.imageset/addFolderDark.png new file mode 100644 index 0000000000..021899fc7c Binary files /dev/null and b/iOSClient/Images.xcassets/addFolder.imageset/addFolderDark.png differ diff --git a/iOSClient/Images.xcassets/addFolder.imageset/addFolderDark@2x.png b/iOSClient/Images.xcassets/addFolder.imageset/addFolderDark@2x.png new file mode 100644 index 0000000000..a4eede1fd9 Binary files /dev/null and b/iOSClient/Images.xcassets/addFolder.imageset/addFolderDark@2x.png differ diff --git a/iOSClient/Images.xcassets/addFolder.imageset/addFolderDark@3x.png b/iOSClient/Images.xcassets/addFolder.imageset/addFolderDark@3x.png new file mode 100644 index 0000000000..bc59610706 Binary files /dev/null and b/iOSClient/Images.xcassets/addFolder.imageset/addFolderDark@3x.png differ diff --git a/iOSClient/Images.xcassets/addFolderInfo.imageset/Contents.json b/iOSClient/Images.xcassets/addFolderInfo.imageset/Contents.json new file mode 100644 index 0000000000..bfc9b6a226 --- /dev/null +++ b/iOSClient/Images.xcassets/addFolderInfo.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "addFolderInfo.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/addFolderInfo.imageset/addFolderInfo.pdf b/iOSClient/Images.xcassets/addFolderInfo.imageset/addFolderInfo.pdf new file mode 100644 index 0000000000..874d974e1b Binary files /dev/null and b/iOSClient/Images.xcassets/addFolderInfo.imageset/addFolderInfo.pdf differ diff --git a/iOSClient/Images.xcassets/address.imageset/Contents.json b/iOSClient/Images.xcassets/address.imageset/Contents.json new file mode 100644 index 0000000000..5b5d33f9fb --- /dev/null +++ b/iOSClient/Images.xcassets/address.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "address.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/address.imageset/address.pdf b/iOSClient/Images.xcassets/address.imageset/address.pdf new file mode 100644 index 0000000000..0860bb2b76 Binary files /dev/null and b/iOSClient/Images.xcassets/address.imageset/address.pdf differ diff --git a/iOSClient/Images.xcassets/application.imageset/Contents.json b/iOSClient/Images.xcassets/application.imageset/Contents.json new file mode 100644 index 0000000000..3b9c152375 --- /dev/null +++ b/iOSClient/Images.xcassets/application.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "application.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/application.imageset/application.pdf b/iOSClient/Images.xcassets/application.imageset/application.pdf new file mode 100644 index 0000000000..8260068619 Binary files /dev/null and b/iOSClient/Images.xcassets/application.imageset/application.pdf differ diff --git a/iOSClient/Images.xcassets/arrow.forward.square.imageset/Contents.json b/iOSClient/Images.xcassets/arrow.forward.square.imageset/Contents.json new file mode 100644 index 0000000000..0ba67da948 --- /dev/null +++ b/iOSClient/Images.xcassets/arrow.forward.square.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "arrow-right-bold-box-outline.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/arrow.forward.square.imageset/arrow-right-bold-box-outline.svg b/iOSClient/Images.xcassets/arrow.forward.square.imageset/arrow-right-bold-box-outline.svg new file mode 100644 index 0000000000..2532280572 --- /dev/null +++ b/iOSClient/Images.xcassets/arrow.forward.square.imageset/arrow-right-bold-box-outline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/directory.imageset/Contents.json b/iOSClient/Images.xcassets/arrow.up.right.square.imageset/Contents.json similarity index 84% rename from iOSClient/Images.xcassets/directory.imageset/Contents.json rename to iOSClient/Images.xcassets/arrow.up.right.square.imageset/Contents.json index 30d89a66b2..ba9ee6e434 100644 --- a/iOSClient/Images.xcassets/directory.imageset/Contents.json +++ b/iOSClient/Images.xcassets/arrow.up.right.square.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "directory.pdf", + "filename" : "Unknown.svg", "idiom" : "universal" } ], diff --git a/iOSClient/Images.xcassets/arrow.up.right.square.imageset/Unknown.svg b/iOSClient/Images.xcassets/arrow.up.right.square.imageset/Unknown.svg new file mode 100644 index 0000000000..364925ef85 --- /dev/null +++ b/iOSClient/Images.xcassets/arrow.up.right.square.imageset/Unknown.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/audioPlay.imageset/Contents.json b/iOSClient/Images.xcassets/audioPlay.imageset/Contents.json new file mode 100644 index 0000000000..0efd94c42a --- /dev/null +++ b/iOSClient/Images.xcassets/audioPlay.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "play.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/audioPlay.imageset/play.pdf b/iOSClient/Images.xcassets/audioPlay.imageset/play.pdf new file mode 100644 index 0000000000..54a7ce1700 Binary files /dev/null and b/iOSClient/Images.xcassets/audioPlay.imageset/play.pdf differ diff --git a/iOSClient/Images.xcassets/autoUpload.imageset/Contents.json b/iOSClient/Images.xcassets/autoUpload.imageset/Contents.json new file mode 100644 index 0000000000..e65583e6eb --- /dev/null +++ b/iOSClient/Images.xcassets/autoUpload.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "camera-outline.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/autoUpload.imageset/camera-outline.svg b/iOSClient/Images.xcassets/autoUpload.imageset/camera-outline.svg new file mode 100644 index 0000000000..3fc1c37b2e --- /dev/null +++ b/iOSClient/Images.xcassets/autoUpload.imageset/camera-outline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/backward.imageset/Contents.json b/iOSClient/Images.xcassets/backward.imageset/Contents.json new file mode 100644 index 0000000000..3940e5e48a --- /dev/null +++ b/iOSClient/Images.xcassets/backward.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "backward.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/backward.imageset/backward.svg b/iOSClient/Images.xcassets/backward.imageset/backward.svg new file mode 100644 index 0000000000..9b8d324edb --- /dev/null +++ b/iOSClient/Images.xcassets/backward.imageset/backward.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/businesstype.imageset/Contents.json b/iOSClient/Images.xcassets/businesstype.imageset/Contents.json new file mode 100644 index 0000000000..1c6770c981 --- /dev/null +++ b/iOSClient/Images.xcassets/businesstype.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "businesstype.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/businesstype.imageset/businesstype.pdf b/iOSClient/Images.xcassets/businesstype.imageset/businesstype.pdf new file mode 100644 index 0000000000..fd349393c6 Binary files /dev/null and b/iOSClient/Images.xcassets/businesstype.imageset/businesstype.pdf differ diff --git a/iOSClient/Images.xcassets/caldavcardav.imageset/Contents.json b/iOSClient/Images.xcassets/caldavcardav.imageset/Contents.json new file mode 100644 index 0000000000..a1aca4cacd --- /dev/null +++ b/iOSClient/Images.xcassets/caldavcardav.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "icons8-calendario-delle-persone.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/caldavcardav.imageset/icons8-calendario-delle-persone.svg b/iOSClient/Images.xcassets/caldavcardav.imageset/icons8-calendario-delle-persone.svg new file mode 100644 index 0000000000..f45b9ec9a6 --- /dev/null +++ b/iOSClient/Images.xcassets/caldavcardav.imageset/icons8-calendario-delle-persone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/calenderNew.imageset/Contents.json b/iOSClient/Images.xcassets/calenderNew.imageset/Contents.json new file mode 100644 index 0000000000..880c251ea0 --- /dev/null +++ b/iOSClient/Images.xcassets/calenderNew.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "calenderNew.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "calenderNew@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "calenderNew@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/calenderNew.imageset/calenderNew.png b/iOSClient/Images.xcassets/calenderNew.imageset/calenderNew.png new file mode 100644 index 0000000000..8740adcad6 Binary files /dev/null and b/iOSClient/Images.xcassets/calenderNew.imageset/calenderNew.png differ diff --git a/iOSClient/Images.xcassets/calenderNew.imageset/calenderNew@2x.png b/iOSClient/Images.xcassets/calenderNew.imageset/calenderNew@2x.png new file mode 100644 index 0000000000..d5304afd2d Binary files /dev/null and b/iOSClient/Images.xcassets/calenderNew.imageset/calenderNew@2x.png differ diff --git a/iOSClient/Images.xcassets/calenderNew.imageset/calenderNew@3x.png b/iOSClient/Images.xcassets/calenderNew.imageset/calenderNew@3x.png new file mode 100644 index 0000000000..7188fb52e0 Binary files /dev/null and b/iOSClient/Images.xcassets/calenderNew.imageset/calenderNew@3x.png differ diff --git a/iOSClient/Images.xcassets/capabilities.imageset/Contents.json b/iOSClient/Images.xcassets/capabilities.imageset/Contents.json new file mode 100644 index 0000000000..f25afae1ee --- /dev/null +++ b/iOSClient/Images.xcassets/capabilities.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "format-list-bulleted.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/capabilities.imageset/format-list-bulleted.svg b/iOSClient/Images.xcassets/capabilities.imageset/format-list-bulleted.svg new file mode 100644 index 0000000000..3eb8f96f9f --- /dev/null +++ b/iOSClient/Images.xcassets/capabilities.imageset/format-list-bulleted.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/checkedYes.imageset/Contents.json b/iOSClient/Images.xcassets/checkedYes.imageset/Contents.json new file mode 100644 index 0000000000..0b5d3dafc8 --- /dev/null +++ b/iOSClient/Images.xcassets/checkedYes.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "filename" : "green-white-filled@500w.pdf", + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "green-Gray90-filled copy@500w.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/checkedYes.imageset/green-Gray90-filled copy@500w.pdf b/iOSClient/Images.xcassets/checkedYes.imageset/green-Gray90-filled copy@500w.pdf new file mode 100644 index 0000000000..a689619ff2 Binary files /dev/null and b/iOSClient/Images.xcassets/checkedYes.imageset/green-Gray90-filled copy@500w.pdf differ diff --git a/iOSClient/Images.xcassets/checkedYes.imageset/green-white-filled@500w.pdf b/iOSClient/Images.xcassets/checkedYes.imageset/green-white-filled@500w.pdf new file mode 100644 index 0000000000..f47e13070e Binary files /dev/null and b/iOSClient/Images.xcassets/checkedYes.imageset/green-white-filled@500w.pdf differ diff --git a/iOSClient/Images.xcassets/checkmark.imageset/Contents.json b/iOSClient/Images.xcassets/checkmark.imageset/Contents.json new file mode 100644 index 0000000000..cdaeb04a44 --- /dev/null +++ b/iOSClient/Images.xcassets/checkmark.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "check.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/checkmark.imageset/check.svg b/iOSClient/Images.xcassets/checkmark.imageset/check.svg new file mode 100644 index 0000000000..68e30c18bf --- /dev/null +++ b/iOSClient/Images.xcassets/checkmark.imageset/check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/circle.grid.cross.down.fill.imageset/Contents.json b/iOSClient/Images.xcassets/circle.grid.cross.down.fill.imageset/Contents.json new file mode 100644 index 0000000000..a96275cf93 --- /dev/null +++ b/iOSClient/Images.xcassets/circle.grid.cross.down.fill.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "sortCreatedDate.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/circle.grid.cross.down.fill.imageset/sortCreatedDate.pdf b/iOSClient/Images.xcassets/circle.grid.cross.down.fill.imageset/sortCreatedDate.pdf new file mode 100644 index 0000000000..ddebfd8ceb Binary files /dev/null and b/iOSClient/Images.xcassets/circle.grid.cross.down.fill.imageset/sortCreatedDate.pdf differ diff --git a/iOSClient/Images.xcassets/circle.grid.cross.right.fill.imageset/Contents.json b/iOSClient/Images.xcassets/circle.grid.cross.right.fill.imageset/Contents.json new file mode 100644 index 0000000000..935c5b1a59 --- /dev/null +++ b/iOSClient/Images.xcassets/circle.grid.cross.right.fill.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "sortUploadDate.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/circle.grid.cross.right.fill.imageset/sortUploadDate.pdf b/iOSClient/Images.xcassets/circle.grid.cross.right.fill.imageset/sortUploadDate.pdf new file mode 100644 index 0000000000..0a500b1a47 Binary files /dev/null and b/iOSClient/Images.xcassets/circle.grid.cross.right.fill.imageset/sortUploadDate.pdf differ diff --git a/iOSClient/Images.xcassets/circle.grid.cross.up.fill.imageset/Contents.json b/iOSClient/Images.xcassets/circle.grid.cross.up.fill.imageset/Contents.json new file mode 100644 index 0000000000..11689d266c --- /dev/null +++ b/iOSClient/Images.xcassets/circle.grid.cross.up.fill.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "sortModifiedDate.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/circle.grid.cross.up.fill.imageset/sortModifiedDate.pdf b/iOSClient/Images.xcassets/circle.grid.cross.up.fill.imageset/sortModifiedDate.pdf new file mode 100644 index 0000000000..6736d87ad5 Binary files /dev/null and b/iOSClient/Images.xcassets/circle.grid.cross.up.fill.imageset/sortModifiedDate.pdf differ diff --git a/iOSClient/Images.xcassets/circle.imageset/Contents.json b/iOSClient/Images.xcassets/circle.imageset/Contents.json new file mode 100644 index 0000000000..4db51fb5a6 --- /dev/null +++ b/iOSClient/Images.xcassets/circle.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "checkedNo.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/circle.imageset/checkedNo.pdf b/iOSClient/Images.xcassets/circle.imageset/checkedNo.pdf new file mode 100644 index 0000000000..d9d96bea85 Binary files /dev/null and b/iOSClient/Images.xcassets/circle.imageset/checkedNo.pdf differ diff --git a/iOSClient/Images.xcassets/city.imageset/Contents.json b/iOSClient/Images.xcassets/city.imageset/Contents.json new file mode 100644 index 0000000000..91e3e1fe0e --- /dev/null +++ b/iOSClient/Images.xcassets/city.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "city.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/city.imageset/city.pdf b/iOSClient/Images.xcassets/city.imageset/city.pdf new file mode 100644 index 0000000000..3bf8a0dc83 Binary files /dev/null and b/iOSClient/Images.xcassets/city.imageset/city.pdf differ diff --git a/iOSClient/Images.xcassets/cityzip.imageset/Contents.json b/iOSClient/Images.xcassets/cityzip.imageset/Contents.json new file mode 100644 index 0000000000..5f7eb33844 --- /dev/null +++ b/iOSClient/Images.xcassets/cityzip.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "cityzip.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/cityzip.imageset/cityzip.pdf b/iOSClient/Images.xcassets/cityzip.imageset/cityzip.pdf new file mode 100644 index 0000000000..2ceae8c760 Binary files /dev/null and b/iOSClient/Images.xcassets/cityzip.imageset/cityzip.pdf differ diff --git a/iOSClient/Images.xcassets/clear.imageset/Contents.json b/iOSClient/Images.xcassets/clear.imageset/Contents.json new file mode 100644 index 0000000000..f1d0224ac4 --- /dev/null +++ b/iOSClient/Images.xcassets/clear.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "clear.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/clear.imageset/clear.pdf b/iOSClient/Images.xcassets/clear.imageset/clear.pdf new file mode 100644 index 0000000000..240a72b22d Binary files /dev/null and b/iOSClient/Images.xcassets/clear.imageset/clear.pdf differ diff --git a/iOSClient/Images.xcassets/closeCircle.imageset/Contents.json b/iOSClient/Images.xcassets/closeCircle.imageset/Contents.json new file mode 100644 index 0000000000..97c449e694 --- /dev/null +++ b/iOSClient/Images.xcassets/closeCircle.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "closeCircle.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/directory.imageset/directory.pdf b/iOSClient/Images.xcassets/closeCircle.imageset/closeCircle.pdf similarity index 61% rename from iOSClient/Images.xcassets/directory.imageset/directory.pdf rename to iOSClient/Images.xcassets/closeCircle.imageset/closeCircle.pdf index 2bab530b52..5b391d1af6 100644 Binary files a/iOSClient/Images.xcassets/directory.imageset/directory.pdf and b/iOSClient/Images.xcassets/closeCircle.imageset/closeCircle.pdf differ diff --git a/iOSClient/Images.xcassets/cloudDownload.imageset/Contents.json b/iOSClient/Images.xcassets/cloudDownload.imageset/Contents.json new file mode 100644 index 0000000000..63c1601220 --- /dev/null +++ b/iOSClient/Images.xcassets/cloudDownload.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "cloudDownload.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/cloudDownload.imageset/cloudDownload.pdf b/iOSClient/Images.xcassets/cloudDownload.imageset/cloudDownload.pdf new file mode 100644 index 0000000000..600f62feda Binary files /dev/null and b/iOSClient/Images.xcassets/cloudDownload.imageset/cloudDownload.pdf differ diff --git a/iOSClient/Images.xcassets/cloudUpload.imageset/Contents.json b/iOSClient/Images.xcassets/cloudUpload.imageset/Contents.json new file mode 100644 index 0000000000..8d7e531cd6 --- /dev/null +++ b/iOSClient/Images.xcassets/cloudUpload.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "cloudUpload.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/cloudUpload.imageset/cloudUpload.pdf b/iOSClient/Images.xcassets/cloudUpload.imageset/cloudUpload.pdf new file mode 100644 index 0000000000..6985e202b0 Binary files /dev/null and b/iOSClient/Images.xcassets/cloudUpload.imageset/cloudUpload.pdf differ diff --git a/iOSClient/Images.xcassets/comment.imageset/Contents.json b/iOSClient/Images.xcassets/comment.imageset/Contents.json new file mode 100644 index 0000000000..68748032a0 --- /dev/null +++ b/iOSClient/Images.xcassets/comment.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "comment.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/shareTypeEmail.imageset/shareTypeEmail.pdf b/iOSClient/Images.xcassets/comment.imageset/comment.pdf similarity index 51% rename from iOSClient/Images.xcassets/shareTypeEmail.imageset/shareTypeEmail.pdf rename to iOSClient/Images.xcassets/comment.imageset/comment.pdf index 48b0f832f5..97aae2ea20 100644 Binary files a/iOSClient/Images.xcassets/shareTypeEmail.imageset/shareTypeEmail.pdf and b/iOSClient/Images.xcassets/comment.imageset/comment.pdf differ diff --git a/iOSClient/Images.xcassets/comments.imageset/Contents.json b/iOSClient/Images.xcassets/comments.imageset/Contents.json new file mode 100644 index 0000000000..942972f7aa --- /dev/null +++ b/iOSClient/Images.xcassets/comments.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "comments.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/comments.imageset/comments.pdf b/iOSClient/Images.xcassets/comments.imageset/comments.pdf new file mode 100644 index 0000000000..a060b48ba5 Binary files /dev/null and b/iOSClient/Images.xcassets/comments.imageset/comments.pdf differ diff --git a/iOSClient/Images.xcassets/company.imageset/Contents.json b/iOSClient/Images.xcassets/company.imageset/Contents.json new file mode 100644 index 0000000000..e2f8bd4746 --- /dev/null +++ b/iOSClient/Images.xcassets/company.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "company.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/document.imageset/document.pdf b/iOSClient/Images.xcassets/company.imageset/company.pdf similarity index 59% rename from iOSClient/Images.xcassets/document.imageset/document.pdf rename to iOSClient/Images.xcassets/company.imageset/company.pdf index eed811dc9a..eee8b91aa7 100644 Binary files a/iOSClient/Images.xcassets/document.imageset/document.pdf and b/iOSClient/Images.xcassets/company.imageset/company.pdf differ diff --git a/iOSClient/Images.xcassets/contact.imageset/Contents.json b/iOSClient/Images.xcassets/contact.imageset/Contents.json new file mode 100644 index 0000000000..581aa7969d --- /dev/null +++ b/iOSClient/Images.xcassets/contact.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "contact.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "contact@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "contact@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/contact.imageset/contact.png b/iOSClient/Images.xcassets/contact.imageset/contact.png new file mode 100644 index 0000000000..1eafc7a680 Binary files /dev/null and b/iOSClient/Images.xcassets/contact.imageset/contact.png differ diff --git a/iOSClient/Images.xcassets/contact.imageset/contact@2x.png b/iOSClient/Images.xcassets/contact.imageset/contact@2x.png new file mode 100644 index 0000000000..c3841a20bd Binary files /dev/null and b/iOSClient/Images.xcassets/contact.imageset/contact@2x.png differ diff --git a/iOSClient/Images.xcassets/contact.imageset/contact@3x.png b/iOSClient/Images.xcassets/contact.imageset/contact@3x.png new file mode 100644 index 0000000000..fbfc494222 Binary files /dev/null and b/iOSClient/Images.xcassets/contact.imageset/contact@3x.png differ diff --git a/iOSClient/Images.xcassets/contactOld.imageset/Contents.json b/iOSClient/Images.xcassets/contactOld.imageset/Contents.json new file mode 100644 index 0000000000..212bb4dfb1 --- /dev/null +++ b/iOSClient/Images.xcassets/contactOld.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "contact.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/contactOld.imageset/contact.svg b/iOSClient/Images.xcassets/contactOld.imageset/contact.svg new file mode 100644 index 0000000000..6b3f9684ae --- /dev/null +++ b/iOSClient/Images.xcassets/contactOld.imageset/contact.svg @@ -0,0 +1,7 @@ + + + 01_24px/icon/user_file/contacts/default + + + + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/copy.imageset/Contents.json b/iOSClient/Images.xcassets/copy.imageset/Contents.json new file mode 100644 index 0000000000..f711ad67af --- /dev/null +++ b/iOSClient/Images.xcassets/copy.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "copy.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/copy.imageset/copy.pdf b/iOSClient/Images.xcassets/copy.imageset/copy.pdf new file mode 100644 index 0000000000..fb90c89c8e Binary files /dev/null and b/iOSClient/Images.xcassets/copy.imageset/copy.pdf differ diff --git a/iOSClient/Images.xcassets/country.imageset/Contents.json b/iOSClient/Images.xcassets/country.imageset/Contents.json new file mode 100644 index 0000000000..a2a693d280 --- /dev/null +++ b/iOSClient/Images.xcassets/country.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "country.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/country.imageset/country.pdf b/iOSClient/Images.xcassets/country.imageset/country.pdf new file mode 100644 index 0000000000..f9667fe22a Binary files /dev/null and b/iOSClient/Images.xcassets/country.imageset/country.pdf differ diff --git a/iOSClient/Images.xcassets/crashservice.imageset/Contents.json b/iOSClient/Images.xcassets/crashservice.imageset/Contents.json new file mode 100644 index 0000000000..b1436bb6d2 --- /dev/null +++ b/iOSClient/Images.xcassets/crashservice.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "bug-outline.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/crashservice.imageset/bug-outline.svg b/iOSClient/Images.xcassets/crashservice.imageset/bug-outline.svg new file mode 100644 index 0000000000..d58d933f8e --- /dev/null +++ b/iOSClient/Images.xcassets/crashservice.imageset/bug-outline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/create_file_document.imageset/Contents.json b/iOSClient/Images.xcassets/create_file_document.imageset/Contents.json new file mode 100644 index 0000000000..356e75ee11 --- /dev/null +++ b/iOSClient/Images.xcassets/create_file_document.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "file_text 1.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/create_file_document.imageset/file_text 1.pdf b/iOSClient/Images.xcassets/create_file_document.imageset/file_text 1.pdf new file mode 100644 index 0000000000..95241831e1 Binary files /dev/null and b/iOSClient/Images.xcassets/create_file_document.imageset/file_text 1.pdf differ diff --git a/iOSClient/Images.xcassets/create_file_ppt.imageset/Contents.json b/iOSClient/Images.xcassets/create_file_ppt.imageset/Contents.json new file mode 100644 index 0000000000..b976e2da22 --- /dev/null +++ b/iOSClient/Images.xcassets/create_file_ppt.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "file_ppt.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/create_file_ppt.imageset/file_ppt.pdf b/iOSClient/Images.xcassets/create_file_ppt.imageset/file_ppt.pdf new file mode 100644 index 0000000000..c127187374 Binary files /dev/null and b/iOSClient/Images.xcassets/create_file_ppt.imageset/file_ppt.pdf differ diff --git a/iOSClient/Images.xcassets/create_file_xls.imageset/Contents.json b/iOSClient/Images.xcassets/create_file_xls.imageset/Contents.json new file mode 100644 index 0000000000..72c7b90297 --- /dev/null +++ b/iOSClient/Images.xcassets/create_file_xls.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "file-calculation.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/create_file_xls.imageset/file-calculation.pdf b/iOSClient/Images.xcassets/create_file_xls.imageset/file-calculation.pdf new file mode 100644 index 0000000000..1c9642dbab Binary files /dev/null and b/iOSClient/Images.xcassets/create_file_xls.imageset/file-calculation.pdf differ diff --git a/iOSClient/Images.xcassets/dataPrivacy.imageset/Contents.json b/iOSClient/Images.xcassets/dataPrivacy.imageset/Contents.json new file mode 100644 index 0000000000..4fb0d4c09c --- /dev/null +++ b/iOSClient/Images.xcassets/dataPrivacy.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "default copy@2x.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "default copy@3x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "default copy@4x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/dataPrivacy.imageset/default copy@2x.png b/iOSClient/Images.xcassets/dataPrivacy.imageset/default copy@2x.png new file mode 100644 index 0000000000..40c3e7d47f Binary files /dev/null and b/iOSClient/Images.xcassets/dataPrivacy.imageset/default copy@2x.png differ diff --git a/iOSClient/Images.xcassets/dataPrivacy.imageset/default copy@3x.png b/iOSClient/Images.xcassets/dataPrivacy.imageset/default copy@3x.png new file mode 100644 index 0000000000..74d9dbb7dd Binary files /dev/null and b/iOSClient/Images.xcassets/dataPrivacy.imageset/default copy@3x.png differ diff --git a/iOSClient/Images.xcassets/dataPrivacy.imageset/default copy@4x.png b/iOSClient/Images.xcassets/dataPrivacy.imageset/default copy@4x.png new file mode 100644 index 0000000000..682122c3f2 Binary files /dev/null and b/iOSClient/Images.xcassets/dataPrivacy.imageset/default copy@4x.png differ diff --git a/iOSClient/Images.xcassets/deleteScan.imageset/Contents.json b/iOSClient/Images.xcassets/deleteScan.imageset/Contents.json new file mode 100644 index 0000000000..a339b95ca4 --- /dev/null +++ b/iOSClient/Images.xcassets/deleteScan.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "deleteScan.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "deleteScan@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "deleteScan@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/deleteScan.imageset/deleteScan.png b/iOSClient/Images.xcassets/deleteScan.imageset/deleteScan.png new file mode 100644 index 0000000000..c7a4ff62f0 Binary files /dev/null and b/iOSClient/Images.xcassets/deleteScan.imageset/deleteScan.png differ diff --git a/iOSClient/Images.xcassets/deleteScan.imageset/deleteScan@2x.png b/iOSClient/Images.xcassets/deleteScan.imageset/deleteScan@2x.png new file mode 100644 index 0000000000..d0b2037c59 Binary files /dev/null and b/iOSClient/Images.xcassets/deleteScan.imageset/deleteScan@2x.png differ diff --git a/iOSClient/Images.xcassets/deleteScan.imageset/deleteScan@3x.png b/iOSClient/Images.xcassets/deleteScan.imageset/deleteScan@3x.png new file mode 100644 index 0000000000..b6526408be Binary files /dev/null and b/iOSClient/Images.xcassets/deleteScan.imageset/deleteScan@3x.png differ diff --git a/iOSClient/Images.xcassets/diagram.imageset/Contents.json b/iOSClient/Images.xcassets/diagram.imageset/Contents.json new file mode 100644 index 0000000000..6cbdad9726 --- /dev/null +++ b/iOSClient/Images.xcassets/diagram.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "diagram.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/diagram.imageset/diagram.svg b/iOSClient/Images.xcassets/diagram.imageset/diagram.svg new file mode 100644 index 0000000000..ae5b35d9ef --- /dev/null +++ b/iOSClient/Images.xcassets/diagram.imageset/diagram.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/disclosureIndicator.imageset/Contents.json b/iOSClient/Images.xcassets/disclosureIndicator.imageset/Contents.json new file mode 100644 index 0000000000..da15f89512 --- /dev/null +++ b/iOSClient/Images.xcassets/disclosureIndicator.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "disclosureIndicator@2x.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/disclosureIndicator.imageset/disclosureIndicator@2x.png b/iOSClient/Images.xcassets/disclosureIndicator.imageset/disclosureIndicator@2x.png new file mode 100644 index 0000000000..7f4605655a Binary files /dev/null and b/iOSClient/Images.xcassets/disclosureIndicator.imageset/disclosureIndicator@2x.png differ diff --git a/iOSClient/Images.xcassets/document.imageset/Contents.json b/iOSClient/Images.xcassets/document.imageset/Contents.json index 847026cf24..63f2a7bb2a 100644 --- a/iOSClient/Images.xcassets/document.imageset/Contents.json +++ b/iOSClient/Images.xcassets/document.imageset/Contents.json @@ -1,15 +1,15 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "document.pdf" + "filename" : "file_text.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { "preserves-vector-representation" : true } -} \ No newline at end of file +} diff --git a/iOSClient/Images.xcassets/document.imageset/file_text.pdf b/iOSClient/Images.xcassets/document.imageset/file_text.pdf new file mode 100644 index 0000000000..95241831e1 Binary files /dev/null and b/iOSClient/Images.xcassets/document.imageset/file_text.pdf differ diff --git a/iOSClient/Images.xcassets/downArrow.imageset/Contents.json b/iOSClient/Images.xcassets/downArrow.imageset/Contents.json new file mode 100644 index 0000000000..81ef9bbb37 --- /dev/null +++ b/iOSClient/Images.xcassets/downArrow.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "downArrow@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/downArrow.imageset/downArrow@2x.png b/iOSClient/Images.xcassets/downArrow.imageset/downArrow@2x.png new file mode 100644 index 0000000000..6da8c3c9c5 Binary files /dev/null and b/iOSClient/Images.xcassets/downArrow.imageset/downArrow@2x.png differ diff --git a/iOSClient/Images.xcassets/e2eReadPassphrase.imageset/Contents.json b/iOSClient/Images.xcassets/e2eReadPassphrase.imageset/Contents.json new file mode 100644 index 0000000000..f3789cc3bb --- /dev/null +++ b/iOSClient/Images.xcassets/e2eReadPassphrase.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "e2eReadPassphrase.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/e2eReadPassphrase.imageset/e2eReadPassphrase.pdf b/iOSClient/Images.xcassets/e2eReadPassphrase.imageset/e2eReadPassphrase.pdf new file mode 100644 index 0000000000..d0ef6af164 Binary files /dev/null and b/iOSClient/Images.xcassets/e2eReadPassphrase.imageset/e2eReadPassphrase.pdf differ diff --git a/iOSClient/Images.xcassets/editNew.imageset/Contents.json b/iOSClient/Images.xcassets/editNew.imageset/Contents.json new file mode 100644 index 0000000000..cdb886f349 --- /dev/null +++ b/iOSClient/Images.xcassets/editNew.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "editNew.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "editNew@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "editNew@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/editNew.imageset/editNew.png b/iOSClient/Images.xcassets/editNew.imageset/editNew.png new file mode 100644 index 0000000000..ff3bf49a82 Binary files /dev/null and b/iOSClient/Images.xcassets/editNew.imageset/editNew.png differ diff --git a/iOSClient/Images.xcassets/editNew.imageset/editNew@2x.png b/iOSClient/Images.xcassets/editNew.imageset/editNew@2x.png new file mode 100644 index 0000000000..46415573f0 Binary files /dev/null and b/iOSClient/Images.xcassets/editNew.imageset/editNew@2x.png differ diff --git a/iOSClient/Images.xcassets/editNew.imageset/editNew@3x.png b/iOSClient/Images.xcassets/editNew.imageset/editNew@3x.png new file mode 100644 index 0000000000..27f7dff1cf Binary files /dev/null and b/iOSClient/Images.xcassets/editNew.imageset/editNew@3x.png differ diff --git a/iOSClient/Images.xcassets/editUserProfile.imageset/Contents.json b/iOSClient/Images.xcassets/editUserProfile.imageset/Contents.json new file mode 100644 index 0000000000..ae240a41a3 --- /dev/null +++ b/iOSClient/Images.xcassets/editUserProfile.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "editUserProfile.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/editUserProfile.imageset/editUserProfile.pdf b/iOSClient/Images.xcassets/editUserProfile.imageset/editUserProfile.pdf new file mode 100644 index 0000000000..b3fbbbd0b5 Binary files /dev/null and b/iOSClient/Images.xcassets/editUserProfile.imageset/editUserProfile.pdf differ diff --git a/iOSClient/Images.xcassets/email.imageset/Contents.json b/iOSClient/Images.xcassets/email.imageset/Contents.json new file mode 100644 index 0000000000..565a76d806 --- /dev/null +++ b/iOSClient/Images.xcassets/email.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "mail.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/email.imageset/mail.pdf b/iOSClient/Images.xcassets/email.imageset/mail.pdf new file mode 100644 index 0000000000..33d54d385e Binary files /dev/null and b/iOSClient/Images.xcassets/email.imageset/mail.pdf differ diff --git a/iOSClient/Images.xcassets/encryptedfolder.imageset/Contents.json b/iOSClient/Images.xcassets/encryptedfolder.imageset/Contents.json new file mode 100644 index 0000000000..37e424164b --- /dev/null +++ b/iOSClient/Images.xcassets/encryptedfolder.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "encrypted folder.svg", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/encryptedfolder.imageset/encrypted folder.svg b/iOSClient/Images.xcassets/encryptedfolder.imageset/encrypted folder.svg new file mode 100644 index 0000000000..454ea06f3b --- /dev/null +++ b/iOSClient/Images.xcassets/encryptedfolder.imageset/encrypted folder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/favoriteSmall.imageset/Contents.json b/iOSClient/Images.xcassets/favoriteSmall.imageset/Contents.json new file mode 100644 index 0000000000..dbb4c2c5e1 --- /dev/null +++ b/iOSClient/Images.xcassets/favoriteSmall.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "videoFavoriteOn.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/favoriteSmall.imageset/videoFavoriteOn.pdf b/iOSClient/Images.xcassets/favoriteSmall.imageset/videoFavoriteOn.pdf new file mode 100644 index 0000000000..7b18400a76 Binary files /dev/null and b/iOSClient/Images.xcassets/favoriteSmall.imageset/videoFavoriteOn.pdf differ diff --git a/iOSClient/Images.xcassets/file.imageset/Contents.json b/iOSClient/Images.xcassets/file.imageset/Contents.json index 48ca8dd53d..34568170ce 100644 --- a/iOSClient/Images.xcassets/file.imageset/Contents.json +++ b/iOSClient/Images.xcassets/file.imageset/Contents.json @@ -1,15 +1,15 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "file.pdf" + "filename" : "file.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { "preserves-vector-representation" : true } -} \ No newline at end of file +} diff --git a/iOSClient/Images.xcassets/file.imageset/file.pdf b/iOSClient/Images.xcassets/file.imageset/file.pdf index e629726c98..bdbe2682c2 100644 Binary files a/iOSClient/Images.xcassets/file.imageset/file.pdf and b/iOSClient/Images.xcassets/file.imageset/file.pdf differ diff --git a/iOSClient/Images.xcassets/file_application.imageset/Contents.json b/iOSClient/Images.xcassets/file_application.imageset/Contents.json new file mode 100644 index 0000000000..31e255fd34 --- /dev/null +++ b/iOSClient/Images.xcassets/file_application.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "file_application.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/file_application.imageset/file_application.pdf b/iOSClient/Images.xcassets/file_application.imageset/file_application.pdf new file mode 100644 index 0000000000..987c78d183 Binary files /dev/null and b/iOSClient/Images.xcassets/file_application.imageset/file_application.pdf differ diff --git a/iOSClient/Images.xcassets/file_audio.imageset/Contents.json b/iOSClient/Images.xcassets/file_audio.imageset/Contents.json new file mode 100644 index 0000000000..165f3569e0 --- /dev/null +++ b/iOSClient/Images.xcassets/file_audio.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "file-audio.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/file_audio.imageset/file-audio.pdf b/iOSClient/Images.xcassets/file_audio.imageset/file-audio.pdf new file mode 100644 index 0000000000..ac39ce823a Binary files /dev/null and b/iOSClient/Images.xcassets/file_audio.imageset/file-audio.pdf differ diff --git a/iOSClient/Images.xcassets/file_code.imageset/Contents.json b/iOSClient/Images.xcassets/file_code.imageset/Contents.json new file mode 100644 index 0000000000..c967791083 --- /dev/null +++ b/iOSClient/Images.xcassets/file_code.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "file_code.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/file_code.imageset/file_code.pdf b/iOSClient/Images.xcassets/file_code.imageset/file_code.pdf new file mode 100644 index 0000000000..74613b5ac9 Binary files /dev/null and b/iOSClient/Images.xcassets/file_code.imageset/file_code.pdf differ diff --git a/iOSClient/Images.xcassets/file_compress.imageset/Contents.json b/iOSClient/Images.xcassets/file_compress.imageset/Contents.json new file mode 100644 index 0000000000..4a32eb8305 --- /dev/null +++ b/iOSClient/Images.xcassets/file_compress.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "file_compress.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/file_compress.imageset/file_compress.pdf b/iOSClient/Images.xcassets/file_compress.imageset/file_compress.pdf new file mode 100644 index 0000000000..491b479d9d Binary files /dev/null and b/iOSClient/Images.xcassets/file_compress.imageset/file_compress.pdf differ diff --git a/iOSClient/Images.xcassets/file_movie.imageset/Contents.json b/iOSClient/Images.xcassets/file_movie.imageset/Contents.json new file mode 100644 index 0000000000..7993c40c5b --- /dev/null +++ b/iOSClient/Images.xcassets/file_movie.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "file-video.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/file_movie.imageset/file-video.pdf b/iOSClient/Images.xcassets/file_movie.imageset/file-video.pdf new file mode 100644 index 0000000000..6b6a451b42 Binary files /dev/null and b/iOSClient/Images.xcassets/file_movie.imageset/file-video.pdf differ diff --git a/iOSClient/Images.xcassets/file_pdf.imageset/Contents.json b/iOSClient/Images.xcassets/file_pdf.imageset/Contents.json index 05026cff7f..2f97942cc1 100644 --- a/iOSClient/Images.xcassets/file_pdf.imageset/Contents.json +++ b/iOSClient/Images.xcassets/file_pdf.imageset/Contents.json @@ -1,12 +1,15 @@ { "images" : [ { - "filename" : "file_pdf.svg", + "filename" : "file-pdf.pdf", "idiom" : "universal" } ], "info" : { "author" : "xcode", "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true } } diff --git a/iOSClient/Images.xcassets/file_pdf.imageset/file-pdf.pdf b/iOSClient/Images.xcassets/file_pdf.imageset/file-pdf.pdf new file mode 100644 index 0000000000..aea9e1e55e Binary files /dev/null and b/iOSClient/Images.xcassets/file_pdf.imageset/file-pdf.pdf differ diff --git a/iOSClient/Images.xcassets/file_pdf.imageset/file_pdf.svg b/iOSClient/Images.xcassets/file_pdf.imageset/file_pdf.svg deleted file mode 100644 index 02fb207294..0000000000 --- a/iOSClient/Images.xcassets/file_pdf.imageset/file_pdf.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/iOSClient/Images.xcassets/file_photo.imageset/Contents.json b/iOSClient/Images.xcassets/file_photo.imageset/Contents.json index ca8f401824..b854b32ca4 100644 --- a/iOSClient/Images.xcassets/file_photo.imageset/Contents.json +++ b/iOSClient/Images.xcassets/file_photo.imageset/Contents.json @@ -1,15 +1,15 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "file_photo.pdf" + "filename" : "file_photo.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { "preserves-vector-representation" : true } -} \ No newline at end of file +} diff --git a/iOSClient/Images.xcassets/file_photo.imageset/file_photo.pdf b/iOSClient/Images.xcassets/file_photo.imageset/file_photo.pdf index a95c3f5577..a47ec6136f 100644 Binary files a/iOSClient/Images.xcassets/file_photo.imageset/file_photo.pdf and b/iOSClient/Images.xcassets/file_photo.imageset/file_photo.pdf differ diff --git a/iOSClient/Images.xcassets/file_photo_menu.imageset/Contents.json b/iOSClient/Images.xcassets/file_photo_menu.imageset/Contents.json new file mode 100644 index 0000000000..94f24bec38 --- /dev/null +++ b/iOSClient/Images.xcassets/file_photo_menu.imageset/Contents.json @@ -0,0 +1,52 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "file_photo_menu.pdf", + "idiom" : "universal", + "scale" : "2x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "default copy@500w.pdf", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/file_photo_menu.imageset/default copy@500w.pdf b/iOSClient/Images.xcassets/file_photo_menu.imageset/default copy@500w.pdf new file mode 100644 index 0000000000..47f3245514 Binary files /dev/null and b/iOSClient/Images.xcassets/file_photo_menu.imageset/default copy@500w.pdf differ diff --git a/iOSClient/Images.xcassets/file_photo_menu.imageset/file_photo_menu.pdf b/iOSClient/Images.xcassets/file_photo_menu.imageset/file_photo_menu.pdf new file mode 100644 index 0000000000..2439cdd6b2 Binary files /dev/null and b/iOSClient/Images.xcassets/file_photo_menu.imageset/file_photo_menu.pdf differ diff --git a/iOSClient/Images.xcassets/file_ppt.imageset/Contents.json b/iOSClient/Images.xcassets/file_ppt.imageset/Contents.json new file mode 100644 index 0000000000..b976e2da22 --- /dev/null +++ b/iOSClient/Images.xcassets/file_ppt.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "file_ppt.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/file_ppt.imageset/file_ppt.pdf b/iOSClient/Images.xcassets/file_ppt.imageset/file_ppt.pdf new file mode 100644 index 0000000000..c127187374 Binary files /dev/null and b/iOSClient/Images.xcassets/file_ppt.imageset/file_ppt.pdf differ diff --git a/iOSClient/Images.xcassets/file_txt.imageset/Contents.json b/iOSClient/Images.xcassets/file_txt.imageset/Contents.json new file mode 100644 index 0000000000..5bdfa81f6a --- /dev/null +++ b/iOSClient/Images.xcassets/file_txt.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "file_txt.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/file_txt.imageset/file_txt.pdf b/iOSClient/Images.xcassets/file_txt.imageset/file_txt.pdf new file mode 100644 index 0000000000..bdbe2682c2 Binary files /dev/null and b/iOSClient/Images.xcassets/file_txt.imageset/file_txt.pdf differ diff --git a/iOSClient/Images.xcassets/file_txt_menu.imageset/Contents.json b/iOSClient/Images.xcassets/file_txt_menu.imageset/Contents.json new file mode 100644 index 0000000000..6f4aef470f --- /dev/null +++ b/iOSClient/Images.xcassets/file_txt_menu.imageset/Contents.json @@ -0,0 +1,56 @@ +{ + "images" : [ + { + "filename" : "fileText.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "fileTextDark.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "fileText@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "fileTextDark@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "fileText@3x.png", + "idiom" : "universal", + "scale" : "3x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "fileTextDark@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/file_txt_menu.imageset/fileText.png b/iOSClient/Images.xcassets/file_txt_menu.imageset/fileText.png new file mode 100644 index 0000000000..2d13982ecd Binary files /dev/null and b/iOSClient/Images.xcassets/file_txt_menu.imageset/fileText.png differ diff --git a/iOSClient/Images.xcassets/file_txt_menu.imageset/fileText@2x.png b/iOSClient/Images.xcassets/file_txt_menu.imageset/fileText@2x.png new file mode 100644 index 0000000000..be32ea9f60 Binary files /dev/null and b/iOSClient/Images.xcassets/file_txt_menu.imageset/fileText@2x.png differ diff --git a/iOSClient/Images.xcassets/file_txt_menu.imageset/fileText@3x.png b/iOSClient/Images.xcassets/file_txt_menu.imageset/fileText@3x.png new file mode 100644 index 0000000000..73f455751b Binary files /dev/null and b/iOSClient/Images.xcassets/file_txt_menu.imageset/fileText@3x.png differ diff --git a/iOSClient/Images.xcassets/file_txt_menu.imageset/fileTextDark.png b/iOSClient/Images.xcassets/file_txt_menu.imageset/fileTextDark.png new file mode 100644 index 0000000000..03c4b10325 Binary files /dev/null and b/iOSClient/Images.xcassets/file_txt_menu.imageset/fileTextDark.png differ diff --git a/iOSClient/Images.xcassets/file_txt_menu.imageset/fileTextDark@2x.png b/iOSClient/Images.xcassets/file_txt_menu.imageset/fileTextDark@2x.png new file mode 100644 index 0000000000..3d25bf1702 Binary files /dev/null and b/iOSClient/Images.xcassets/file_txt_menu.imageset/fileTextDark@2x.png differ diff --git a/iOSClient/Images.xcassets/file_txt_menu.imageset/fileTextDark@3x.png b/iOSClient/Images.xcassets/file_txt_menu.imageset/fileTextDark@3x.png new file mode 100644 index 0000000000..32ac4b3355 Binary files /dev/null and b/iOSClient/Images.xcassets/file_txt_menu.imageset/fileTextDark@3x.png differ diff --git a/iOSClient/Images.xcassets/file_xls.imageset/Contents.json b/iOSClient/Images.xcassets/file_xls.imageset/Contents.json new file mode 100644 index 0000000000..72c7b90297 --- /dev/null +++ b/iOSClient/Images.xcassets/file_xls.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "file-calculation.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/file_xls.imageset/file-calculation.pdf b/iOSClient/Images.xcassets/file_xls.imageset/file-calculation.pdf new file mode 100644 index 0000000000..1c9642dbab Binary files /dev/null and b/iOSClient/Images.xcassets/file_xls.imageset/file-calculation.pdf differ diff --git a/iOSClient/Images.xcassets/folder-photo.imageset/Contents.json b/iOSClient/Images.xcassets/folder-photo.imageset/Contents.json new file mode 100644 index 0000000000..2786542100 --- /dev/null +++ b/iOSClient/Images.xcassets/folder-photo.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "folder-photo.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/folder-photo.imageset/folder-photo.pdf b/iOSClient/Images.xcassets/folder-photo.imageset/folder-photo.pdf new file mode 100644 index 0000000000..f646199438 Binary files /dev/null and b/iOSClient/Images.xcassets/folder-photo.imageset/folder-photo.pdf differ diff --git a/iOSClient/Images.xcassets/folder-share.imageset/Contents.json b/iOSClient/Images.xcassets/folder-share.imageset/Contents.json new file mode 100644 index 0000000000..63a3af51db --- /dev/null +++ b/iOSClient/Images.xcassets/folder-share.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "folder-share.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/folder-share.imageset/folder-share.pdf b/iOSClient/Images.xcassets/folder-share.imageset/folder-share.pdf new file mode 100644 index 0000000000..4a5832ff32 Binary files /dev/null and b/iOSClient/Images.xcassets/folder-share.imageset/folder-share.pdf differ diff --git a/iOSClient/Images.xcassets/folder.imageset/Contents.json b/iOSClient/Images.xcassets/folder.imageset/Contents.json index 68fa26d8d7..6ceb844517 100644 --- a/iOSClient/Images.xcassets/folder.imageset/Contents.json +++ b/iOSClient/Images.xcassets/folder.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "folder.svg", + "filename" : "folder.png", "idiom" : "universal" } ], @@ -10,7 +10,6 @@ "version" : 1 }, "properties" : { - "preserves-vector-representation" : true, - "template-rendering-intent" : "template" + "preserves-vector-representation" : true } } diff --git a/iOSClient/Images.xcassets/folder.imageset/folder.png b/iOSClient/Images.xcassets/folder.imageset/folder.png new file mode 100644 index 0000000000..005b163e55 Binary files /dev/null and b/iOSClient/Images.xcassets/folder.imageset/folder.png differ diff --git a/iOSClient/Images.xcassets/folder.imageset/folder.svg b/iOSClient/Images.xcassets/folder.imageset/folder.svg deleted file mode 100644 index b3bf667783..0000000000 --- a/iOSClient/Images.xcassets/folder.imageset/folder.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/iOSClient/Images.xcassets/folderAutomaticUpload.imageset/Contents.json b/iOSClient/Images.xcassets/folderAutomaticUpload.imageset/Contents.json index 51ff0d5d02..2786542100 100644 --- a/iOSClient/Images.xcassets/folderAutomaticUpload.imageset/Contents.json +++ b/iOSClient/Images.xcassets/folderAutomaticUpload.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "folder_photo.svg", + "filename" : "folder-photo.pdf", "idiom" : "universal" } ], @@ -10,7 +10,6 @@ "version" : 1 }, "properties" : { - "preserves-vector-representation" : true, - "template-rendering-intent" : "template" + "preserves-vector-representation" : true } } diff --git a/iOSClient/Images.xcassets/folderAutomaticUpload.imageset/folder-photo.pdf b/iOSClient/Images.xcassets/folderAutomaticUpload.imageset/folder-photo.pdf new file mode 100644 index 0000000000..f646199438 Binary files /dev/null and b/iOSClient/Images.xcassets/folderAutomaticUpload.imageset/folder-photo.pdf differ diff --git a/iOSClient/Images.xcassets/folderAutomaticUpload.imageset/folder_photo.svg b/iOSClient/Images.xcassets/folderAutomaticUpload.imageset/folder_photo.svg deleted file mode 100644 index f46eb94656..0000000000 --- a/iOSClient/Images.xcassets/folderAutomaticUpload.imageset/folder_photo.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/iOSClient/Images.xcassets/folderEncrypted.imageset/Contents.json b/iOSClient/Images.xcassets/folderEncrypted.imageset/Contents.json index d5a0abaa2c..d3a66aded2 100644 --- a/iOSClient/Images.xcassets/folderEncrypted.imageset/Contents.json +++ b/iOSClient/Images.xcassets/folderEncrypted.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "folder_encrypted.svg", + "filename" : "folder-encrypted.pdf", "idiom" : "universal" } ], @@ -10,7 +10,6 @@ "version" : 1 }, "properties" : { - "preserves-vector-representation" : true, - "template-rendering-intent" : "template" + "preserves-vector-representation" : true } } diff --git a/iOSClient/Images.xcassets/folderEncrypted.imageset/folder-encrypted.pdf b/iOSClient/Images.xcassets/folderEncrypted.imageset/folder-encrypted.pdf new file mode 100644 index 0000000000..f2754a18a9 Binary files /dev/null and b/iOSClient/Images.xcassets/folderEncrypted.imageset/folder-encrypted.pdf differ diff --git a/iOSClient/Images.xcassets/folderEncrypted.imageset/folder_encrypted.svg b/iOSClient/Images.xcassets/folderEncrypted.imageset/folder_encrypted.svg deleted file mode 100644 index 4f9e6b487e..0000000000 --- a/iOSClient/Images.xcassets/folderEncrypted.imageset/folder_encrypted.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/iOSClient/Images.xcassets/folder_external.imageset/Contents.json b/iOSClient/Images.xcassets/folder_external.imageset/Contents.json index 741bbee824..63a3af51db 100644 --- a/iOSClient/Images.xcassets/folder_external.imageset/Contents.json +++ b/iOSClient/Images.xcassets/folder_external.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "folder_external.svg", + "filename" : "folder-share.pdf", "idiom" : "universal" } ], @@ -10,7 +10,6 @@ "version" : 1 }, "properties" : { - "preserves-vector-representation" : true, - "template-rendering-intent" : "template" + "preserves-vector-representation" : true } } diff --git a/iOSClient/Images.xcassets/folder_external.imageset/folder-share.pdf b/iOSClient/Images.xcassets/folder_external.imageset/folder-share.pdf new file mode 100644 index 0000000000..4a5832ff32 Binary files /dev/null and b/iOSClient/Images.xcassets/folder_external.imageset/folder-share.pdf differ diff --git a/iOSClient/Images.xcassets/folder_external.imageset/folder_external.svg b/iOSClient/Images.xcassets/folder_external.imageset/folder_external.svg deleted file mode 100644 index c6a0db5b35..0000000000 --- a/iOSClient/Images.xcassets/folder_external.imageset/folder_external.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/iOSClient/Images.xcassets/folder_group.imageset/Contents.json b/iOSClient/Images.xcassets/folder_group.imageset/Contents.json index 2c54bdc970..63a3af51db 100644 --- a/iOSClient/Images.xcassets/folder_group.imageset/Contents.json +++ b/iOSClient/Images.xcassets/folder_group.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "folder_group.svg", + "filename" : "folder-share.pdf", "idiom" : "universal" } ], @@ -10,7 +10,6 @@ "version" : 1 }, "properties" : { - "preserves-vector-representation" : true, - "template-rendering-intent" : "template" + "preserves-vector-representation" : true } } diff --git a/iOSClient/Images.xcassets/folder_group.imageset/folder-share.pdf b/iOSClient/Images.xcassets/folder_group.imageset/folder-share.pdf new file mode 100644 index 0000000000..4a5832ff32 Binary files /dev/null and b/iOSClient/Images.xcassets/folder_group.imageset/folder-share.pdf differ diff --git a/iOSClient/Images.xcassets/folder_group.imageset/folder_group.svg b/iOSClient/Images.xcassets/folder_group.imageset/folder_group.svg deleted file mode 100644 index 960ab84ec1..0000000000 --- a/iOSClient/Images.xcassets/folder_group.imageset/folder_group.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/iOSClient/Images.xcassets/folder_nmcloud.imageset/Contents.json b/iOSClient/Images.xcassets/folder_nmcloud.imageset/Contents.json new file mode 100644 index 0000000000..54635c2f38 --- /dev/null +++ b/iOSClient/Images.xcassets/folder_nmcloud.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "folder_nmcloud.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/folder_nmcloud.imageset/folder_nmcloud.pdf b/iOSClient/Images.xcassets/folder_nmcloud.imageset/folder_nmcloud.pdf new file mode 100644 index 0000000000..b828c52c05 Binary files /dev/null and b/iOSClient/Images.xcassets/folder_nmcloud.imageset/folder_nmcloud.pdf differ diff --git a/iOSClient/Images.xcassets/folder_public.imageset/Contents.json b/iOSClient/Images.xcassets/folder_public.imageset/Contents.json index ce84569fca..63a3af51db 100644 --- a/iOSClient/Images.xcassets/folder_public.imageset/Contents.json +++ b/iOSClient/Images.xcassets/folder_public.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "folder_link.svg", + "filename" : "folder-share.pdf", "idiom" : "universal" } ], @@ -10,7 +10,6 @@ "version" : 1 }, "properties" : { - "preserves-vector-representation" : true, - "template-rendering-intent" : "template" + "preserves-vector-representation" : true } } diff --git a/iOSClient/Images.xcassets/folder_public.imageset/folder-share.pdf b/iOSClient/Images.xcassets/folder_public.imageset/folder-share.pdf new file mode 100644 index 0000000000..4a5832ff32 Binary files /dev/null and b/iOSClient/Images.xcassets/folder_public.imageset/folder-share.pdf differ diff --git a/iOSClient/Images.xcassets/folder_public.imageset/folder_link.svg b/iOSClient/Images.xcassets/folder_public.imageset/folder_link.svg deleted file mode 100644 index 8966f9a61a..0000000000 --- a/iOSClient/Images.xcassets/folder_public.imageset/folder_link.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/iOSClient/Images.xcassets/folder_shared_with_me.imageset/Contents.json b/iOSClient/Images.xcassets/folder_shared_with_me.imageset/Contents.json index 8b5e688724..63a3af51db 100644 --- a/iOSClient/Images.xcassets/folder_shared_with_me.imageset/Contents.json +++ b/iOSClient/Images.xcassets/folder_shared_with_me.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "folder_shared_with_me.svg", + "filename" : "folder-share.pdf", "idiom" : "universal" } ], @@ -10,7 +10,6 @@ "version" : 1 }, "properties" : { - "preserves-vector-representation" : true, - "template-rendering-intent" : "template" + "preserves-vector-representation" : true } } diff --git a/iOSClient/Images.xcassets/folder_shared_with_me.imageset/folder-share.pdf b/iOSClient/Images.xcassets/folder_shared_with_me.imageset/folder-share.pdf new file mode 100644 index 0000000000..4a5832ff32 Binary files /dev/null and b/iOSClient/Images.xcassets/folder_shared_with_me.imageset/folder-share.pdf differ diff --git a/iOSClient/Images.xcassets/folder_shared_with_me.imageset/folder_shared_with_me.svg b/iOSClient/Images.xcassets/folder_shared_with_me.imageset/folder_shared_with_me.svg deleted file mode 100644 index d115211941..0000000000 --- a/iOSClient/Images.xcassets/folder_shared_with_me.imageset/folder_shared_with_me.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/iOSClient/Images.xcassets/foldersOnTop.imageset/Contents.json b/iOSClient/Images.xcassets/foldersOnTop.imageset/Contents.json new file mode 100644 index 0000000000..2f2e54e8c1 --- /dev/null +++ b/iOSClient/Images.xcassets/foldersOnTop.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "foldersOnTop.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "foldersOnTop@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "foldersOnTop@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/foldersOnTop.imageset/foldersOnTop.png b/iOSClient/Images.xcassets/foldersOnTop.imageset/foldersOnTop.png new file mode 100644 index 0000000000..728ecfd3a1 Binary files /dev/null and b/iOSClient/Images.xcassets/foldersOnTop.imageset/foldersOnTop.png differ diff --git a/iOSClient/Images.xcassets/foldersOnTop.imageset/foldersOnTop@2x.png b/iOSClient/Images.xcassets/foldersOnTop.imageset/foldersOnTop@2x.png new file mode 100644 index 0000000000..8c0bcb63c5 Binary files /dev/null and b/iOSClient/Images.xcassets/foldersOnTop.imageset/foldersOnTop@2x.png differ diff --git a/iOSClient/Images.xcassets/foldersOnTop.imageset/foldersOnTop@3x.png b/iOSClient/Images.xcassets/foldersOnTop.imageset/foldersOnTop@3x.png new file mode 100644 index 0000000000..45f64ca429 Binary files /dev/null and b/iOSClient/Images.xcassets/foldersOnTop.imageset/foldersOnTop@3x.png differ diff --git a/iOSClient/Images.xcassets/form-textbox.imageset/Contents.json b/iOSClient/Images.xcassets/form-textbox.imageset/Contents.json new file mode 100644 index 0000000000..60638382ad --- /dev/null +++ b/iOSClient/Images.xcassets/form-textbox.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "form-textbox.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/form-textbox.imageset/form-textbox.svg b/iOSClient/Images.xcassets/form-textbox.imageset/form-textbox.svg new file mode 100644 index 0000000000..d9f47d4e70 --- /dev/null +++ b/iOSClient/Images.xcassets/form-textbox.imageset/form-textbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/go-to-page.imageset/Contents.json b/iOSClient/Images.xcassets/go-to-page.imageset/Contents.json new file mode 100644 index 0000000000..684d965e60 --- /dev/null +++ b/iOSClient/Images.xcassets/go-to-page.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "go-to-page.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/go-to-page.imageset/go-to-page.pdf b/iOSClient/Images.xcassets/go-to-page.imageset/go-to-page.pdf new file mode 100644 index 0000000000..d9c8811dca Binary files /dev/null and b/iOSClient/Images.xcassets/go-to-page.imageset/go-to-page.pdf differ diff --git a/iOSClient/Images.xcassets/grid.imageset/Contents.json b/iOSClient/Images.xcassets/grid.imageset/Contents.json new file mode 100644 index 0000000000..30a6d892c1 --- /dev/null +++ b/iOSClient/Images.xcassets/grid.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "Untitled.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/iOSClient/Images.xcassets/grid.imageset/Untitled.pdf b/iOSClient/Images.xcassets/grid.imageset/Untitled.pdf new file mode 100644 index 0000000000..432ec04afa Binary files /dev/null and b/iOSClient/Images.xcassets/grid.imageset/Untitled.pdf differ diff --git a/iOSClient/Images.xcassets/home.imageset/Contents.json b/iOSClient/Images.xcassets/home.imageset/Contents.json new file mode 100644 index 0000000000..acdff8855e --- /dev/null +++ b/iOSClient/Images.xcassets/home.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "home.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/home.imageset/home.pdf b/iOSClient/Images.xcassets/home.imageset/home.pdf new file mode 100644 index 0000000000..024221c275 Binary files /dev/null and b/iOSClient/Images.xcassets/home.imageset/home.pdf differ diff --git a/iOSClient/Images.xcassets/icon-calendar.imageset/Contents.json b/iOSClient/Images.xcassets/icon-calendar.imageset/Contents.json new file mode 100644 index 0000000000..830a3079bc --- /dev/null +++ b/iOSClient/Images.xcassets/icon-calendar.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "icons8-calendario.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/icon-calendar.imageset/icons8-calendario.svg b/iOSClient/Images.xcassets/icon-calendar.imageset/icons8-calendario.svg new file mode 100644 index 0000000000..8146bc2cf9 --- /dev/null +++ b/iOSClient/Images.xcassets/icon-calendar.imageset/icons8-calendario.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/icon-confirm.imageset/Contents.json b/iOSClient/Images.xcassets/icon-confirm.imageset/Contents.json new file mode 100644 index 0000000000..f208a73f87 --- /dev/null +++ b/iOSClient/Images.xcassets/icon-confirm.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "icon-confirm.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/icon-confirm.imageset/icon-confirm.svg b/iOSClient/Images.xcassets/icon-confirm.imageset/icon-confirm.svg new file mode 100644 index 0000000000..f9e268e5b3 --- /dev/null +++ b/iOSClient/Images.xcassets/icon-confirm.imageset/icon-confirm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/icon-contacts.imageset/Contents.json b/iOSClient/Images.xcassets/icon-contacts.imageset/Contents.json new file mode 100644 index 0000000000..ca321128d9 --- /dev/null +++ b/iOSClient/Images.xcassets/icon-contacts.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "icons8-gruppo-utente-uomo-uomo.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/icon-contacts.imageset/icons8-gruppo-utente-uomo-uomo.svg b/iOSClient/Images.xcassets/icon-contacts.imageset/icons8-gruppo-utente-uomo-uomo.svg new file mode 100644 index 0000000000..927eab2467 --- /dev/null +++ b/iOSClient/Images.xcassets/icon-contacts.imageset/icons8-gruppo-utente-uomo-uomo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/icon-deck.imageset/Contents.json b/iOSClient/Images.xcassets/icon-deck.imageset/Contents.json new file mode 100644 index 0000000000..90df8ba400 --- /dev/null +++ b/iOSClient/Images.xcassets/icon-deck.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "deck.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/icon-deck.imageset/deck.svg b/iOSClient/Images.xcassets/icon-deck.imageset/deck.svg new file mode 100644 index 0000000000..0e36f77afc --- /dev/null +++ b/iOSClient/Images.xcassets/icon-deck.imageset/deck.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/icon-mail.imageset/Contents.json b/iOSClient/Images.xcassets/icon-mail.imageset/Contents.json new file mode 100644 index 0000000000..f08f7eaae4 --- /dev/null +++ b/iOSClient/Images.xcassets/icon-mail.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "icons8-nuovo-messaggio.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/icon-mail.imageset/icons8-nuovo-messaggio.svg b/iOSClient/Images.xcassets/icon-mail.imageset/icons8-nuovo-messaggio.svg new file mode 100644 index 0000000000..8518704a8a --- /dev/null +++ b/iOSClient/Images.xcassets/icon-mail.imageset/icons8-nuovo-messaggio.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/icon-pages.imageset/Contents.json b/iOSClient/Images.xcassets/icon-pages.imageset/Contents.json new file mode 100644 index 0000000000..fe86cc0dc3 --- /dev/null +++ b/iOSClient/Images.xcassets/icon-pages.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "icon-pages.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/icon-pages.imageset/icon-pages.svg b/iOSClient/Images.xcassets/icon-pages.imageset/icon-pages.svg new file mode 100644 index 0000000000..67730faf16 --- /dev/null +++ b/iOSClient/Images.xcassets/icon-pages.imageset/icon-pages.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/icon-talk.imageset/Contents.json b/iOSClient/Images.xcassets/icon-talk.imageset/Contents.json new file mode 100644 index 0000000000..f0dc62157f --- /dev/null +++ b/iOSClient/Images.xcassets/icon-talk.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "app-dark.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/talk-template.imageset/app.svg b/iOSClient/Images.xcassets/icon-talk.imageset/app-dark.svg similarity index 92% rename from iOSClient/Images.xcassets/talk-template.imageset/app.svg rename to iOSClient/Images.xcassets/icon-talk.imageset/app-dark.svg index 024e8ca294..3e133d0a17 100644 --- a/iOSClient/Images.xcassets/talk-template.imageset/app.svg +++ b/iOSClient/Images.xcassets/icon-talk.imageset/app-dark.svg @@ -1 +1 @@ - + diff --git a/iOSClient/Images.xcassets/iconError.imageset/Contents.json b/iOSClient/Images.xcassets/iconError.imageset/Contents.json index edd808cf53..6e53abd5b4 100644 --- a/iOSClient/Images.xcassets/iconError.imageset/Contents.json +++ b/iOSClient/Images.xcassets/iconError.imageset/Contents.json @@ -1,8 +1,17 @@ { "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, { "filename" : "iconError@2x.png", - "idiom" : "universal" + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" } ], "info" : { diff --git a/iOSClient/Images.xcassets/iconInfo.imageset/Contents.json b/iOSClient/Images.xcassets/iconInfo.imageset/Contents.json index 43617286e3..dbc8ea0ff7 100644 --- a/iOSClient/Images.xcassets/iconInfo.imageset/Contents.json +++ b/iOSClient/Images.xcassets/iconInfo.imageset/Contents.json @@ -1,8 +1,17 @@ { "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, { "filename" : "iconInfo@2x.png", - "idiom" : "universal" + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" } ], "info" : { diff --git a/iOSClient/Images.xcassets/iconSuccess.imageset/Contents.json b/iOSClient/Images.xcassets/iconSuccess.imageset/Contents.json index 4fe638ca8f..f705d52525 100644 --- a/iOSClient/Images.xcassets/iconSuccess.imageset/Contents.json +++ b/iOSClient/Images.xcassets/iconSuccess.imageset/Contents.json @@ -1,8 +1,17 @@ { "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, { "filename" : "iconSuccess@2x.png", - "idiom" : "universal" + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" } ], "info" : { diff --git a/iOSClient/Images.xcassets/info.imageset/Contents.json b/iOSClient/Images.xcassets/info.imageset/Contents.json new file mode 100644 index 0000000000..ba9ee6e434 --- /dev/null +++ b/iOSClient/Images.xcassets/info.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Unknown.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/info.imageset/Unknown.svg b/iOSClient/Images.xcassets/info.imageset/Unknown.svg new file mode 100644 index 0000000000..7757cbd0fd --- /dev/null +++ b/iOSClient/Images.xcassets/info.imageset/Unknown.svg @@ -0,0 +1 @@ + diff --git a/iOSClient/Images.xcassets/local.imageset/Contents.json b/iOSClient/Images.xcassets/local.imageset/Contents.json new file mode 100644 index 0000000000..5ffe3a6eed --- /dev/null +++ b/iOSClient/Images.xcassets/local.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "local.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "local@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "local@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/local.imageset/local.png b/iOSClient/Images.xcassets/local.imageset/local.png new file mode 100644 index 0000000000..7002ef11a0 Binary files /dev/null and b/iOSClient/Images.xcassets/local.imageset/local.png differ diff --git a/iOSClient/Images.xcassets/local.imageset/local@2x.png b/iOSClient/Images.xcassets/local.imageset/local@2x.png new file mode 100644 index 0000000000..c216a43f84 Binary files /dev/null and b/iOSClient/Images.xcassets/local.imageset/local@2x.png differ diff --git a/iOSClient/Images.xcassets/local.imageset/local@3x.png b/iOSClient/Images.xcassets/local.imageset/local@3x.png new file mode 100644 index 0000000000..744db900e2 Binary files /dev/null and b/iOSClient/Images.xcassets/local.imageset/local@3x.png differ diff --git a/iOSClient/Images.xcassets/lockNew.imageset/Contents.json b/iOSClient/Images.xcassets/lockNew.imageset/Contents.json new file mode 100644 index 0000000000..f03e824fde --- /dev/null +++ b/iOSClient/Images.xcassets/lockNew.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "lock.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "lock@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "lock@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/lockNew.imageset/lock.png b/iOSClient/Images.xcassets/lockNew.imageset/lock.png new file mode 100644 index 0000000000..32536732f6 Binary files /dev/null and b/iOSClient/Images.xcassets/lockNew.imageset/lock.png differ diff --git a/iOSClient/Images.xcassets/lockNew.imageset/lock@2x.png b/iOSClient/Images.xcassets/lockNew.imageset/lock@2x.png new file mode 100644 index 0000000000..794bdfc94b Binary files /dev/null and b/iOSClient/Images.xcassets/lockNew.imageset/lock@2x.png differ diff --git a/iOSClient/Images.xcassets/lockNew.imageset/lock@3x.png b/iOSClient/Images.xcassets/lockNew.imageset/lock@3x.png new file mode 100644 index 0000000000..985b53470e Binary files /dev/null and b/iOSClient/Images.xcassets/lockNew.imageset/lock@3x.png differ diff --git a/iOSClient/Images.xcassets/log.imageset/Contents.json b/iOSClient/Images.xcassets/log.imageset/Contents.json new file mode 100644 index 0000000000..6ed94a9c3e --- /dev/null +++ b/iOSClient/Images.xcassets/log.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "log.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/log.imageset/log.pdf b/iOSClient/Images.xcassets/log.imageset/log.pdf new file mode 100644 index 0000000000..4bd5c5c302 Binary files /dev/null and b/iOSClient/Images.xcassets/log.imageset/log.pdf differ diff --git a/iOSClient/Images.xcassets/loginPassword.imageset/Contents.json b/iOSClient/Images.xcassets/loginPassword.imageset/Contents.json new file mode 100644 index 0000000000..a417091099 --- /dev/null +++ b/iOSClient/Images.xcassets/loginPassword.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "passwordNextcloud.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "passwordNextcloud@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "passwordNextcloud@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/loginPassword.imageset/passwordNextcloud.png b/iOSClient/Images.xcassets/loginPassword.imageset/passwordNextcloud.png new file mode 100644 index 0000000000..cd3f50839c Binary files /dev/null and b/iOSClient/Images.xcassets/loginPassword.imageset/passwordNextcloud.png differ diff --git a/iOSClient/Images.xcassets/loginPassword.imageset/passwordNextcloud@2x.png b/iOSClient/Images.xcassets/loginPassword.imageset/passwordNextcloud@2x.png new file mode 100644 index 0000000000..5c9ab644cd Binary files /dev/null and b/iOSClient/Images.xcassets/loginPassword.imageset/passwordNextcloud@2x.png differ diff --git a/iOSClient/Images.xcassets/loginPassword.imageset/passwordNextcloud@3x.png b/iOSClient/Images.xcassets/loginPassword.imageset/passwordNextcloud@3x.png new file mode 100644 index 0000000000..4a9d396894 Binary files /dev/null and b/iOSClient/Images.xcassets/loginPassword.imageset/passwordNextcloud@3x.png differ diff --git a/iOSClient/Images.xcassets/loginURL.imageset/Contents.json b/iOSClient/Images.xcassets/loginURL.imageset/Contents.json new file mode 100644 index 0000000000..6de00731ba --- /dev/null +++ b/iOSClient/Images.xcassets/loginURL.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "baseurlNextcloud.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "baseurlNextcloud@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "baseurlNextcloud@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/loginURL.imageset/baseurlNextcloud.png b/iOSClient/Images.xcassets/loginURL.imageset/baseurlNextcloud.png new file mode 100644 index 0000000000..d76926e7d6 Binary files /dev/null and b/iOSClient/Images.xcassets/loginURL.imageset/baseurlNextcloud.png differ diff --git a/iOSClient/Images.xcassets/loginURL.imageset/baseurlNextcloud@2x.png b/iOSClient/Images.xcassets/loginURL.imageset/baseurlNextcloud@2x.png new file mode 100644 index 0000000000..9c5853d14d Binary files /dev/null and b/iOSClient/Images.xcassets/loginURL.imageset/baseurlNextcloud@2x.png differ diff --git a/iOSClient/Images.xcassets/loginURL.imageset/baseurlNextcloud@3x.png b/iOSClient/Images.xcassets/loginURL.imageset/baseurlNextcloud@3x.png new file mode 100644 index 0000000000..8450538e3d Binary files /dev/null and b/iOSClient/Images.xcassets/loginURL.imageset/baseurlNextcloud@3x.png differ diff --git a/iOSClient/Images.xcassets/loginUser.imageset/Contents.json b/iOSClient/Images.xcassets/loginUser.imageset/Contents.json new file mode 100644 index 0000000000..9f0cdbcee5 --- /dev/null +++ b/iOSClient/Images.xcassets/loginUser.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "userNextcloud.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "userNextcloud@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "userNextcloud@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/loginUser.imageset/userNextcloud.png b/iOSClient/Images.xcassets/loginUser.imageset/userNextcloud.png new file mode 100644 index 0000000000..95a6baaef1 Binary files /dev/null and b/iOSClient/Images.xcassets/loginUser.imageset/userNextcloud.png differ diff --git a/iOSClient/Images.xcassets/loginUser.imageset/userNextcloud@2x.png b/iOSClient/Images.xcassets/loginUser.imageset/userNextcloud@2x.png new file mode 100644 index 0000000000..51bd35db1c Binary files /dev/null and b/iOSClient/Images.xcassets/loginUser.imageset/userNextcloud@2x.png differ diff --git a/iOSClient/Images.xcassets/loginUser.imageset/userNextcloud@3x.png b/iOSClient/Images.xcassets/loginUser.imageset/userNextcloud@3x.png new file mode 100644 index 0000000000..fd54f635e6 Binary files /dev/null and b/iOSClient/Images.xcassets/loginUser.imageset/userNextcloud@3x.png differ diff --git a/iOSClient/Images.xcassets/logoPng.imageset/Contents.json b/iOSClient/Images.xcassets/logoPng.imageset/Contents.json new file mode 100644 index 0000000000..43967f1e4a --- /dev/null +++ b/iOSClient/Images.xcassets/logoPng.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "logoPng 1.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/logoPng.imageset/logoPng 1.png b/iOSClient/Images.xcassets/logoPng.imageset/logoPng 1.png new file mode 100644 index 0000000000..a0402be0f4 Binary files /dev/null and b/iOSClient/Images.xcassets/logoPng.imageset/logoPng 1.png differ diff --git a/iOSClient/Images.xcassets/media.imageset/tabBarMedia.pdf b/iOSClient/Images.xcassets/media.imageset/tabBarMedia.pdf index 515ca27a10..57ab2633a8 100644 Binary files a/iOSClient/Images.xcassets/media.imageset/tabBarMedia.pdf and b/iOSClient/Images.xcassets/media.imageset/tabBarMedia.pdf differ diff --git a/iOSClient/Images.xcassets/mediaPlay.imageset/Contents.json b/iOSClient/Images.xcassets/mediaPlay.imageset/Contents.json new file mode 100644 index 0000000000..db15d73769 --- /dev/null +++ b/iOSClient/Images.xcassets/mediaPlay.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "play.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/mediaPlay.imageset/play.png b/iOSClient/Images.xcassets/mediaPlay.imageset/play.png new file mode 100644 index 0000000000..9dfae947ea Binary files /dev/null and b/iOSClient/Images.xcassets/mediaPlay.imageset/play.png differ diff --git a/iOSClient/Images.xcassets/mediaSelected.imageset/Contents.json b/iOSClient/Images.xcassets/mediaSelected.imageset/Contents.json new file mode 100644 index 0000000000..63e74b9485 --- /dev/null +++ b/iOSClient/Images.xcassets/mediaSelected.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "mediaSelected.pdf", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/mediaSelected.imageset/mediaSelected.pdf b/iOSClient/Images.xcassets/mediaSelected.imageset/mediaSelected.pdf new file mode 100644 index 0000000000..f75f63eb82 Binary files /dev/null and b/iOSClient/Images.xcassets/mediaSelected.imageset/mediaSelected.pdf differ diff --git a/iOSClient/Images.xcassets/menuLogoUser.imageset/Contents.json b/iOSClient/Images.xcassets/menuLogoUser.imageset/Contents.json new file mode 100644 index 0000000000..02f557bf47 --- /dev/null +++ b/iOSClient/Images.xcassets/menuLogoUser.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "menuLogoUser.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "menuLogoUser@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "menuLogoUser@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/menuLogoUser.imageset/menuLogoUser.png b/iOSClient/Images.xcassets/menuLogoUser.imageset/menuLogoUser.png new file mode 100644 index 0000000000..1d1ca01288 Binary files /dev/null and b/iOSClient/Images.xcassets/menuLogoUser.imageset/menuLogoUser.png differ diff --git a/iOSClient/Images.xcassets/menuLogoUser.imageset/menuLogoUser@2x.png b/iOSClient/Images.xcassets/menuLogoUser.imageset/menuLogoUser@2x.png new file mode 100644 index 0000000000..7dbcfa2767 Binary files /dev/null and b/iOSClient/Images.xcassets/menuLogoUser.imageset/menuLogoUser@2x.png differ diff --git a/iOSClient/Images.xcassets/menuLogoUser.imageset/menuLogoUser@3x.png b/iOSClient/Images.xcassets/menuLogoUser.imageset/menuLogoUser@3x.png new file mode 100644 index 0000000000..40ed64e0ab Binary files /dev/null and b/iOSClient/Images.xcassets/menuLogoUser.imageset/menuLogoUser@3x.png differ diff --git a/iOSClient/Images.xcassets/microphoneMenu.imageset/Contents.json b/iOSClient/Images.xcassets/microphoneMenu.imageset/Contents.json new file mode 100644 index 0000000000..36303602eb --- /dev/null +++ b/iOSClient/Images.xcassets/microphoneMenu.imageset/Contents.json @@ -0,0 +1,52 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "microphoneMenu.pdf", + "idiom" : "universal", + "scale" : "2x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "default copy@500w.pdf", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/microphoneMenu.imageset/default copy@500w.pdf b/iOSClient/Images.xcassets/microphoneMenu.imageset/default copy@500w.pdf new file mode 100644 index 0000000000..2be53f66ca Binary files /dev/null and b/iOSClient/Images.xcassets/microphoneMenu.imageset/default copy@500w.pdf differ diff --git a/iOSClient/Images.xcassets/microphoneMenu.imageset/microphoneMenu.pdf b/iOSClient/Images.xcassets/microphoneMenu.imageset/microphoneMenu.pdf new file mode 100644 index 0000000000..9bfed5ddc2 Binary files /dev/null and b/iOSClient/Images.xcassets/microphoneMenu.imageset/microphoneMenu.pdf differ diff --git a/iOSClient/Images.xcassets/more.imageset/Contents.json b/iOSClient/Images.xcassets/more.imageset/Contents.json new file mode 100644 index 0000000000..0fead39b1f --- /dev/null +++ b/iOSClient/Images.xcassets/more.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "default@500w.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/more.imageset/default@500w.pdf b/iOSClient/Images.xcassets/more.imageset/default@500w.pdf new file mode 100644 index 0000000000..414e585364 Binary files /dev/null and b/iOSClient/Images.xcassets/more.imageset/default@500w.pdf differ diff --git a/iOSClient/Images.xcassets/moreBig.imageset/Contents.json b/iOSClient/Images.xcassets/moreBig.imageset/Contents.json new file mode 100644 index 0000000000..2bd4f9dce3 --- /dev/null +++ b/iOSClient/Images.xcassets/moreBig.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "moreBig.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "moreBig@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "moreBig@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/moreBig.imageset/moreBig.png b/iOSClient/Images.xcassets/moreBig.imageset/moreBig.png new file mode 100644 index 0000000000..a63fd72eaf Binary files /dev/null and b/iOSClient/Images.xcassets/moreBig.imageset/moreBig.png differ diff --git a/iOSClient/Images.xcassets/moreBig.imageset/moreBig@2x.png b/iOSClient/Images.xcassets/moreBig.imageset/moreBig@2x.png new file mode 100644 index 0000000000..4dda5c1668 Binary files /dev/null and b/iOSClient/Images.xcassets/moreBig.imageset/moreBig@2x.png differ diff --git a/iOSClient/Images.xcassets/moreBig.imageset/moreBig@3x.png b/iOSClient/Images.xcassets/moreBig.imageset/moreBig@3x.png new file mode 100644 index 0000000000..1652e91f3b Binary files /dev/null and b/iOSClient/Images.xcassets/moreBig.imageset/moreBig@3x.png differ diff --git a/iOSClient/Images.xcassets/moreEmpty.imageset/Contents.json b/iOSClient/Images.xcassets/moreEmpty.imageset/Contents.json new file mode 100644 index 0000000000..608e3161e0 --- /dev/null +++ b/iOSClient/Images.xcassets/moreEmpty.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "moreEmpty.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "moreEmpty@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "moreEmpty@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/moreEmpty.imageset/moreEmpty.png b/iOSClient/Images.xcassets/moreEmpty.imageset/moreEmpty.png new file mode 100644 index 0000000000..f06ecbf37c Binary files /dev/null and b/iOSClient/Images.xcassets/moreEmpty.imageset/moreEmpty.png differ diff --git a/iOSClient/Images.xcassets/moreEmpty.imageset/moreEmpty@2x.png b/iOSClient/Images.xcassets/moreEmpty.imageset/moreEmpty@2x.png new file mode 100644 index 0000000000..b004371d02 Binary files /dev/null and b/iOSClient/Images.xcassets/moreEmpty.imageset/moreEmpty@2x.png differ diff --git a/iOSClient/Images.xcassets/moreEmpty.imageset/moreEmpty@3x.png b/iOSClient/Images.xcassets/moreEmpty.imageset/moreEmpty@3x.png new file mode 100644 index 0000000000..9ff7153798 Binary files /dev/null and b/iOSClient/Images.xcassets/moreEmpty.imageset/moreEmpty@3x.png differ diff --git a/iOSClient/Images.xcassets/move.imageset/Contents.json b/iOSClient/Images.xcassets/move.imageset/Contents.json new file mode 100644 index 0000000000..e31439f23a --- /dev/null +++ b/iOSClient/Images.xcassets/move.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "actionSheetMove.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "actionSheetMove@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "actionSheetMove@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/move.imageset/actionSheetMove.png b/iOSClient/Images.xcassets/move.imageset/actionSheetMove.png new file mode 100644 index 0000000000..1bd5ec35e9 Binary files /dev/null and b/iOSClient/Images.xcassets/move.imageset/actionSheetMove.png differ diff --git a/iOSClient/Images.xcassets/move.imageset/actionSheetMove@2x.png b/iOSClient/Images.xcassets/move.imageset/actionSheetMove@2x.png new file mode 100644 index 0000000000..d25c3fd724 Binary files /dev/null and b/iOSClient/Images.xcassets/move.imageset/actionSheetMove@2x.png differ diff --git a/iOSClient/Images.xcassets/move.imageset/actionSheetMove@3x.png b/iOSClient/Images.xcassets/move.imageset/actionSheetMove@3x.png new file mode 100644 index 0000000000..afcc5b64fa Binary files /dev/null and b/iOSClient/Images.xcassets/move.imageset/actionSheetMove@3x.png differ diff --git a/iOSClient/Images.xcassets/navigationMore.imageset/Contents.json b/iOSClient/Images.xcassets/navigationMore.imageset/Contents.json new file mode 100644 index 0000000000..fa2d81caaa --- /dev/null +++ b/iOSClient/Images.xcassets/navigationMore.imageset/Contents.json @@ -0,0 +1,25 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "more-round.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/iOSClient/Images.xcassets/navigationMore.imageset/more-round.png b/iOSClient/Images.xcassets/navigationMore.imageset/more-round.png new file mode 100644 index 0000000000..4440d0415f Binary files /dev/null and b/iOSClient/Images.xcassets/navigationMore.imageset/more-round.png differ diff --git a/iOSClient/Images.xcassets/navigationSort.imageset/Contents.json b/iOSClient/Images.xcassets/navigationSort.imageset/Contents.json new file mode 100644 index 0000000000..30a6d892c1 --- /dev/null +++ b/iOSClient/Images.xcassets/navigationSort.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "Untitled.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/iOSClient/Images.xcassets/navigationSort.imageset/Untitled.pdf b/iOSClient/Images.xcassets/navigationSort.imageset/Untitled.pdf new file mode 100644 index 0000000000..7d1fa8c47c Binary files /dev/null and b/iOSClient/Images.xcassets/navigationSort.imageset/Untitled.pdf differ diff --git a/iOSClient/Images.xcassets/networkInProgress.imageset/Contents.json b/iOSClient/Images.xcassets/networkInProgress.imageset/Contents.json new file mode 100644 index 0000000000..5cd67041ca --- /dev/null +++ b/iOSClient/Images.xcassets/networkInProgress.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "networkInProgress.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/networkInProgress.imageset/networkInProgress.pdf b/iOSClient/Images.xcassets/networkInProgress.imageset/networkInProgress.pdf new file mode 100644 index 0000000000..5441ff5fd7 Binary files /dev/null and b/iOSClient/Images.xcassets/networkInProgress.imageset/networkInProgress.pdf differ diff --git a/iOSClient/Images.xcassets/noPreview.imageset/Contents.json b/iOSClient/Images.xcassets/noPreview.imageset/Contents.json new file mode 100644 index 0000000000..05a0360065 --- /dev/null +++ b/iOSClient/Images.xcassets/noPreview.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "noPreview.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/noPreview.imageset/noPreview.pdf b/iOSClient/Images.xcassets/noPreview.imageset/noPreview.pdf new file mode 100644 index 0000000000..321ef3dab5 Binary files /dev/null and b/iOSClient/Images.xcassets/noPreview.imageset/noPreview.pdf differ diff --git a/iOSClient/Images.xcassets/noPreviewAudio.imageset/Contents.json b/iOSClient/Images.xcassets/noPreviewAudio.imageset/Contents.json new file mode 100644 index 0000000000..2854571244 --- /dev/null +++ b/iOSClient/Images.xcassets/noPreviewAudio.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "noPreviewAudio.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/noPreviewAudio.imageset/noPreviewAudio.pdf b/iOSClient/Images.xcassets/noPreviewAudio.imageset/noPreviewAudio.pdf new file mode 100644 index 0000000000..4e5cb56cba Binary files /dev/null and b/iOSClient/Images.xcassets/noPreviewAudio.imageset/noPreviewAudio.pdf differ diff --git a/iOSClient/Images.xcassets/noPreviewVideo.imageset/Contents.json b/iOSClient/Images.xcassets/noPreviewVideo.imageset/Contents.json new file mode 100644 index 0000000000..c3002c4769 --- /dev/null +++ b/iOSClient/Images.xcassets/noPreviewVideo.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "noPreviewVideo.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/noPreviewVideo.imageset/noPreviewVideo.pdf b/iOSClient/Images.xcassets/noPreviewVideo.imageset/noPreviewVideo.pdf new file mode 100644 index 0000000000..f710e31f4d Binary files /dev/null and b/iOSClient/Images.xcassets/noPreviewVideo.imageset/noPreviewVideo.pdf differ diff --git a/iOSClient/Images.xcassets/nocamera.imageset/Contents.json b/iOSClient/Images.xcassets/nocamera.imageset/Contents.json new file mode 100644 index 0000000000..78fb1072de --- /dev/null +++ b/iOSClient/Images.xcassets/nocamera.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "default@500w.pdf", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/nocamera.imageset/default@500w.pdf b/iOSClient/Images.xcassets/nocamera.imageset/default@500w.pdf new file mode 100644 index 0000000000..429fd3fa2c Binary files /dev/null and b/iOSClient/Images.xcassets/nocamera.imageset/default@500w.pdf differ diff --git a/iOSClient/Images.xcassets/nonetwork.imageset/Contents.json b/iOSClient/Images.xcassets/nonetwork.imageset/Contents.json new file mode 100644 index 0000000000..34ae16431f --- /dev/null +++ b/iOSClient/Images.xcassets/nonetwork.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "nonetwork.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/nonetwork.imageset/nonetwork.pdf b/iOSClient/Images.xcassets/nonetwork.imageset/nonetwork.pdf new file mode 100644 index 0000000000..777d945c77 Binary files /dev/null and b/iOSClient/Images.xcassets/nonetwork.imageset/nonetwork.pdf differ diff --git a/iOSClient/Images.xcassets/notaMusic.imageset/Contents.json b/iOSClient/Images.xcassets/notaMusic.imageset/Contents.json new file mode 100644 index 0000000000..857154c7de --- /dev/null +++ b/iOSClient/Images.xcassets/notaMusic.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "notaMusic.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "notaMusic@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "notaMusic@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/notaMusic.imageset/notaMusic.png b/iOSClient/Images.xcassets/notaMusic.imageset/notaMusic.png new file mode 100644 index 0000000000..1cd41c8713 Binary files /dev/null and b/iOSClient/Images.xcassets/notaMusic.imageset/notaMusic.png differ diff --git a/iOSClient/Images.xcassets/notaMusic.imageset/notaMusic@2x.png b/iOSClient/Images.xcassets/notaMusic.imageset/notaMusic@2x.png new file mode 100644 index 0000000000..aed44f6548 Binary files /dev/null and b/iOSClient/Images.xcassets/notaMusic.imageset/notaMusic@2x.png differ diff --git a/iOSClient/Images.xcassets/notaMusic.imageset/notaMusic@3x.png b/iOSClient/Images.xcassets/notaMusic.imageset/notaMusic@3x.png new file mode 100644 index 0000000000..bd918083c6 Binary files /dev/null and b/iOSClient/Images.xcassets/notaMusic.imageset/notaMusic@3x.png differ diff --git a/iOSClient/Images.xcassets/notification.imageset/Contents.json b/iOSClient/Images.xcassets/notification.imageset/Contents.json new file mode 100644 index 0000000000..da621b2a42 --- /dev/null +++ b/iOSClient/Images.xcassets/notification.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "bell.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/notification.imageset/bell.pdf b/iOSClient/Images.xcassets/notification.imageset/bell.pdf new file mode 100644 index 0000000000..a98f3182ab Binary files /dev/null and b/iOSClient/Images.xcassets/notification.imageset/bell.pdf differ diff --git a/iOSClient/Images.xcassets/offOutlineAudio.imageset/Contents.json b/iOSClient/Images.xcassets/offOutlineAudio.imageset/Contents.json new file mode 100644 index 0000000000..a3f76c948d --- /dev/null +++ b/iOSClient/Images.xcassets/offOutlineAudio.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Untitled.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/offOutlineAudio.imageset/Untitled.pdf b/iOSClient/Images.xcassets/offOutlineAudio.imageset/Untitled.pdf new file mode 100644 index 0000000000..bef40d5022 Binary files /dev/null and b/iOSClient/Images.xcassets/offOutlineAudio.imageset/Untitled.pdf differ diff --git a/iOSClient/Images.xcassets/offOutlineImage.imageset/Contents.json b/iOSClient/Images.xcassets/offOutlineImage.imageset/Contents.json new file mode 100644 index 0000000000..90bb416360 --- /dev/null +++ b/iOSClient/Images.xcassets/offOutlineImage.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "image.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/offOutlineImage.imageset/image.pdf b/iOSClient/Images.xcassets/offOutlineImage.imageset/image.pdf new file mode 100644 index 0000000000..e46da2947e Binary files /dev/null and b/iOSClient/Images.xcassets/offOutlineImage.imageset/image.pdf differ diff --git a/iOSClient/Images.xcassets/offOutlineVideo.imageset/Contents.json b/iOSClient/Images.xcassets/offOutlineVideo.imageset/Contents.json new file mode 100644 index 0000000000..a3f76c948d --- /dev/null +++ b/iOSClient/Images.xcassets/offOutlineVideo.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Untitled.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/offOutlineVideo.imageset/Untitled.pdf b/iOSClient/Images.xcassets/offOutlineVideo.imageset/Untitled.pdf new file mode 100644 index 0000000000..6174b23e81 Binary files /dev/null and b/iOSClient/Images.xcassets/offOutlineVideo.imageset/Untitled.pdf differ diff --git a/iOSClient/Images.xcassets/offlineFlag.imageset/Contents.json b/iOSClient/Images.xcassets/offlineFlag.imageset/Contents.json new file mode 100644 index 0000000000..a66d8bacff --- /dev/null +++ b/iOSClient/Images.xcassets/offlineFlag.imageset/Contents.json @@ -0,0 +1,59 @@ +{ + "images" : [ + { + "filename" : "offlineFlagD.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "offlineFlag 1.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "offlineFlagD@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "offlineFlag@2x 1.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "offlineFlagD@3x.png", + "idiom" : "universal", + "scale" : "3x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "offlineFlag@3x 1.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/offlineFlag.imageset/offlineFlag 1.png b/iOSClient/Images.xcassets/offlineFlag.imageset/offlineFlag 1.png new file mode 100644 index 0000000000..92508fbf3f Binary files /dev/null and b/iOSClient/Images.xcassets/offlineFlag.imageset/offlineFlag 1.png differ diff --git a/iOSClient/Images.xcassets/offlineFlag.imageset/offlineFlag@2x 1.png b/iOSClient/Images.xcassets/offlineFlag.imageset/offlineFlag@2x 1.png new file mode 100644 index 0000000000..3bc47bb8f2 Binary files /dev/null and b/iOSClient/Images.xcassets/offlineFlag.imageset/offlineFlag@2x 1.png differ diff --git a/iOSClient/Images.xcassets/offlineFlag.imageset/offlineFlag@3x 1.png b/iOSClient/Images.xcassets/offlineFlag.imageset/offlineFlag@3x 1.png new file mode 100644 index 0000000000..306d0499ec Binary files /dev/null and b/iOSClient/Images.xcassets/offlineFlag.imageset/offlineFlag@3x 1.png differ diff --git a/iOSClient/Images.xcassets/offlineFlag.imageset/offlineFlagD.png b/iOSClient/Images.xcassets/offlineFlag.imageset/offlineFlagD.png new file mode 100644 index 0000000000..760a94c27f Binary files /dev/null and b/iOSClient/Images.xcassets/offlineFlag.imageset/offlineFlagD.png differ diff --git a/iOSClient/Images.xcassets/offlineFlag.imageset/offlineFlagD@2x.png b/iOSClient/Images.xcassets/offlineFlag.imageset/offlineFlagD@2x.png new file mode 100644 index 0000000000..ea83af70d5 Binary files /dev/null and b/iOSClient/Images.xcassets/offlineFlag.imageset/offlineFlagD@2x.png differ diff --git a/iOSClient/Images.xcassets/offlineFlag.imageset/offlineFlagD@3x.png b/iOSClient/Images.xcassets/offlineFlag.imageset/offlineFlagD@3x.png new file mode 100644 index 0000000000..1adf1bebdd Binary files /dev/null and b/iOSClient/Images.xcassets/offlineFlag.imageset/offlineFlagD@3x.png differ diff --git a/iOSClient/Images.xcassets/offlineMenu.imageset/Contents.json b/iOSClient/Images.xcassets/offlineMenu.imageset/Contents.json new file mode 100644 index 0000000000..8f3e754211 --- /dev/null +++ b/iOSClient/Images.xcassets/offlineMenu.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "default@500w.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/offlineMenu.imageset/default@500w.pdf b/iOSClient/Images.xcassets/offlineMenu.imageset/default@500w.pdf new file mode 100644 index 0000000000..8655164ae6 Binary files /dev/null and b/iOSClient/Images.xcassets/offlineMenu.imageset/default@500w.pdf differ diff --git a/iOSClient/Images.xcassets/open_file.imageset/Contents.json b/iOSClient/Images.xcassets/open_file.imageset/Contents.json new file mode 100644 index 0000000000..1712417fdc --- /dev/null +++ b/iOSClient/Images.xcassets/open_file.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "openFile.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "openFile@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "openFile@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/open_file.imageset/openFile.png b/iOSClient/Images.xcassets/open_file.imageset/openFile.png new file mode 100644 index 0000000000..0f76ce12bc Binary files /dev/null and b/iOSClient/Images.xcassets/open_file.imageset/openFile.png differ diff --git a/iOSClient/Images.xcassets/open_file.imageset/openFile@2x.png b/iOSClient/Images.xcassets/open_file.imageset/openFile@2x.png new file mode 100644 index 0000000000..2f4e286f6f Binary files /dev/null and b/iOSClient/Images.xcassets/open_file.imageset/openFile@2x.png differ diff --git a/iOSClient/Images.xcassets/open_file.imageset/openFile@3x.png b/iOSClient/Images.xcassets/open_file.imageset/openFile@3x.png new file mode 100644 index 0000000000..5a0f7be299 Binary files /dev/null and b/iOSClient/Images.xcassets/open_file.imageset/openFile@3x.png differ diff --git a/iOSClient/Images.xcassets/palette.imageset/Contents.json b/iOSClient/Images.xcassets/palette.imageset/Contents.json new file mode 100644 index 0000000000..6601935c6f --- /dev/null +++ b/iOSClient/Images.xcassets/palette.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "palette.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/palette.imageset/palette.svg b/iOSClient/Images.xcassets/palette.imageset/palette.svg new file mode 100644 index 0000000000..6ded5cbb6c --- /dev/null +++ b/iOSClient/Images.xcassets/palette.imageset/palette.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/passcode.imageset/Contents.json b/iOSClient/Images.xcassets/passcode.imageset/Contents.json new file mode 100644 index 0000000000..63ca80e76c --- /dev/null +++ b/iOSClient/Images.xcassets/passcode.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "passcode.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "passcode@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "passcode@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/passcode.imageset/passcode.png b/iOSClient/Images.xcassets/passcode.imageset/passcode.png new file mode 100644 index 0000000000..41a50a2571 Binary files /dev/null and b/iOSClient/Images.xcassets/passcode.imageset/passcode.png differ diff --git a/iOSClient/Images.xcassets/passcode.imageset/passcode@2x.png b/iOSClient/Images.xcassets/passcode.imageset/passcode@2x.png new file mode 100644 index 0000000000..1a7859c3c8 Binary files /dev/null and b/iOSClient/Images.xcassets/passcode.imageset/passcode@2x.png differ diff --git a/iOSClient/Images.xcassets/passcode.imageset/passcode@3x.png b/iOSClient/Images.xcassets/passcode.imageset/passcode@3x.png new file mode 100644 index 0000000000..b83b8f904a Binary files /dev/null and b/iOSClient/Images.xcassets/passcode.imageset/passcode@3x.png differ diff --git a/iOSClient/Images.xcassets/pip.enter.imageset/Contents.json b/iOSClient/Images.xcassets/pip.enter.imageset/Contents.json new file mode 100644 index 0000000000..d737f573c8 --- /dev/null +++ b/iOSClient/Images.xcassets/pip.enter.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "pip.enter.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/pip.enter.imageset/pip.enter.svg b/iOSClient/Images.xcassets/pip.enter.imageset/pip.enter.svg new file mode 100644 index 0000000000..8fa725a8ba --- /dev/null +++ b/iOSClient/Images.xcassets/pip.enter.imageset/pip.enter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/printer.imageset/Contents.json b/iOSClient/Images.xcassets/printer.imageset/Contents.json new file mode 100644 index 0000000000..d92ed2c7e6 --- /dev/null +++ b/iOSClient/Images.xcassets/printer.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "print.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/printer.imageset/print.svg b/iOSClient/Images.xcassets/printer.imageset/print.svg new file mode 100644 index 0000000000..1eac5337a8 --- /dev/null +++ b/iOSClient/Images.xcassets/printer.imageset/print.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/qrcode.imageset/Contents.json b/iOSClient/Images.xcassets/qrcode.imageset/Contents.json new file mode 100644 index 0000000000..3d370c566d --- /dev/null +++ b/iOSClient/Images.xcassets/qrcode.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "qrcode.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/qrcode.imageset/qrcode.pdf b/iOSClient/Images.xcassets/qrcode.imageset/qrcode.pdf new file mode 100644 index 0000000000..d2c7194a64 Binary files /dev/null and b/iOSClient/Images.xcassets/qrcode.imageset/qrcode.pdf differ diff --git a/iOSClient/Images.xcassets/recent.imageset/Contents.json b/iOSClient/Images.xcassets/recent.imageset/Contents.json new file mode 100644 index 0000000000..59b0186b06 --- /dev/null +++ b/iOSClient/Images.xcassets/recent.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "recent.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/recent.imageset/recent.pdf b/iOSClient/Images.xcassets/recent.imageset/recent.pdf new file mode 100644 index 0000000000..496833c975 Binary files /dev/null and b/iOSClient/Images.xcassets/recent.imageset/recent.pdf differ diff --git a/iOSClient/Images.xcassets/rename.imageset/Contents.json b/iOSClient/Images.xcassets/rename.imageset/Contents.json new file mode 100644 index 0000000000..f361ec03e2 --- /dev/null +++ b/iOSClient/Images.xcassets/rename.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "actionSheetRename.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "actionSheetRename@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "actionSheetRename@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/rename.imageset/actionSheetRename.png b/iOSClient/Images.xcassets/rename.imageset/actionSheetRename.png new file mode 100644 index 0000000000..ff3bf49a82 Binary files /dev/null and b/iOSClient/Images.xcassets/rename.imageset/actionSheetRename.png differ diff --git a/iOSClient/Images.xcassets/rename.imageset/actionSheetRename@2x.png b/iOSClient/Images.xcassets/rename.imageset/actionSheetRename@2x.png new file mode 100644 index 0000000000..46415573f0 Binary files /dev/null and b/iOSClient/Images.xcassets/rename.imageset/actionSheetRename@2x.png differ diff --git a/iOSClient/Images.xcassets/rename.imageset/actionSheetRename@3x.png b/iOSClient/Images.xcassets/rename.imageset/actionSheetRename@3x.png new file mode 100644 index 0000000000..27f7dff1cf Binary files /dev/null and b/iOSClient/Images.xcassets/rename.imageset/actionSheetRename@3x.png differ diff --git a/iOSClient/Images.xcassets/restore.imageset/Contents.json b/iOSClient/Images.xcassets/restore.imageset/Contents.json new file mode 100644 index 0000000000..74570520e4 --- /dev/null +++ b/iOSClient/Images.xcassets/restore.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "restore.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "restore@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "restore@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/restore.imageset/restore.png b/iOSClient/Images.xcassets/restore.imageset/restore.png new file mode 100644 index 0000000000..04da83267c Binary files /dev/null and b/iOSClient/Images.xcassets/restore.imageset/restore.png differ diff --git a/iOSClient/Images.xcassets/restore.imageset/restore@2x.png b/iOSClient/Images.xcassets/restore.imageset/restore@2x.png new file mode 100644 index 0000000000..01cbc53d57 Binary files /dev/null and b/iOSClient/Images.xcassets/restore.imageset/restore@2x.png differ diff --git a/iOSClient/Images.xcassets/restore.imageset/restore@3x.png b/iOSClient/Images.xcassets/restore.imageset/restore@3x.png new file mode 100644 index 0000000000..c02e1e8291 Binary files /dev/null and b/iOSClient/Images.xcassets/restore.imageset/restore@3x.png differ diff --git a/iOSClient/Images.xcassets/rightArrow.imageset/Contents.json b/iOSClient/Images.xcassets/rightArrow.imageset/Contents.json new file mode 100644 index 0000000000..87b82f699e --- /dev/null +++ b/iOSClient/Images.xcassets/rightArrow.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "rightArrow.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "rightArrow@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "rightArrow@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/rightArrow.imageset/rightArrow.png b/iOSClient/Images.xcassets/rightArrow.imageset/rightArrow.png new file mode 100644 index 0000000000..dc70ac1d46 Binary files /dev/null and b/iOSClient/Images.xcassets/rightArrow.imageset/rightArrow.png differ diff --git a/iOSClient/Images.xcassets/rightArrow.imageset/rightArrow@2x.png b/iOSClient/Images.xcassets/rightArrow.imageset/rightArrow@2x.png new file mode 100644 index 0000000000..a472f58c1c Binary files /dev/null and b/iOSClient/Images.xcassets/rightArrow.imageset/rightArrow@2x.png differ diff --git a/iOSClient/Images.xcassets/rightArrow.imageset/rightArrow@3x.png b/iOSClient/Images.xcassets/rightArrow.imageset/rightArrow@3x.png new file mode 100644 index 0000000000..38fd1b6bbe Binary files /dev/null and b/iOSClient/Images.xcassets/rightArrow.imageset/rightArrow@3x.png differ diff --git a/iOSClient/Images.xcassets/role.imageset/Contents.json b/iOSClient/Images.xcassets/role.imageset/Contents.json new file mode 100644 index 0000000000..33866e577e --- /dev/null +++ b/iOSClient/Images.xcassets/role.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "role.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/role.imageset/role.pdf b/iOSClient/Images.xcassets/role.imageset/role.pdf new file mode 100644 index 0000000000..9f7dcfb04f Binary files /dev/null and b/iOSClient/Images.xcassets/role.imageset/role.pdf differ diff --git a/iOSClient/Images.xcassets/rotate.imageset/Contents.json b/iOSClient/Images.xcassets/rotate.imageset/Contents.json new file mode 100644 index 0000000000..6ef84edb13 --- /dev/null +++ b/iOSClient/Images.xcassets/rotate.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "rotate.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "rotate@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "rotate@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/rotate.imageset/rotate.png b/iOSClient/Images.xcassets/rotate.imageset/rotate.png new file mode 100644 index 0000000000..05bc26fc89 Binary files /dev/null and b/iOSClient/Images.xcassets/rotate.imageset/rotate.png differ diff --git a/iOSClient/Images.xcassets/rotate.imageset/rotate@2x.png b/iOSClient/Images.xcassets/rotate.imageset/rotate@2x.png new file mode 100644 index 0000000000..0fbf592dd2 Binary files /dev/null and b/iOSClient/Images.xcassets/rotate.imageset/rotate@2x.png differ diff --git a/iOSClient/Images.xcassets/rotate.imageset/rotate@3x.png b/iOSClient/Images.xcassets/rotate.imageset/rotate@3x.png new file mode 100644 index 0000000000..b840562baa Binary files /dev/null and b/iOSClient/Images.xcassets/rotate.imageset/rotate@3x.png differ diff --git a/iOSClient/Images.xcassets/save_files.imageset/Contents.json b/iOSClient/Images.xcassets/save_files.imageset/Contents.json new file mode 100644 index 0000000000..5d67bf067b --- /dev/null +++ b/iOSClient/Images.xcassets/save_files.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "saveSelectedFiles.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "saveSelectedFiles@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "saveSelectedFiles@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/save_files.imageset/saveSelectedFiles.png b/iOSClient/Images.xcassets/save_files.imageset/saveSelectedFiles.png new file mode 100644 index 0000000000..590c922f4e Binary files /dev/null and b/iOSClient/Images.xcassets/save_files.imageset/saveSelectedFiles.png differ diff --git a/iOSClient/Images.xcassets/save_files.imageset/saveSelectedFiles@2x.png b/iOSClient/Images.xcassets/save_files.imageset/saveSelectedFiles@2x.png new file mode 100644 index 0000000000..589eeb56c2 Binary files /dev/null and b/iOSClient/Images.xcassets/save_files.imageset/saveSelectedFiles@2x.png differ diff --git a/iOSClient/Images.xcassets/save_files.imageset/saveSelectedFiles@3x.png b/iOSClient/Images.xcassets/save_files.imageset/saveSelectedFiles@3x.png new file mode 100644 index 0000000000..4d1f750642 Binary files /dev/null and b/iOSClient/Images.xcassets/save_files.imageset/saveSelectedFiles@3x.png differ diff --git a/iOSClient/Images.xcassets/scan.imageset/Contents.json b/iOSClient/Images.xcassets/scan.imageset/Contents.json new file mode 100644 index 0000000000..8776a75678 --- /dev/null +++ b/iOSClient/Images.xcassets/scan.imageset/Contents.json @@ -0,0 +1,25 @@ +{ + "images" : [ + { + "filename" : "default@500w.pdf", + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "default copy@500w.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/scan.imageset/default copy@500w.pdf b/iOSClient/Images.xcassets/scan.imageset/default copy@500w.pdf new file mode 100644 index 0000000000..9731102ea6 Binary files /dev/null and b/iOSClient/Images.xcassets/scan.imageset/default copy@500w.pdf differ diff --git a/iOSClient/Images.xcassets/scan.imageset/default@500w.pdf b/iOSClient/Images.xcassets/scan.imageset/default@500w.pdf new file mode 100644 index 0000000000..118d570d99 Binary files /dev/null and b/iOSClient/Images.xcassets/scan.imageset/default@500w.pdf differ diff --git a/iOSClient/Images.xcassets/search.imageset/Contents.json b/iOSClient/Images.xcassets/search.imageset/Contents.json new file mode 100644 index 0000000000..8a79382902 --- /dev/null +++ b/iOSClient/Images.xcassets/search.imageset/Contents.json @@ -0,0 +1,25 @@ +{ + "images" : [ + { + "filename" : "search.pdf", + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "searchDark.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/iOSClient/Images.xcassets/search.imageset/search.pdf b/iOSClient/Images.xcassets/search.imageset/search.pdf new file mode 100644 index 0000000000..b96af4459e Binary files /dev/null and b/iOSClient/Images.xcassets/search.imageset/search.pdf differ diff --git a/iOSClient/Images.xcassets/search.imageset/searchDark.pdf b/iOSClient/Images.xcassets/search.imageset/searchDark.pdf new file mode 100644 index 0000000000..313042ee07 Binary files /dev/null and b/iOSClient/Images.xcassets/search.imageset/searchDark.pdf differ diff --git a/iOSClient/Images.xcassets/select.imageset/1.pdf b/iOSClient/Images.xcassets/select.imageset/1.pdf new file mode 100644 index 0000000000..70a7d0de4f Binary files /dev/null and b/iOSClient/Images.xcassets/select.imageset/1.pdf differ diff --git a/iOSClient/Images.xcassets/select.imageset/Contents.json b/iOSClient/Images.xcassets/select.imageset/Contents.json new file mode 100644 index 0000000000..dc28a0e196 --- /dev/null +++ b/iOSClient/Images.xcassets/select.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "1.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/selectFull.imageset/Contents.json b/iOSClient/Images.xcassets/selectFull.imageset/Contents.json new file mode 100644 index 0000000000..0fead39b1f --- /dev/null +++ b/iOSClient/Images.xcassets/selectFull.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "default@500w.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/selectFull.imageset/default@500w.pdf b/iOSClient/Images.xcassets/selectFull.imageset/default@500w.pdf new file mode 100644 index 0000000000..45d5146a5e Binary files /dev/null and b/iOSClient/Images.xcassets/selectFull.imageset/default@500w.pdf differ diff --git a/iOSClient/Images.xcassets/selectLight.imageset/Contents.json b/iOSClient/Images.xcassets/selectLight.imageset/Contents.json new file mode 100644 index 0000000000..12db6d7f50 --- /dev/null +++ b/iOSClient/Images.xcassets/selectLight.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "selectLight.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/selectLight.imageset/selectLight.png b/iOSClient/Images.xcassets/selectLight.imageset/selectLight.png new file mode 100644 index 0000000000..eff8324be3 Binary files /dev/null and b/iOSClient/Images.xcassets/selectLight.imageset/selectLight.png differ diff --git a/iOSClient/Images.xcassets/settings.imageset/Contents.json b/iOSClient/Images.xcassets/settings.imageset/Contents.json new file mode 100644 index 0000000000..8dfa77c79d --- /dev/null +++ b/iOSClient/Images.xcassets/settings.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "gear.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/settings.imageset/gear.pdf b/iOSClient/Images.xcassets/settings.imageset/gear.pdf new file mode 100644 index 0000000000..7182936e45 Binary files /dev/null and b/iOSClient/Images.xcassets/settings.imageset/gear.pdf differ diff --git a/iOSClient/Images.xcassets/share.imageset/Contents.json b/iOSClient/Images.xcassets/share.imageset/Contents.json new file mode 100644 index 0000000000..2991236cb4 --- /dev/null +++ b/iOSClient/Images.xcassets/share.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "shareNew.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "shareNew@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "shareNew@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/share.imageset/shareNew.png b/iOSClient/Images.xcassets/share.imageset/shareNew.png new file mode 100644 index 0000000000..e90a9c435d Binary files /dev/null and b/iOSClient/Images.xcassets/share.imageset/shareNew.png differ diff --git a/iOSClient/Images.xcassets/share.imageset/shareNew@2x.png b/iOSClient/Images.xcassets/share.imageset/shareNew@2x.png new file mode 100644 index 0000000000..92b1ee34b1 Binary files /dev/null and b/iOSClient/Images.xcassets/share.imageset/shareNew@2x.png differ diff --git a/iOSClient/Images.xcassets/share.imageset/shareNew@3x.png b/iOSClient/Images.xcassets/share.imageset/shareNew@3x.png new file mode 100644 index 0000000000..b645c63e20 Binary files /dev/null and b/iOSClient/Images.xcassets/share.imageset/shareNew@3x.png differ diff --git a/iOSClient/Images.xcassets/shareAdd.imageset/Contents.json b/iOSClient/Images.xcassets/shareAdd.imageset/Contents.json new file mode 100644 index 0000000000..cf2205ffcc --- /dev/null +++ b/iOSClient/Images.xcassets/shareAdd.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "shareAdd.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/shareAdd.imageset/shareAdd.pdf b/iOSClient/Images.xcassets/shareAdd.imageset/shareAdd.pdf new file mode 100644 index 0000000000..7a8c5c9193 Binary files /dev/null and b/iOSClient/Images.xcassets/shareAdd.imageset/shareAdd.pdf differ diff --git a/iOSClient/Images.xcassets/shareFill.imageset/Contents.json b/iOSClient/Images.xcassets/shareFill.imageset/Contents.json new file mode 100644 index 0000000000..5d0e2aab26 --- /dev/null +++ b/iOSClient/Images.xcassets/shareFill.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "share.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/shareFill.imageset/share.pdf b/iOSClient/Images.xcassets/shareFill.imageset/share.pdf new file mode 100644 index 0000000000..a1a4c9c1a2 Binary files /dev/null and b/iOSClient/Images.xcassets/shareFill.imageset/share.pdf differ diff --git a/iOSClient/Images.xcassets/shareInternalLink.imageset/Contents.json b/iOSClient/Images.xcassets/shareInternalLink.imageset/Contents.json new file mode 100644 index 0000000000..f5b01a429b --- /dev/null +++ b/iOSClient/Images.xcassets/shareInternalLink.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "shareInternalLink.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/shareInternalLink.imageset/shareInternalLink.pdf b/iOSClient/Images.xcassets/shareInternalLink.imageset/shareInternalLink.pdf new file mode 100644 index 0000000000..12ca2227f5 Binary files /dev/null and b/iOSClient/Images.xcassets/shareInternalLink.imageset/shareInternalLink.pdf differ diff --git a/iOSClient/Images.xcassets/shareMenu.imageset/Contents.json b/iOSClient/Images.xcassets/shareMenu.imageset/Contents.json new file mode 100644 index 0000000000..f1879b92be --- /dev/null +++ b/iOSClient/Images.xcassets/shareMenu.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "shareMenu.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/shareMenu.imageset/shareMenu.pdf b/iOSClient/Images.xcassets/shareMenu.imageset/shareMenu.pdf new file mode 100644 index 0000000000..46c899f329 Binary files /dev/null and b/iOSClient/Images.xcassets/shareMenu.imageset/shareMenu.pdf differ diff --git a/iOSClient/Images.xcassets/shareMounted.imageset/Contents.json b/iOSClient/Images.xcassets/shareMounted.imageset/Contents.json new file mode 100644 index 0000000000..d24d893c57 --- /dev/null +++ b/iOSClient/Images.xcassets/shareMounted.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "shareMounted.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "preserves-vector-representation" : true + } +} \ No newline at end of file diff --git a/iOSClient/Images.xcassets/shareMounted.imageset/shareMounted.pdf b/iOSClient/Images.xcassets/shareMounted.imageset/shareMounted.pdf new file mode 100644 index 0000000000..53c160d2c1 Binary files /dev/null and b/iOSClient/Images.xcassets/shareMounted.imageset/shareMounted.pdf differ diff --git a/iOSClient/Images.xcassets/shareOld.imageset/Contents.json b/iOSClient/Images.xcassets/shareOld.imageset/Contents.json new file mode 100644 index 0000000000..5d0e2aab26 --- /dev/null +++ b/iOSClient/Images.xcassets/shareOld.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "share.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/shareOld.imageset/share.pdf b/iOSClient/Images.xcassets/shareOld.imageset/share.pdf new file mode 100644 index 0000000000..a1a4c9c1a2 Binary files /dev/null and b/iOSClient/Images.xcassets/shareOld.imageset/share.pdf differ diff --git a/iOSClient/Images.xcassets/sharePhotoBrowser.imageset/Contents.json b/iOSClient/Images.xcassets/sharePhotoBrowser.imageset/Contents.json new file mode 100644 index 0000000000..1d44c683b2 --- /dev/null +++ b/iOSClient/Images.xcassets/sharePhotoBrowser.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "share.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "sharePhotoBrowser@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "share@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/sharePhotoBrowser.imageset/share.png b/iOSClient/Images.xcassets/sharePhotoBrowser.imageset/share.png new file mode 100644 index 0000000000..6c262ee817 Binary files /dev/null and b/iOSClient/Images.xcassets/sharePhotoBrowser.imageset/share.png differ diff --git a/iOSClient/Images.xcassets/sharePhotoBrowser.imageset/share@3x.png b/iOSClient/Images.xcassets/sharePhotoBrowser.imageset/share@3x.png new file mode 100644 index 0000000000..56205c9bbf Binary files /dev/null and b/iOSClient/Images.xcassets/sharePhotoBrowser.imageset/share@3x.png differ diff --git a/iOSClient/Images.xcassets/sharePhotoBrowser.imageset/sharePhotoBrowser@2x.png b/iOSClient/Images.xcassets/sharePhotoBrowser.imageset/sharePhotoBrowser@2x.png new file mode 100644 index 0000000000..1960d136df Binary files /dev/null and b/iOSClient/Images.xcassets/sharePhotoBrowser.imageset/sharePhotoBrowser@2x.png differ diff --git a/iOSClient/Images.xcassets/shareTypeEmail.imageset/Contents.json b/iOSClient/Images.xcassets/shareTypeEmail.imageset/Contents.json index 00298ac4b4..ffff08a617 100644 --- a/iOSClient/Images.xcassets/shareTypeEmail.imageset/Contents.json +++ b/iOSClient/Images.xcassets/shareTypeEmail.imageset/Contents.json @@ -1,15 +1,15 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "shareTypeEmail.pdf" + "filename" : "user.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { "preserves-vector-representation" : true } -} \ No newline at end of file +} diff --git a/iOSClient/Images.xcassets/shareTypeEmail.imageset/user.pdf b/iOSClient/Images.xcassets/shareTypeEmail.imageset/user.pdf new file mode 100644 index 0000000000..6985e202b0 Binary files /dev/null and b/iOSClient/Images.xcassets/shareTypeEmail.imageset/user.pdf differ diff --git a/iOSClient/Images.xcassets/shareTypeTeam.imageset/Contents.json b/iOSClient/Images.xcassets/shareTypeTeam.imageset/Contents.json index 95d6c3b747..3859d97998 100644 --- a/iOSClient/Images.xcassets/shareTypeTeam.imageset/Contents.json +++ b/iOSClient/Images.xcassets/shareTypeTeam.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "filename" : "shareTypeTeam.pdf", - "idiom" : "universal" + "idiom" : "universal", + "filename" : "circle.pdf" } ], "info" : { - "author" : "xcode", - "version" : 1 + "version" : 1, + "author" : "xcode" }, "properties" : { "preserves-vector-representation" : true diff --git a/iOSClient/Images.xcassets/shareTypeTeam.imageset/circle.pdf b/iOSClient/Images.xcassets/shareTypeTeam.imageset/circle.pdf new file mode 100644 index 0000000000..4be68b831d Binary files /dev/null and b/iOSClient/Images.xcassets/shareTypeTeam.imageset/circle.pdf differ diff --git a/iOSClient/Images.xcassets/shareTypeUser.imageset/Contents.json b/iOSClient/Images.xcassets/shareTypeUser.imageset/Contents.json index 874a5b2007..11ca2fc9dd 100644 --- a/iOSClient/Images.xcassets/shareTypeUser.imageset/Contents.json +++ b/iOSClient/Images.xcassets/shareTypeUser.imageset/Contents.json @@ -1,15 +1,15 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "shareTypeUser.pdf" + "filename" : "shareTypeUser.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { "preserves-vector-representation" : true } -} \ No newline at end of file +} diff --git a/iOSClient/Images.xcassets/shareTypeUser.imageset/shareTypeUser.pdf b/iOSClient/Images.xcassets/shareTypeUser.imageset/shareTypeUser.pdf index 03d855dcc4..62d278bb89 100644 Binary files a/iOSClient/Images.xcassets/shareTypeUser.imageset/shareTypeUser.pdf and b/iOSClient/Images.xcassets/shareTypeUser.imageset/shareTypeUser.pdf differ diff --git a/iOSClient/Images.xcassets/sharebylink.imageset/Contents.json b/iOSClient/Images.xcassets/sharebylink.imageset/Contents.json new file mode 100644 index 0000000000..3d40e6ef2a --- /dev/null +++ b/iOSClient/Images.xcassets/sharebylink.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "sharebylink.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/trash.imageset/trash.pdf b/iOSClient/Images.xcassets/sharebylink.imageset/sharebylink.pdf similarity index 94% rename from iOSClient/Images.xcassets/trash.imageset/trash.pdf rename to iOSClient/Images.xcassets/sharebylink.imageset/sharebylink.pdf index 9233b74c6f..40caf0cbcf 100644 Binary files a/iOSClient/Images.xcassets/trash.imageset/trash.pdf and b/iOSClient/Images.xcassets/sharebylink.imageset/sharebylink.pdf differ diff --git a/iOSClient/Images.xcassets/shield.checkerboard.imageset/Contents.json b/iOSClient/Images.xcassets/shield.checkerboard.imageset/Contents.json new file mode 100644 index 0000000000..e60bc99a84 --- /dev/null +++ b/iOSClient/Images.xcassets/shield.checkerboard.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "privacy.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "privacy@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "privacy@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/shield.checkerboard.imageset/privacy.png b/iOSClient/Images.xcassets/shield.checkerboard.imageset/privacy.png new file mode 100644 index 0000000000..b83f9c242c Binary files /dev/null and b/iOSClient/Images.xcassets/shield.checkerboard.imageset/privacy.png differ diff --git a/iOSClient/Images.xcassets/shield.checkerboard.imageset/privacy@2x.png b/iOSClient/Images.xcassets/shield.checkerboard.imageset/privacy@2x.png new file mode 100644 index 0000000000..4890418de1 Binary files /dev/null and b/iOSClient/Images.xcassets/shield.checkerboard.imageset/privacy@2x.png differ diff --git a/iOSClient/Images.xcassets/shield.checkerboard.imageset/privacy@3x.png b/iOSClient/Images.xcassets/shield.checkerboard.imageset/privacy@3x.png new file mode 100644 index 0000000000..bafa61a8b0 Binary files /dev/null and b/iOSClient/Images.xcassets/shield.checkerboard.imageset/privacy@3x.png differ diff --git a/iOSClient/Images.xcassets/showPasswordNew.imageset/Contents.json b/iOSClient/Images.xcassets/showPasswordNew.imageset/Contents.json new file mode 100644 index 0000000000..0408c1c271 --- /dev/null +++ b/iOSClient/Images.xcassets/showPasswordNew.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "showPasswordNew.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "showPasswordNew@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "showPasswordNew@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/showPasswordNew.imageset/showPasswordNew.png b/iOSClient/Images.xcassets/showPasswordNew.imageset/showPasswordNew.png new file mode 100644 index 0000000000..3b63d5e432 Binary files /dev/null and b/iOSClient/Images.xcassets/showPasswordNew.imageset/showPasswordNew.png differ diff --git a/iOSClient/Images.xcassets/showPasswordNew.imageset/showPasswordNew@2x.png b/iOSClient/Images.xcassets/showPasswordNew.imageset/showPasswordNew@2x.png new file mode 100644 index 0000000000..93e980311a Binary files /dev/null and b/iOSClient/Images.xcassets/showPasswordNew.imageset/showPasswordNew@2x.png differ diff --git a/iOSClient/Images.xcassets/showPasswordNew.imageset/showPasswordNew@3x.png b/iOSClient/Images.xcassets/showPasswordNew.imageset/showPasswordNew@3x.png new file mode 100644 index 0000000000..3f91ca46d0 Binary files /dev/null and b/iOSClient/Images.xcassets/showPasswordNew.imageset/showPasswordNew@3x.png differ diff --git a/iOSClient/Images.xcassets/sortDateLessRecent.imageset/Contents.json b/iOSClient/Images.xcassets/sortDateLessRecent.imageset/Contents.json new file mode 100644 index 0000000000..16f652eaab --- /dev/null +++ b/iOSClient/Images.xcassets/sortDateLessRecent.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "sortDateLess.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "sortDateLess@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "sortDateLess@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/sortDateLessRecent.imageset/sortDateLess.png b/iOSClient/Images.xcassets/sortDateLessRecent.imageset/sortDateLess.png new file mode 100644 index 0000000000..7679833bfe Binary files /dev/null and b/iOSClient/Images.xcassets/sortDateLessRecent.imageset/sortDateLess.png differ diff --git a/iOSClient/Images.xcassets/sortDateLessRecent.imageset/sortDateLess@2x.png b/iOSClient/Images.xcassets/sortDateLessRecent.imageset/sortDateLess@2x.png new file mode 100644 index 0000000000..3c31183268 Binary files /dev/null and b/iOSClient/Images.xcassets/sortDateLessRecent.imageset/sortDateLess@2x.png differ diff --git a/iOSClient/Images.xcassets/sortDateLessRecent.imageset/sortDateLess@3x.png b/iOSClient/Images.xcassets/sortDateLessRecent.imageset/sortDateLess@3x.png new file mode 100644 index 0000000000..d607e5c1a4 Binary files /dev/null and b/iOSClient/Images.xcassets/sortDateLessRecent.imageset/sortDateLess@3x.png differ diff --git a/iOSClient/Images.xcassets/sortDateMoreRecent.imageset/Contents.json b/iOSClient/Images.xcassets/sortDateMoreRecent.imageset/Contents.json new file mode 100644 index 0000000000..16f652eaab --- /dev/null +++ b/iOSClient/Images.xcassets/sortDateMoreRecent.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "sortDateLess.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "sortDateLess@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "sortDateLess@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/sortDateMoreRecent.imageset/sortDateLess.png b/iOSClient/Images.xcassets/sortDateMoreRecent.imageset/sortDateLess.png new file mode 100644 index 0000000000..7679833bfe Binary files /dev/null and b/iOSClient/Images.xcassets/sortDateMoreRecent.imageset/sortDateLess.png differ diff --git a/iOSClient/Images.xcassets/sortDateMoreRecent.imageset/sortDateLess@2x.png b/iOSClient/Images.xcassets/sortDateMoreRecent.imageset/sortDateLess@2x.png new file mode 100644 index 0000000000..3c31183268 Binary files /dev/null and b/iOSClient/Images.xcassets/sortDateMoreRecent.imageset/sortDateLess@2x.png differ diff --git a/iOSClient/Images.xcassets/sortDateMoreRecent.imageset/sortDateLess@3x.png b/iOSClient/Images.xcassets/sortDateMoreRecent.imageset/sortDateLess@3x.png new file mode 100644 index 0000000000..d607e5c1a4 Binary files /dev/null and b/iOSClient/Images.xcassets/sortDateMoreRecent.imageset/sortDateLess@3x.png differ diff --git a/iOSClient/Images.xcassets/sortFileNameAZ.imageset/Contents.json b/iOSClient/Images.xcassets/sortFileNameAZ.imageset/Contents.json new file mode 100644 index 0000000000..ab8789256f --- /dev/null +++ b/iOSClient/Images.xcassets/sortFileNameAZ.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "sortFileNameAZ.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "sortFileNameAZ@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "sortFileNameAZ@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/sortFileNameAZ.imageset/sortFileNameAZ.png b/iOSClient/Images.xcassets/sortFileNameAZ.imageset/sortFileNameAZ.png new file mode 100644 index 0000000000..41c8ae8e25 Binary files /dev/null and b/iOSClient/Images.xcassets/sortFileNameAZ.imageset/sortFileNameAZ.png differ diff --git a/iOSClient/Images.xcassets/sortFileNameAZ.imageset/sortFileNameAZ@2x.png b/iOSClient/Images.xcassets/sortFileNameAZ.imageset/sortFileNameAZ@2x.png new file mode 100644 index 0000000000..0532a1bf38 Binary files /dev/null and b/iOSClient/Images.xcassets/sortFileNameAZ.imageset/sortFileNameAZ@2x.png differ diff --git a/iOSClient/Images.xcassets/sortFileNameAZ.imageset/sortFileNameAZ@3x.png b/iOSClient/Images.xcassets/sortFileNameAZ.imageset/sortFileNameAZ@3x.png new file mode 100644 index 0000000000..5cb93d7c25 Binary files /dev/null and b/iOSClient/Images.xcassets/sortFileNameAZ.imageset/sortFileNameAZ@3x.png differ diff --git a/iOSClient/Images.xcassets/sortFileNameZA.imageset/Contents.json b/iOSClient/Images.xcassets/sortFileNameZA.imageset/Contents.json new file mode 100644 index 0000000000..33faa99868 --- /dev/null +++ b/iOSClient/Images.xcassets/sortFileNameZA.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "sortFileNameAZ.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "sortFileNameAZ@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "sortFileNameAZ@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/sortFileNameZA.imageset/sortFileNameAZ.png b/iOSClient/Images.xcassets/sortFileNameZA.imageset/sortFileNameAZ.png new file mode 100644 index 0000000000..41c8ae8e25 Binary files /dev/null and b/iOSClient/Images.xcassets/sortFileNameZA.imageset/sortFileNameAZ.png differ diff --git a/iOSClient/Images.xcassets/sortFileNameZA.imageset/sortFileNameAZ@2x.png b/iOSClient/Images.xcassets/sortFileNameZA.imageset/sortFileNameAZ@2x.png new file mode 100644 index 0000000000..0532a1bf38 Binary files /dev/null and b/iOSClient/Images.xcassets/sortFileNameZA.imageset/sortFileNameAZ@2x.png differ diff --git a/iOSClient/Images.xcassets/sortFileNameZA.imageset/sortFileNameAZ@3x.png b/iOSClient/Images.xcassets/sortFileNameZA.imageset/sortFileNameAZ@3x.png new file mode 100644 index 0000000000..5cb93d7c25 Binary files /dev/null and b/iOSClient/Images.xcassets/sortFileNameZA.imageset/sortFileNameAZ@3x.png differ diff --git a/iOSClient/Images.xcassets/sortLargest.imageset/Contents.json b/iOSClient/Images.xcassets/sortLargest.imageset/Contents.json new file mode 100644 index 0000000000..e92b17d4d0 --- /dev/null +++ b/iOSClient/Images.xcassets/sortLargest.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "sortLargest.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "sortLargest@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "sortLargest@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/sortLargest.imageset/sortLargest.png b/iOSClient/Images.xcassets/sortLargest.imageset/sortLargest.png new file mode 100644 index 0000000000..47a510c37b Binary files /dev/null and b/iOSClient/Images.xcassets/sortLargest.imageset/sortLargest.png differ diff --git a/iOSClient/Images.xcassets/sortLargest.imageset/sortLargest@2x.png b/iOSClient/Images.xcassets/sortLargest.imageset/sortLargest@2x.png new file mode 100644 index 0000000000..e77c5e3960 Binary files /dev/null and b/iOSClient/Images.xcassets/sortLargest.imageset/sortLargest@2x.png differ diff --git a/iOSClient/Images.xcassets/sortLargest.imageset/sortLargest@3x.png b/iOSClient/Images.xcassets/sortLargest.imageset/sortLargest@3x.png new file mode 100644 index 0000000000..8938830b7e Binary files /dev/null and b/iOSClient/Images.xcassets/sortLargest.imageset/sortLargest@3x.png differ diff --git a/iOSClient/Images.xcassets/sortSmallest.imageset/Contents.json b/iOSClient/Images.xcassets/sortSmallest.imageset/Contents.json new file mode 100644 index 0000000000..91698080a7 --- /dev/null +++ b/iOSClient/Images.xcassets/sortSmallest.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "sortSmallest.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "sortSmallest@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "sortSmallest@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/sortSmallest.imageset/sortSmallest.png b/iOSClient/Images.xcassets/sortSmallest.imageset/sortSmallest.png new file mode 100644 index 0000000000..24dda815e8 Binary files /dev/null and b/iOSClient/Images.xcassets/sortSmallest.imageset/sortSmallest.png differ diff --git a/iOSClient/Images.xcassets/sortSmallest.imageset/sortSmallest@2x.png b/iOSClient/Images.xcassets/sortSmallest.imageset/sortSmallest@2x.png new file mode 100644 index 0000000000..2977b318dd Binary files /dev/null and b/iOSClient/Images.xcassets/sortSmallest.imageset/sortSmallest@2x.png differ diff --git a/iOSClient/Images.xcassets/sortSmallest.imageset/sortSmallest@3x.png b/iOSClient/Images.xcassets/sortSmallest.imageset/sortSmallest@3x.png new file mode 100644 index 0000000000..834e834132 Binary files /dev/null and b/iOSClient/Images.xcassets/sortSmallest.imageset/sortSmallest@3x.png differ diff --git a/iOSClient/Images.xcassets/speaker0.imageset/Contents.json b/iOSClient/Images.xcassets/speaker0.imageset/Contents.json new file mode 100644 index 0000000000..cc93e05978 --- /dev/null +++ b/iOSClient/Images.xcassets/speaker0.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "speaker0.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/speaker0.imageset/speaker0.svg b/iOSClient/Images.xcassets/speaker0.imageset/speaker0.svg new file mode 100644 index 0000000000..a70f4507ee --- /dev/null +++ b/iOSClient/Images.xcassets/speaker0.imageset/speaker0.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/speaker1.imageset/Contents.json b/iOSClient/Images.xcassets/speaker1.imageset/Contents.json new file mode 100644 index 0000000000..ff3b03bf97 --- /dev/null +++ b/iOSClient/Images.xcassets/speaker1.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "speaker1.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/speaker1.imageset/speaker1.svg b/iOSClient/Images.xcassets/speaker1.imageset/speaker1.svg new file mode 100644 index 0000000000..957cd4d925 --- /dev/null +++ b/iOSClient/Images.xcassets/speaker1.imageset/speaker1.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/speaker2.imageset/Contents.json b/iOSClient/Images.xcassets/speaker2.imageset/Contents.json new file mode 100644 index 0000000000..92044d85c5 --- /dev/null +++ b/iOSClient/Images.xcassets/speaker2.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "speaker2.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/speaker2.imageset/speaker2.svg b/iOSClient/Images.xcassets/speaker2.imageset/speaker2.svg new file mode 100644 index 0000000000..3a22d817a4 --- /dev/null +++ b/iOSClient/Images.xcassets/speaker2.imageset/speaker2.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/speaker3.imageset/Contents.json b/iOSClient/Images.xcassets/speaker3.imageset/Contents.json new file mode 100644 index 0000000000..0125d154b4 --- /dev/null +++ b/iOSClient/Images.xcassets/speaker3.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "speaker3.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/speaker3.imageset/speaker3.svg b/iOSClient/Images.xcassets/speaker3.imageset/speaker3.svg new file mode 100644 index 0000000000..567b58690d --- /dev/null +++ b/iOSClient/Images.xcassets/speaker3.imageset/speaker3.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/square.and.arrow.down.imageset/Contents.json b/iOSClient/Images.xcassets/square.and.arrow.down.imageset/Contents.json new file mode 100644 index 0000000000..052394eece --- /dev/null +++ b/iOSClient/Images.xcassets/square.and.arrow.down.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "saveSelectedFiles.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "saveSelectedFiles@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "saveSelectedFiles@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/square.and.arrow.down.imageset/saveSelectedFiles.png b/iOSClient/Images.xcassets/square.and.arrow.down.imageset/saveSelectedFiles.png new file mode 100644 index 0000000000..590c922f4e Binary files /dev/null and b/iOSClient/Images.xcassets/square.and.arrow.down.imageset/saveSelectedFiles.png differ diff --git a/iOSClient/Images.xcassets/square.and.arrow.down.imageset/saveSelectedFiles@2x.png b/iOSClient/Images.xcassets/square.and.arrow.down.imageset/saveSelectedFiles@2x.png new file mode 100644 index 0000000000..589eeb56c2 Binary files /dev/null and b/iOSClient/Images.xcassets/square.and.arrow.down.imageset/saveSelectedFiles@2x.png differ diff --git a/iOSClient/Images.xcassets/square.and.arrow.down.imageset/saveSelectedFiles@3x.png b/iOSClient/Images.xcassets/square.and.arrow.down.imageset/saveSelectedFiles@3x.png new file mode 100644 index 0000000000..4d1f750642 Binary files /dev/null and b/iOSClient/Images.xcassets/square.and.arrow.down.imageset/saveSelectedFiles@3x.png differ diff --git a/iOSClient/Images.xcassets/square.and.arrow.up.imageset/Contents.json b/iOSClient/Images.xcassets/square.and.arrow.up.imageset/Contents.json new file mode 100644 index 0000000000..78451c57ba --- /dev/null +++ b/iOSClient/Images.xcassets/square.and.arrow.up.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "export-variant.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/square.and.arrow.up.imageset/export-variant.svg b/iOSClient/Images.xcassets/square.and.arrow.up.imageset/export-variant.svg new file mode 100644 index 0000000000..5b5f5aecd9 --- /dev/null +++ b/iOSClient/Images.xcassets/square.and.arrow.up.imageset/export-variant.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/iOSClient/Images.xcassets/statusdownload.imageset/Contents.json b/iOSClient/Images.xcassets/statusdownload.imageset/Contents.json new file mode 100644 index 0000000000..be3c311a02 --- /dev/null +++ b/iOSClient/Images.xcassets/statusdownload.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "statusdownload.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "statusdownload@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "statusdownload@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/statusdownload.imageset/statusdownload.png b/iOSClient/Images.xcassets/statusdownload.imageset/statusdownload.png new file mode 100644 index 0000000000..ea4a54a7af Binary files /dev/null and b/iOSClient/Images.xcassets/statusdownload.imageset/statusdownload.png differ diff --git a/iOSClient/Images.xcassets/statusdownload.imageset/statusdownload@2x.png b/iOSClient/Images.xcassets/statusdownload.imageset/statusdownload@2x.png new file mode 100644 index 0000000000..86523e479d Binary files /dev/null and b/iOSClient/Images.xcassets/statusdownload.imageset/statusdownload@2x.png differ diff --git a/iOSClient/Images.xcassets/statusdownload.imageset/statusdownload@3x.png b/iOSClient/Images.xcassets/statusdownload.imageset/statusdownload@3x.png new file mode 100644 index 0000000000..30b1858034 Binary files /dev/null and b/iOSClient/Images.xcassets/statusdownload.imageset/statusdownload@3x.png differ diff --git a/iOSClient/Images.xcassets/statuserror.imageset/Contents.json b/iOSClient/Images.xcassets/statuserror.imageset/Contents.json new file mode 100644 index 0000000000..90c24b9a7e --- /dev/null +++ b/iOSClient/Images.xcassets/statuserror.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "statuserror.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "statuserror@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "statuserror@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/statuserror.imageset/statuserror.png b/iOSClient/Images.xcassets/statuserror.imageset/statuserror.png new file mode 100644 index 0000000000..ec243f09c0 Binary files /dev/null and b/iOSClient/Images.xcassets/statuserror.imageset/statuserror.png differ diff --git a/iOSClient/Images.xcassets/statuserror.imageset/statuserror@2x.png b/iOSClient/Images.xcassets/statuserror.imageset/statuserror@2x.png new file mode 100644 index 0000000000..83e5cb20f7 Binary files /dev/null and b/iOSClient/Images.xcassets/statuserror.imageset/statuserror@2x.png differ diff --git a/iOSClient/Images.xcassets/statuserror.imageset/statuserror@3x.png b/iOSClient/Images.xcassets/statuserror.imageset/statuserror@3x.png new file mode 100644 index 0000000000..886dd8b538 Binary files /dev/null and b/iOSClient/Images.xcassets/statuserror.imageset/statuserror@3x.png differ diff --git a/iOSClient/Images.xcassets/statusupload.imageset/Contents.json b/iOSClient/Images.xcassets/statusupload.imageset/Contents.json new file mode 100644 index 0000000000..07cd780b37 --- /dev/null +++ b/iOSClient/Images.xcassets/statusupload.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "statusupload.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "statusupload@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "statusupload@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/statusupload.imageset/statusupload.png b/iOSClient/Images.xcassets/statusupload.imageset/statusupload.png new file mode 100644 index 0000000000..95e89fae88 Binary files /dev/null and b/iOSClient/Images.xcassets/statusupload.imageset/statusupload.png differ diff --git a/iOSClient/Images.xcassets/statusupload.imageset/statusupload@2x.png b/iOSClient/Images.xcassets/statusupload.imageset/statusupload@2x.png new file mode 100644 index 0000000000..6a22c8f3d1 Binary files /dev/null and b/iOSClient/Images.xcassets/statusupload.imageset/statusupload@2x.png differ diff --git a/iOSClient/Images.xcassets/statusupload.imageset/statusupload@3x.png b/iOSClient/Images.xcassets/statusupload.imageset/statusupload@3x.png new file mode 100644 index 0000000000..8740be36ed Binary files /dev/null and b/iOSClient/Images.xcassets/statusupload.imageset/statusupload@3x.png differ diff --git a/iOSClient/Images.xcassets/success.imageset/Contents.json b/iOSClient/Images.xcassets/success.imageset/Contents.json new file mode 100644 index 0000000000..858785f7a8 --- /dev/null +++ b/iOSClient/Images.xcassets/success.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "success.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "success@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "success@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/success.imageset/success.png b/iOSClient/Images.xcassets/success.imageset/success.png new file mode 100644 index 0000000000..b1d2459a4b Binary files /dev/null and b/iOSClient/Images.xcassets/success.imageset/success.png differ diff --git a/iOSClient/Images.xcassets/success.imageset/success@2x.png b/iOSClient/Images.xcassets/success.imageset/success@2x.png new file mode 100644 index 0000000000..9832eda028 Binary files /dev/null and b/iOSClient/Images.xcassets/success.imageset/success@2x.png differ diff --git a/iOSClient/Images.xcassets/success.imageset/success@3x.png b/iOSClient/Images.xcassets/success.imageset/success@3x.png new file mode 100644 index 0000000000..d89d2e4719 Binary files /dev/null and b/iOSClient/Images.xcassets/success.imageset/success@3x.png differ diff --git a/iOSClient/Images.xcassets/switchGrid.imageset/Contents.json b/iOSClient/Images.xcassets/switchGrid.imageset/Contents.json new file mode 100644 index 0000000000..b1304ea08b --- /dev/null +++ b/iOSClient/Images.xcassets/switchGrid.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "switchGrid.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "switchGrid@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "switchGrid@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/switchGrid.imageset/switchGrid.png b/iOSClient/Images.xcassets/switchGrid.imageset/switchGrid.png new file mode 100644 index 0000000000..ed000d793f Binary files /dev/null and b/iOSClient/Images.xcassets/switchGrid.imageset/switchGrid.png differ diff --git a/iOSClient/Images.xcassets/switchGrid.imageset/switchGrid@2x.png b/iOSClient/Images.xcassets/switchGrid.imageset/switchGrid@2x.png new file mode 100644 index 0000000000..860729706b Binary files /dev/null and b/iOSClient/Images.xcassets/switchGrid.imageset/switchGrid@2x.png differ diff --git a/iOSClient/Images.xcassets/switchGrid.imageset/switchGrid@3x.png b/iOSClient/Images.xcassets/switchGrid.imageset/switchGrid@3x.png new file mode 100644 index 0000000000..582b458a0a Binary files /dev/null and b/iOSClient/Images.xcassets/switchGrid.imageset/switchGrid@3x.png differ diff --git a/iOSClient/Images.xcassets/switchList.imageset/Contents.json b/iOSClient/Images.xcassets/switchList.imageset/Contents.json new file mode 100644 index 0000000000..d0a70e20e3 --- /dev/null +++ b/iOSClient/Images.xcassets/switchList.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "switchList.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "switchList@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "switchList@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/switchList.imageset/switchList.png b/iOSClient/Images.xcassets/switchList.imageset/switchList.png new file mode 100644 index 0000000000..e68e96d87e Binary files /dev/null and b/iOSClient/Images.xcassets/switchList.imageset/switchList.png differ diff --git a/iOSClient/Images.xcassets/switchList.imageset/switchList@2x.png b/iOSClient/Images.xcassets/switchList.imageset/switchList@2x.png new file mode 100644 index 0000000000..1f387ae4e9 Binary files /dev/null and b/iOSClient/Images.xcassets/switchList.imageset/switchList@2x.png differ diff --git a/iOSClient/Images.xcassets/switchList.imageset/switchList@3x.png b/iOSClient/Images.xcassets/switchList.imageset/switchList@3x.png new file mode 100644 index 0000000000..5671a05ded Binary files /dev/null and b/iOSClient/Images.xcassets/switchList.imageset/switchList@3x.png differ diff --git a/iOSClient/Images.xcassets/tabBarFiles.imageset/Contents.json b/iOSClient/Images.xcassets/tabBarFiles.imageset/Contents.json new file mode 100644 index 0000000000..662b45275b --- /dev/null +++ b/iOSClient/Images.xcassets/tabBarFiles.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "tabBarFiles.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/iOSClient/Images.xcassets/tabBarFiles.imageset/tabBarFiles.pdf b/iOSClient/Images.xcassets/tabBarFiles.imageset/tabBarFiles.pdf new file mode 100644 index 0000000000..e9a6038f8e Binary files /dev/null and b/iOSClient/Images.xcassets/tabBarFiles.imageset/tabBarFiles.pdf differ diff --git a/iOSClient/Images.xcassets/tabBarMore.imageset/Contents.json b/iOSClient/Images.xcassets/tabBarMore.imageset/Contents.json new file mode 100644 index 0000000000..27f050f497 --- /dev/null +++ b/iOSClient/Images.xcassets/tabBarMore.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "tabBarMore.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/iOSClient/Images.xcassets/tabBarMore.imageset/tabBarMore.pdf b/iOSClient/Images.xcassets/tabBarMore.imageset/tabBarMore.pdf new file mode 100644 index 0000000000..9a950a9b28 Binary files /dev/null and b/iOSClient/Images.xcassets/tabBarMore.imageset/tabBarMore.pdf differ diff --git a/iOSClient/Images.xcassets/talk-template.imageset/Contents.json b/iOSClient/Images.xcassets/talk-template.imageset/Contents.json index 84eb196479..7ecaa63288 100644 --- a/iOSClient/Images.xcassets/talk-template.imageset/Contents.json +++ b/iOSClient/Images.xcassets/talk-template.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "app.svg", + "filename" : "talk.png", "idiom" : "universal" } ], diff --git a/iOSClient/Images.xcassets/talk-template.imageset/talk.png b/iOSClient/Images.xcassets/talk-template.imageset/talk.png new file mode 100644 index 0000000000..c124efb15d Binary files /dev/null and b/iOSClient/Images.xcassets/talk-template.imageset/talk.png differ diff --git a/iOSClient/Images.xcassets/talk.imageset/Contents.json b/iOSClient/Images.xcassets/talk.imageset/Contents.json new file mode 100644 index 0000000000..9384b676cd --- /dev/null +++ b/iOSClient/Images.xcassets/talk.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "talk.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/talk.imageset/talk.png b/iOSClient/Images.xcassets/talk.imageset/talk.png new file mode 100644 index 0000000000..c124efb15d Binary files /dev/null and b/iOSClient/Images.xcassets/talk.imageset/talk.png differ diff --git a/iOSClient/Images.xcassets/talk_bar.imageset/Contents.json b/iOSClient/Images.xcassets/talk_bar.imageset/Contents.json new file mode 100644 index 0000000000..76ba0d1ebe --- /dev/null +++ b/iOSClient/Images.xcassets/talk_bar.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "talk.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "talk_bar 1.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "talk_bar 2.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/talk_bar.imageset/talk.png b/iOSClient/Images.xcassets/talk_bar.imageset/talk.png new file mode 100644 index 0000000000..ff9f79e531 Binary files /dev/null and b/iOSClient/Images.xcassets/talk_bar.imageset/talk.png differ diff --git a/iOSClient/Images.xcassets/talk_bar.imageset/talk_bar 1.png b/iOSClient/Images.xcassets/talk_bar.imageset/talk_bar 1.png new file mode 100644 index 0000000000..f86c0a3574 Binary files /dev/null and b/iOSClient/Images.xcassets/talk_bar.imageset/talk_bar 1.png differ diff --git a/iOSClient/Images.xcassets/talk_bar.imageset/talk_bar 2.png b/iOSClient/Images.xcassets/talk_bar.imageset/talk_bar 2.png new file mode 100644 index 0000000000..a1a2edcf07 Binary files /dev/null and b/iOSClient/Images.xcassets/talk_bar.imageset/talk_bar 2.png differ diff --git a/iOSClient/Images.xcassets/taskCancelDownload.imageset/Contents.json b/iOSClient/Images.xcassets/taskCancelDownload.imageset/Contents.json new file mode 100644 index 0000000000..740de0b53d --- /dev/null +++ b/iOSClient/Images.xcassets/taskCancelDownload.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "stoptask.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "stoptask@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "stoptask@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/taskCancelDownload.imageset/stoptask.png b/iOSClient/Images.xcassets/taskCancelDownload.imageset/stoptask.png new file mode 100644 index 0000000000..0b10fd2706 Binary files /dev/null and b/iOSClient/Images.xcassets/taskCancelDownload.imageset/stoptask.png differ diff --git a/iOSClient/Images.xcassets/taskCancelDownload.imageset/stoptask@2x.png b/iOSClient/Images.xcassets/taskCancelDownload.imageset/stoptask@2x.png new file mode 100644 index 0000000000..f2a89067cb Binary files /dev/null and b/iOSClient/Images.xcassets/taskCancelDownload.imageset/stoptask@2x.png differ diff --git a/iOSClient/Images.xcassets/taskCancelDownload.imageset/stoptask@3x.png b/iOSClient/Images.xcassets/taskCancelDownload.imageset/stoptask@3x.png new file mode 100644 index 0000000000..6b8d8eaef6 Binary files /dev/null and b/iOSClient/Images.xcassets/taskCancelDownload.imageset/stoptask@3x.png differ diff --git a/iOSClient/Images.xcassets/taskCancelUpload.imageset/Contents.json b/iOSClient/Images.xcassets/taskCancelUpload.imageset/Contents.json new file mode 100644 index 0000000000..08d1ba722a --- /dev/null +++ b/iOSClient/Images.xcassets/taskCancelUpload.imageset/Contents.json @@ -0,0 +1,26 @@ +{ + "images" : [ + { + "filename" : "removetask.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "removetask@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "removetask@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/taskCancelUpload.imageset/removetask.png b/iOSClient/Images.xcassets/taskCancelUpload.imageset/removetask.png new file mode 100644 index 0000000000..de385275f3 Binary files /dev/null and b/iOSClient/Images.xcassets/taskCancelUpload.imageset/removetask.png differ diff --git a/iOSClient/Images.xcassets/taskCancelUpload.imageset/removetask@2x.png b/iOSClient/Images.xcassets/taskCancelUpload.imageset/removetask@2x.png new file mode 100644 index 0000000000..3be6410bb3 Binary files /dev/null and b/iOSClient/Images.xcassets/taskCancelUpload.imageset/removetask@2x.png differ diff --git a/iOSClient/Images.xcassets/taskCancelUpload.imageset/removetask@3x.png b/iOSClient/Images.xcassets/taskCancelUpload.imageset/removetask@3x.png new file mode 100644 index 0000000000..ac0e3c6847 Binary files /dev/null and b/iOSClient/Images.xcassets/taskCancelUpload.imageset/removetask@3x.png differ diff --git a/iOSClient/Images.xcassets/text.imageset/Contents.json b/iOSClient/Images.xcassets/text.imageset/Contents.json new file mode 100644 index 0000000000..ceaab0a067 --- /dev/null +++ b/iOSClient/Images.xcassets/text.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "text.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/text.imageset/text.pdf b/iOSClient/Images.xcassets/text.imageset/text.pdf new file mode 100644 index 0000000000..2154ceece1 Binary files /dev/null and b/iOSClient/Images.xcassets/text.imageset/text.pdf differ diff --git a/iOSClient/Images.xcassets/trash.imageset/Contents.json b/iOSClient/Images.xcassets/trash.imageset/Contents.json index e98514534c..0fead39b1f 100644 --- a/iOSClient/Images.xcassets/trash.imageset/Contents.json +++ b/iOSClient/Images.xcassets/trash.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "trash.pdf", + "filename" : "default@500w.pdf", "idiom" : "universal" } ], diff --git a/iOSClient/Images.xcassets/trash.imageset/default@500w.pdf b/iOSClient/Images.xcassets/trash.imageset/default@500w.pdf new file mode 100644 index 0000000000..225c983dec Binary files /dev/null and b/iOSClient/Images.xcassets/trash.imageset/default@500w.pdf differ diff --git a/iOSClient/Images.xcassets/upload.imageset/Contents.json b/iOSClient/Images.xcassets/upload.imageset/Contents.json new file mode 100644 index 0000000000..5ce819825a --- /dev/null +++ b/iOSClient/Images.xcassets/upload.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "upload.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "upload@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "upload@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/upload.imageset/upload.png b/iOSClient/Images.xcassets/upload.imageset/upload.png new file mode 100644 index 0000000000..0f76ce12bc Binary files /dev/null and b/iOSClient/Images.xcassets/upload.imageset/upload.png differ diff --git a/iOSClient/Images.xcassets/upload.imageset/upload@2x.png b/iOSClient/Images.xcassets/upload.imageset/upload@2x.png new file mode 100644 index 0000000000..2f4e286f6f Binary files /dev/null and b/iOSClient/Images.xcassets/upload.imageset/upload@2x.png differ diff --git a/iOSClient/Images.xcassets/upload.imageset/upload@3x.png b/iOSClient/Images.xcassets/upload.imageset/upload@3x.png new file mode 100644 index 0000000000..5a0f7be299 Binary files /dev/null and b/iOSClient/Images.xcassets/upload.imageset/upload@3x.png differ diff --git a/iOSClient/Images.xcassets/uploadFile.imageset/Contents.json b/iOSClient/Images.xcassets/uploadFile.imageset/Contents.json new file mode 100644 index 0000000000..5866e33b62 --- /dev/null +++ b/iOSClient/Images.xcassets/uploadFile.imageset/Contents.json @@ -0,0 +1,52 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "default@500w.pdf", + "idiom" : "universal", + "scale" : "2x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "default copy@500w.pdf", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/uploadFile.imageset/default copy@500w.pdf b/iOSClient/Images.xcassets/uploadFile.imageset/default copy@500w.pdf new file mode 100644 index 0000000000..568fb350d6 Binary files /dev/null and b/iOSClient/Images.xcassets/uploadFile.imageset/default copy@500w.pdf differ diff --git a/iOSClient/Images.xcassets/uploadFile.imageset/default@500w.pdf b/iOSClient/Images.xcassets/uploadFile.imageset/default@500w.pdf new file mode 100644 index 0000000000..49bbe6f285 Binary files /dev/null and b/iOSClient/Images.xcassets/uploadFile.imageset/default@500w.pdf differ diff --git a/iOSClient/Images.xcassets/user_settings.imageset/Contents.json b/iOSClient/Images.xcassets/user_settings.imageset/Contents.json new file mode 100644 index 0000000000..7e6128a816 --- /dev/null +++ b/iOSClient/Images.xcassets/user_settings.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "default@1,5x.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "default@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "default@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/user_settings.imageset/default@1,5x.png b/iOSClient/Images.xcassets/user_settings.imageset/default@1,5x.png new file mode 100644 index 0000000000..a556ff9868 Binary files /dev/null and b/iOSClient/Images.xcassets/user_settings.imageset/default@1,5x.png differ diff --git a/iOSClient/Images.xcassets/user_settings.imageset/default@2x.png b/iOSClient/Images.xcassets/user_settings.imageset/default@2x.png new file mode 100644 index 0000000000..c812343a8c Binary files /dev/null and b/iOSClient/Images.xcassets/user_settings.imageset/default@2x.png differ diff --git a/iOSClient/Images.xcassets/user_settings.imageset/default@3x.png b/iOSClient/Images.xcassets/user_settings.imageset/default@3x.png new file mode 100644 index 0000000000..eed7389198 Binary files /dev/null and b/iOSClient/Images.xcassets/user_settings.imageset/default@3x.png differ diff --git a/iOSClient/Images.xcassets/videono.imageset/Contents.json b/iOSClient/Images.xcassets/videono.imageset/Contents.json new file mode 100644 index 0000000000..5c7961ea2a --- /dev/null +++ b/iOSClient/Images.xcassets/videono.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "deviceNocamera.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/videono.imageset/deviceNocamera.pdf b/iOSClient/Images.xcassets/videono.imageset/deviceNocamera.pdf new file mode 100644 index 0000000000..09ff9e66eb Binary files /dev/null and b/iOSClient/Images.xcassets/videono.imageset/deviceNocamera.pdf differ diff --git a/iOSClient/Images.xcassets/videoyes.imageset/Contents.json b/iOSClient/Images.xcassets/videoyes.imageset/Contents.json new file mode 100644 index 0000000000..bfc956fce2 --- /dev/null +++ b/iOSClient/Images.xcassets/videoyes.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "deviceCamera.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOSClient/Images.xcassets/videoyes.imageset/deviceCamera.pdf b/iOSClient/Images.xcassets/videoyes.imageset/deviceCamera.pdf new file mode 100644 index 0000000000..807d6a30a8 Binary files /dev/null and b/iOSClient/Images.xcassets/videoyes.imageset/deviceCamera.pdf differ diff --git a/iOSClient/Images.xcassets/viewInFolder.imageset/Contents.json b/iOSClient/Images.xcassets/viewInFolder.imageset/Contents.json new file mode 100644 index 0000000000..2ea287530d --- /dev/null +++ b/iOSClient/Images.xcassets/viewInFolder.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "filename" : "viewInFolder-1.pdf", + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "viewInFolderDark.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/viewInFolder.imageset/viewInFolder-1.pdf b/iOSClient/Images.xcassets/viewInFolder.imageset/viewInFolder-1.pdf new file mode 100644 index 0000000000..bb8489ccd9 Binary files /dev/null and b/iOSClient/Images.xcassets/viewInFolder.imageset/viewInFolder-1.pdf differ diff --git a/iOSClient/Images.xcassets/viewInFolder.imageset/viewInFolderDark.pdf b/iOSClient/Images.xcassets/viewInFolder.imageset/viewInFolderDark.pdf new file mode 100644 index 0000000000..1f59694303 Binary files /dev/null and b/iOSClient/Images.xcassets/viewInFolder.imageset/viewInFolderDark.pdf differ diff --git a/iOSClient/Login/NCLogin.storyboard b/iOSClient/Login/NCLogin.storyboard index 981eadcc58..05d3331812 100644 --- a/iOSClient/Login/NCLogin.storyboard +++ b/iOSClient/Login/NCLogin.storyboard @@ -19,14 +19,14 @@ - + - + @@ -36,7 +36,7 @@ - + @@ -58,12 +58,12 @@ + - @@ -73,12 +73,12 @@ - + - + diff --git a/iOSClient/Share/NCShare+Helper.swift b/iOSClient/Share/NCShare+Helper.swift new file mode 100644 index 0000000000..6f98012b78 --- /dev/null +++ b/iOSClient/Share/NCShare+Helper.swift @@ -0,0 +1,114 @@ +// +// NCShare+Helper.swift +// Nextcloud +// +// Created by Henrik Storch on 19.03.22. +// Copyright © 2022 Henrik Storch. All rights reserved. +// +// Author Henrik Storch +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +import UIKit +import NextcloudKit + +extension tableShare: NCTableShareable { } +extension NKShare: NCTableShareable { } + +protocol NCTableShareable: AnyObject { + var shareType: Int { get set } + var permissions: Int { get set } + var idShare: Int { get set } + var shareWith: String { get set } + var hideDownload: Bool { get set } + var password: String { get set } + var label: String { get set } + var note: String { get set } + var expirationDate: NSDate? { get set } + var shareWithDisplayname: String { get set } + var attributes: String? { get set } +} + +extension NCTableShareable { + var expDateString: String? { + guard let date = expirationDate else { return nil } + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "YYYY-MM-dd HH:mm:ss" + return dateFormatter.string(from: date as Date) + } + + func hasChanges(comparedTo other: NCTableShareable) -> Bool { + return other.shareType != shareType + || other.permissions != permissions + || other.hideDownload != hideDownload + || other.password != password + || other.label != label + || other.note != note + || other.expirationDate != expirationDate + } +} + +class NCTableShareOptions: NCTableShareable { + + var shareType: Int + var permissions: Int + + var idShare: Int = 0 + var shareWith: String = "" + + var hideDownload: Bool = false + var password: String = "" + var label: String = "" + var note: String = "" + var expirationDate: NSDate? + var shareWithDisplayname: String = "" + + var attributes: String? + + private init(shareType: Int, metadata: tableMetadata, password: String?) { + if metadata.e2eEncrypted, NCCapabilities.shared.getCapabilities(account: metadata.account).capabilityE2EEApiVersion == NCGlobal.shared.e2eeVersionV12 { + self.permissions = NCPermissions().permissionCreateShare + } else { + self.permissions = NCCapabilities.shared.getCapabilities(account: metadata.account).capabilityFileSharingDefaultPermission & metadata.sharePermissionsCollaborationServices + } + self.shareType = shareType + if let password = password { + self.password = password + } + } + + convenience init(sharee: NKSharee, metadata: tableMetadata, password: String?) { + self.init(shareType: sharee.shareType, metadata: metadata, password: password) + self.shareWith = sharee.shareWith + self.shareWithDisplayname = sharee.label + } + + static func shareLink(metadata: tableMetadata, password: String?) -> NCTableShareOptions { + return NCTableShareOptions(shareType: NCShareCommon().SHARE_TYPE_LINK, metadata: metadata, password: password) + } +} + +protocol NCShareDetail { + var share: NCTableShareable! { get } +} + +extension NCShareDetail where Self: UIViewController { + func setNavigationTitle() { + title = NSLocalizedString("_sharing_", comment: "") + if share.shareType != NCShareCommon().SHARE_TYPE_LINK { + title! = share.shareWithDisplayname.isEmpty ? share.shareWith : share.shareWithDisplayname + } + } +} diff --git a/iOSClient/Share/NCShare+NCCellDelegate.swift b/iOSClient/Share/NCShare+NCCellDelegate.swift index 76c3bf9dc8..412510ed5b 100644 --- a/iOSClient/Share/NCShare+NCCellDelegate.swift +++ b/iOSClient/Share/NCShare+NCCellDelegate.swift @@ -29,10 +29,11 @@ extension NCShare: NCShareLinkCellDelegate, NCShareUserCellDelegate { func copyInternalLink(sender: Any) { guard let metadata = self.metadata else { return } - NCNetworking.shared.readFile(serverUrlFileName: metadata.serverUrlFileName, account: metadata.account) { _, metadata, _, error in + let serverUrlFileName = metadata.serverUrl + "/" + metadata.fileName + NCNetworking.shared.readFile(serverUrlFileName: serverUrlFileName, account: metadata.account) { _, metadata, error in if error == .success, let metadata = metadata { let internalLink = metadata.urlBase + "/index.php/f/" + metadata.fileId - NCShareCommon.copyLink(link: internalLink, viewController: self, sender: sender) + self.shareCommon.copyLink(link: internalLink, viewController: self, sender: sender) } else { NCContentPresenter().showError(error: error) } @@ -43,12 +44,12 @@ extension NCShare: NCShareLinkCellDelegate, NCShareUserCellDelegate { guard let tableShare = tableShare else { return copyInternalLink(sender: sender) } - NCShareCommon.copyLink(link: tableShare.url, viewController: self, sender: sender) + shareCommon.copyLink(link: tableShare.url, viewController: self, sender: sender) } func tapMenu(with tableShare: tableShare?, sender: Any) { if let tableShare = tableShare { - self.toggleShareMenu(for: tableShare, sender: sender) + self.toggleShareMenu(for: tableShare, sendMail: (tableShare.shareType != NCShareCommon().SHARE_TYPE_LINK), folder: metadata?.directory ?? false, sender: sender) } else { self.makeNewLinkShare() } @@ -56,11 +57,12 @@ extension NCShare: NCShareLinkCellDelegate, NCShareUserCellDelegate { func showProfile(with tableShare: tableShare?, sender: Any) { guard let tableShare else { return } - showProfileMenu(userId: tableShare.shareWith, session: session, sender: sender) + showProfileMenu(userId: tableShare.shareWith, session: session) } func quickStatus(with tableShare: tableShare?, sender: Any) { - guard let tableShare, let metadata else { return } - self.toggleQuickPermissionsMenu(isDirectory: metadata.directory, share: tableShare, sender: sender) + guard let tableShare = tableShare, + let metadata = metadata else { return } + self.toggleUserPermissionMenu(isDirectory: metadata.directory, tableShare: tableShare) } } diff --git a/iOSClient/Share/NCShare.storyboard b/iOSClient/Share/NCShare.storyboard index 5bf01c2fb8..0c8a27be32 100644 --- a/iOSClient/Share/NCShare.storyboard +++ b/iOSClient/Share/NCShare.storyboard @@ -1,414 +1,262 @@ - + - - + - - - - - - - - - - - - - - - - - + - + - + - + - + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - + - + - + - - + + - - + + - - + + - - - + + + - + - - + + - - - + + + + - + - - - - + - - - - - - - - - - - + + + + + + + + + + + - - - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + - + - - - - - + + + + + + + + - + - - - + + + + + + + - + - - + + - - + + - - + + - - + + - - - - - - - - - - + - + + + + + + + - - + + - - - - + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + - - + + - - - - - - - - - - - - - - - - - - + + + + + + - + - - - - - - - - - - diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift index f2f73d42a5..ca94bdf118 100644 --- a/iOSClient/Share/NCShare.swift +++ b/iOSClient/Share/NCShare.swift @@ -30,30 +30,32 @@ import NextcloudKit import MarqueeLabel import ContactsUI +enum ShareSection: Int, CaseIterable { + case header + case linkByEmail + case links + case emails +} + class NCShare: UIViewController, NCSharePagingContent { - @IBOutlet weak var viewContainerConstraint: NSLayoutConstraint! - @IBOutlet weak var sharedWithYouByView: UIView! - @IBOutlet weak var sharedWithYouByImage: UIImageView! - @IBOutlet weak var sharedWithYouByLabel: UILabel! - @IBOutlet weak var searchFieldTopConstraint: NSLayoutConstraint! - @IBOutlet weak var searchField: UISearchBar! - var textField: UIView? { searchField } + + var textField: UITextField? { self.view.viewWithTag(Tag.searchField) as? UITextField } @IBOutlet weak var tableView: UITableView! - @IBOutlet weak var btnContact: UIButton! weak var appDelegate = UIApplication.shared.delegate as? AppDelegate public var metadata: tableMetadata! + public var sharingEnabled = true public var height: CGFloat = 0 + let shareCommon = NCShareCommon() let utilityFileSystem = NCUtilityFileSystem() let utility = NCUtility() let database = NCManageDatabase.shared - var shareLinksCount = 0 - var canReshare: Bool { - return ((metadata.sharePermissionsCollaborationServices & NCSharePermissions.permissionReshareShare) != 0) + guard let metadata = metadata else { return true } + return ((metadata.sharePermissionsCollaborationServices & NCPermissions().permissionShareShare) != 0) } var session: NCSession.Session { @@ -62,65 +64,84 @@ class NCShare: UIViewController, NCSharePagingContent { var shares: (firstShareLink: tableShare?, share: [tableShare]?) = (nil, nil) - var capabilities = NKCapabilities.Capabilities() - private var dropDown = DropDown() var networking: NCShareNetworking? + var isCurrentUser: Bool { + if let currentUser = NCManageDatabase.shared.getActiveTableAccount(), currentUser.userId == metadata?.ownerId { + return true + } + return false + } + var shareLinks: [tableShare] = [] + var shareEmails: [tableShare] = [] + var shareOthers: [tableShare] = [] + private var cachedHeader: NCShareAdvancePermissionHeader? + // Stores the next number per share +// var nextLinkNumberByShare: [String: Int] = [:] +// +// // Stores assigned numbers for each link (per share) +// var linkNumbersByShare: [String: [String: Int]] = [:] + +// var shareLinksCount = 0 + // MARK: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() - view.backgroundColor = .systemBackground - - viewContainerConstraint.constant = height - searchFieldTopConstraint.constant = 0 - - searchField.placeholder = NSLocalizedString("_shareLinksearch_placeholder_", comment: "") - searchField.autocorrectionType = .no + view.backgroundColor = .secondarySystemGroupedBackground tableView.dataSource = self tableView.delegate = self tableView.allowsSelection = false - tableView.backgroundColor = .systemBackground - tableView.contentInset = UIEdgeInsets(top: 8, left: 0, bottom: 10, right: 0) + tableView.backgroundColor = .secondarySystemGroupedBackground tableView.register(UINib(nibName: "NCShareLinkCell", bundle: nil), forCellReuseIdentifier: "cellLink") tableView.register(UINib(nibName: "NCShareUserCell", bundle: nil), forCellReuseIdentifier: "cellUser") + tableView.register(UINib(nibName: "NCShareEmailFieldCell", bundle: nil), forCellReuseIdentifier: "NCShareEmailFieldCell") + tableView.register(NCShareEmailLinkHeaderView.self, + forHeaderFooterViewReuseIdentifier: NCShareEmailLinkHeaderView.reuseIdentifier) + tableView.register(CreateLinkFooterView.self, forHeaderFooterViewReuseIdentifier: CreateLinkFooterView.reuseIdentifier) + tableView.register(NoSharesFooterView.self, forHeaderFooterViewReuseIdentifier: NoSharesFooterView.reuseIdentifier) + tableView.register(UINib(nibName: "NCShareAdvancePermissionHeader", bundle: nil), + forHeaderFooterViewReuseIdentifier: NCShareAdvancePermissionHeader.reuseIdentifier) NotificationCenter.default.addObserver(self, selector: #selector(reloadData), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataNCShare), object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(appWillEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(reloadData), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDidCreateShareLink), object: nil) + + guard let metadata = metadata else { return } + +// loadLinkNumberData() + reloadData() - Task { - self.capabilities = await NKCapabilities.shared.getCapabilities(for: metadata.account) - if metadata.e2eEncrypted { - let metadataDirectory = await self.database.getMetadataDirectoryAsync(serverUrl: metadata.serverUrl, account: metadata.account) - if capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV12 || - (capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV20 && metadataDirectory?.e2eEncrypted ?? false) { - searchFieldTopConstraint.constant = -50 - searchField.alpha = 0 - btnContact.alpha = 0 - } - } else { - checkSharedWithYou() - } - - reloadData() - - networking = NCShareNetworking(metadata: metadata, view: self.view, delegate: self, session: session) + networking = NCShareNetworking(metadata: metadata, view: self.view, delegate: self, session: session) + if sharingEnabled { let isVisible = (self.navigationController?.topViewController as? NCSharePaging)?.page == .sharing networking?.readShare(showLoadingIndicator: isVisible) - - searchField.searchTextField.font = .systemFont(ofSize: 14) - searchField.delegate = self } + self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_cancel_", comment: ""), style: .done, target: self, action: #selector(exitTapped)) + navigationItem.largeTitleDisplayMode = .never + } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) +// tableView.reloadData() } + @objc func exitTapped() { + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterUpdateIcons) + self.dismiss(animated: true, completion: nil) + } + func makeNewLinkShare() { guard let advancePermission = UIStoryboard(name: "NCShare", bundle: nil).instantiateViewController(withIdentifier: "NCShareAdvancePermission") as? NCShareAdvancePermission, let navigationController = self.navigationController else { return } - self.checkEnforcedPassword(shareType: NCShareCommon.shareTypeLink) { password in + self.checkEnforcedPassword(shareType: shareCommon.SHARE_TYPE_LINK) { password in advancePermission.networking = self.networking advancePermission.share = TransientShare.shareLink(metadata: self.metadata, password: password) advancePermission.metadata = self.metadata @@ -128,173 +149,509 @@ class NCShare: UIViewController, NCSharePagingContent { } } - // Shared with you by ... - func checkSharedWithYou() { - guard !metadata.ownerId.isEmpty, metadata.ownerId != session.userId else { return } - - if !canReshare { - searchField.isUserInteractionEnabled = false - searchField.alpha = 0.5 - searchField.placeholder = NSLocalizedString("_share_reshare_disabled_", comment: "") - btnContact.isEnabled = false - } - - searchFieldTopConstraint.constant = 45 - sharedWithYouByView.isHidden = false - sharedWithYouByLabel.text = NSLocalizedString("_shared_with_you_by_", comment: "") + " " + metadata.ownerDisplayName - sharedWithYouByImage.image = utility.loadUserImage(for: metadata.ownerId, displayName: metadata.ownerDisplayName, urlBase: session.urlBase) - sharedWithYouByLabel.accessibilityHint = NSLocalizedString("_show_profile_", comment: "") - - let shareAction = UITapGestureRecognizer(target: self, action: #selector(openShareProfile(_:))) - sharedWithYouByImage.addGestureRecognizer(shareAction) - let shareLabelAction = UITapGestureRecognizer(target: self, action: #selector(openShareProfile(_:))) - sharedWithYouByLabel.addGestureRecognizer(shareLabelAction) - - let fileName = NCSession.shared.getFileName(urlBase: session.urlBase, user: metadata.ownerId) - let results = NCManageDatabase.shared.getImageAvatarLoaded(fileName: fileName) - - if results.image == nil { - let etag = self.database.getTableAvatar(fileName: fileName)?.etag - let fileNameLocalPath = utilityFileSystem.createServerUrl(serverUrl: utilityFileSystem.directoryUserData, fileName: fileName) - - NextcloudKit.shared.downloadAvatar( - user: metadata.ownerId, - fileNameLocalPath: fileNameLocalPath, - sizeImage: NCGlobal.shared.avatarSize, - avatarSizeRounded: NCGlobal.shared.avatarSizeRounded, - etagResource: etag, - account: metadata.account) { task in - Task { - let identifier = await NCNetworking.shared.networkingTasks.createIdentifier(account: self.metadata.account, - path: self.metadata.ownerId, - name: "downloadAvatar") - await NCNetworking.shared.networkingTasks.track(identifier: identifier, task: task) - } - } completion: { _, imageAvatar, _, etag, _, error in - if error == .success, let etag = etag, let imageAvatar = imageAvatar { - self.database.addAvatar(fileName: fileName, etag: etag) - self.sharedWithYouByImage.image = imageAvatar - self.reloadData() - } else if error.errorCode == NCGlobal.shared.errorNotModified, let imageAvatar = self.database.setAvatarLoaded(fileName: fileName) { - self.sharedWithYouByImage.image = imageAvatar + // MARK: - Notification Center + + @objc func openShareProfile() { + guard let metadata = metadata else { return } + self.showProfileMenu(userId: metadata.ownerId, session: session) + } + + private func scrollToTopIfNeeded() { + if tableView.numberOfSections > 0 && tableView.numberOfRows(inSection: 0) > 0 { + self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false) + } + } + + @objc func keyboardWillShow(notification: Notification) { + if UIDevice.current.userInterfaceIdiom == .phone { + if UIScreen.main.bounds.width < 374 || UIDevice.current.orientation.isLandscape { + if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue { + if view.frame.origin.y == 0 { + scrollToTopIfNeeded() + self.view.frame.origin.y -= keyboardSize.height } } + } else if UIScreen.main.bounds.height < 850 { + if view.frame.origin.y == 0 { + scrollToTopIfNeeded() + self.view.frame.origin.y -= 70 + } + } else { + if view.frame.origin.y == 0 { + scrollToTopIfNeeded() + self.view.frame.origin.y -= 40 + } + } } - reloadData() + if UIDevice.current.userInterfaceIdiom == .pad, UIDevice.current.orientation.isLandscape { + if view.frame.origin.y == 0 { + if tableView.numberOfSections > 0 && tableView.numberOfRows(inSection: 0) > 0 { + self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false) + } + self.view.frame.origin.y -= 230 + } + } + + textField?.layer.borderColor = NCBrandColor.shared.brand.cgColor } - // MARK: - Notification Center + + @objc func keyboardWillHide(notification: Notification) { + if view.frame.origin.y != 0 { + self.view.frame.origin.y = 0 + } + textField?.layer.borderColor = NCBrandColor.shared.label.cgColor + } - @objc func openShareProfile(_ sender: UITapGestureRecognizer) { - self.showProfileMenu(userId: metadata.ownerId, session: session, sender: sender.view) + @objc func appWillEnterForeground(notification: Notification) { + reloadData() } + +// @objc private func handleShareCountsUpdate(notification: Notification) { +// guard let userInfo = notification.userInfo, +// let links = userInfo["links"] as? Int, +// let emails = userInfo["emails"] as? Int else { return } +// +// if let header = tableView.headerView(forSection: ShareSection.header.rawValue) as? NCShareAdvancePermissionHeader { +// header.setupUI(with: metadata, +// linkCount: links, +// emailCount: emails) +// } else { +// let headerSection = IndexSet(integer: ShareSection.header.rawValue) +// tableView.reloadSections(headerSection, with: .none) +// } +// } // MARK: - @objc func reloadData() { + guard let metadata = metadata else { + return + } +// shares = (nil, nil) // reset shares = self.database.getTableShares(metadata: metadata) - shareLinksCount = 0 + updateShareArrays() tableView.reloadData() } + + func updateShareArrays() { + shareLinks.removeAll() + shareEmails.removeAll() - // MARK: - IBAction + guard var allShares = shares.share else { return } - @IBAction func searchFieldDidEndOnExit(textField: UITextField) { - // https://stackoverflow.com/questions/25471114/how-to-validate-an-e-mail-address-in-swift - func isValidEmail(_ email: String) -> Bool { + if let firstLink = shares.firstShareLink { + // Remove if already exists to avoid duplication + allShares.removeAll { $0.idShare == firstLink.idShare } + allShares.insert(firstLink, at: 0) + } - let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}" - let emailPred = NSPredicate(format: "SELF MATCHES %@", emailRegEx) - return emailPred.evaluate(with: email) + shares.share = allShares + + for item in allShares { + if item.shareType == shareCommon.SHARE_TYPE_LINK { + shareLinks.append(item) + } else { + shareEmails.append(item) + } } + } + + +// func updateShareArrays() { +// shareLinks.removeAll() +// shareEmails.removeAll() +// +// var allShares = shares.share ?? [] +// +// if let firstLink = shares.firstShareLink { +// if let idx = allShares.firstIndex(where: { $0.idShare == firstLink.idShare }) { +// allShares.remove(at: idx) // only one removal +// } +// allShares.insert(firstLink, at: 0) +// } +// +// shares.share = allShares +// +// for item in allShares { +// if item.shareType == shareCommon.SHARE_TYPE_LINK { +// shareLinks.append(item) +// } else { +// shareEmails.append(item) +// } +// } +// } + + + + +// func updateShareArrays() { +// shareLinks.removeAll() +// shareEmails.removeAll() +// +// if let shareLink = shares.firstShareLink { +// shares.share?.insert(shareLink, at: 0) +// } +// +// guard let allShares = shares.share else { return } +// +//// // Use current shareId as the scope +//// let shareId = metadata?.ocId ?? "0" +//// +//// // Ensure storage exists for this share +//// if nextLinkNumberByShare[shareId] == nil { +//// nextLinkNumberByShare[shareId] = 1 +//// linkNumbersByShare[shareId] = [:] +//// } +// +// for item in allShares { +// if item.shareType == shareCommon.SHARE_TYPE_LINK { +// shareLinks.append(item) +// } else { +// shareEmails.append(item) +// } +// } +// +//// // Sort links by assigned number (per-share) +//// shareLinks.sort { lhs, rhs in +//// let lhsNum = linkNumbersByShare[shareId]?[String(lhs.idShare)] ?? 0 +//// let rhsNum = linkNumbersByShare[shareId]?[String(rhs.idShare)] ?? 0 +//// return lhsNum < rhsNum +//// } +//// +//// // ✅ If this share has no links, reset numbering for it +//// if shareLinks.isEmpty { +//// linkNumbersByShare[shareId] = [:] +//// nextLinkNumberByShare[shareId] = 1 +//// saveLinkNumberData() +//// } +// +//// NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataNCShare, +//// userInfo: ["links": shareLinks.count, +//// "emails": shareEmails.count]) +// } + +// // MARK: - Persistence +// func saveLinkNumberData() { +// // Save both maps as UserDefaults property lists +// UserDefaults.standard.set(linkNumbersByShare, forKey: "linkNumbersByShare") +// UserDefaults.standard.set(nextLinkNumberByShare, forKey: "nextLinkNumberByShare") +// } +// +// func loadLinkNumberData() { +// if let savedMap = UserDefaults.standard.dictionary(forKey: "linkNumbersByShare") as? [String: [String: Int]] { +// linkNumbersByShare = savedMap +// } else { +// linkNumbersByShare = [:] +// } +// +// if let savedNext = UserDefaults.standard.dictionary(forKey: "nextLinkNumberByShare") as? [String: Int] { +// nextLinkNumberByShare = savedNext +// } else { +// nextLinkNumberByShare = [:] +// } +// } +// +// // MARK: - Number Assignment +// +// // Assign number to a link (or reuse existing) +// func assignLinkNumber(forShare shareId: String, linkId: String) -> Int { +// if nextLinkNumberByShare[shareId] == nil { +// nextLinkNumberByShare[shareId] = 1 +// linkNumbersByShare[shareId] = [:] +// } +// +// if let number = linkNumbersByShare[shareId]?[linkId] { +// return number +// } +// +// let nextNum = nextLinkNumberByShare[shareId]! +// linkNumbersByShare[shareId]?[linkId] = nextNum +// nextLinkNumberByShare[shareId]! += 1 +// return nextNum +// } +// +// func removeLink(forShare shareId: String, linkId: String) { +// linkNumbersByShare[shareId]?.removeValue(forKey: linkId) +// +// if linkNumbersByShare[shareId]?.isEmpty ?? true { +// linkNumbersByShare[shareId] = [:] +// nextLinkNumberByShare[shareId] = 1 +// } +// } + + + +// func updateShareArrays() { +// shareLinks.removeAll() +// shareEmails.removeAll() +// +// if let shareLink = shares.firstShareLink { +// shares.share?.insert(shareLink, at: 0) +// } +// +// guard let allShares = shares.share else { return } +// +// // Use current shareId as the scope +// let shareId = metadata?.ocId ?? "0" +// +// // Ensure storage exists for this share +// if nextLinkNumberByShare[shareId] == nil { +// nextLinkNumberByShare[shareId] = 1 +// linkNumbersByShare[shareId] = [:] +// } +// +// for item in allShares { +// if item.shareType == shareCommon.SHARE_TYPE_LINK { +// let linkId = String(item.idShare) +// +// // Assign a number if missing +// if linkNumbersByShare[shareId]?[linkId] == nil { +// let nextNum = nextLinkNumberByShare[shareId] ?? 1 +// linkNumbersByShare[shareId]?[linkId] = nextNum +// nextLinkNumberByShare[shareId] = nextNum + 1 +// saveLinkNumberData() +// } +//// if item.shareType == shareCommon.SHARE_TYPE_LINK { shareLinksCount += 1 } +// +// shareLinks.append(item) +// } else { +// shareEmails.append(item) +// } +// } +// +// // Sort links by assigned number (per-share) +// shareLinks.sort { lhs, rhs in +// let lhsNum = linkNumbersByShare[shareId]?[String(lhs.idShare)] ?? 0 +// let rhsNum = linkNumbersByShare[shareId]?[String(rhs.idShare)] ?? 0 +// return lhsNum < rhsNum +// } +// +// // ✅ If this share has no links, reset numbering for it +// if shareLinks.isEmpty { +// linkNumbersByShare[shareId] = [:] +// nextLinkNumberByShare[shareId] = 1 +// saveLinkNumberData() +// } +// +//// NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataNCShare, +//// userInfo: ["links": shareLinks.count, +//// "emails": shareEmails.count]) +// } +// +// // MARK: - Persistence +// func saveLinkNumberData() { +// // Save both maps as UserDefaults property lists +// UserDefaults.standard.set(linkNumbersByShare, forKey: "linkNumbersByShare") +// UserDefaults.standard.set(nextLinkNumberByShare, forKey: "nextLinkNumberByShare") +// } +// +// func loadLinkNumberData() { +// if let savedMap = UserDefaults.standard.dictionary(forKey: "linkNumbersByShare") as? [String: [String: Int]] { +// linkNumbersByShare = savedMap +// } else { +// linkNumbersByShare = [:] +// } +// +// if let savedNext = UserDefaults.standard.dictionary(forKey: "nextLinkNumberByShare") as? [String: Int] { +// nextLinkNumberByShare = savedNext +// } else { +// nextLinkNumberByShare = [:] +// } +// } +// +// // MARK: - Number Assignment +// +// // Assign number to a link (or reuse existing) +// func assignLinkNumber(forShare shareId: String, linkId: String) -> Int { +// if nextLinkNumberByShare[shareId] == nil { +// nextLinkNumberByShare[shareId] = 1 +// linkNumbersByShare[shareId] = [:] +// } +// +// if let number = linkNumbersByShare[shareId]?[linkId] { +// return number +// } +// +// let nextNum = nextLinkNumberByShare[shareId]! +// linkNumbersByShare[shareId]?[linkId] = nextNum +// nextLinkNumberByShare[shareId]! += 1 +// return nextNum +// } +// +// func removeLink(forShare shareId: String, linkId: String) { +// linkNumbersByShare[shareId]?.removeValue(forKey: linkId) +// +// if linkNumbersByShare[shareId]?.isEmpty ?? true { +// linkNumbersByShare[shareId] = [:] +// nextLinkNumberByShare[shareId] = 1 +// } +// } + + // MARK: - IBAction + + @IBAction func searchFieldDidEndOnExit(textField: UITextField) { guard let searchString = textField.text, !searchString.isEmpty else { return } - if searchString.contains("@"), !isValidEmail(searchString) { return } + if searchString.contains("@"), !utility.validateEmail(searchString) { return } networking?.getSharees(searchString: searchString) } + + @IBAction func searchFieldDidChange(textField: UITextField) { + NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(searchSharees), object: nil) + guard let searchString = textField.text else {return} + if searchString.count == 0 { + dropDown.hide() + } else { +// networking?.getSharees(searchString: searchString) + perform(#selector(searchSharees), with: nil, afterDelay: 0.5) + } + } + +// @objc private func searchSharees() { +// // https://stackoverflow.com/questions/25471114/how-to-validate-an-e-mail-address-in-swift +// func isValidEmail(_ email: String) -> Bool { +// +// let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}" +// let emailPred = NSPredicate(format: "SELF MATCHES %@", emailRegEx) +// return emailPred.evaluate(with: email) +// } +// guard let searchString = textField?.text, !searchString.isEmpty else { return } +// if searchString.contains("@"), !isValidEmail(searchString) { return } +// networking?.getSharees(searchString: searchString) +// } + + @IBAction func createLinkClicked(_ sender: Any?) { + appDelegate?.adjust.trackEvent(TriggerEvent(CreateLink.rawValue)) + TealiumHelper.shared.trackEvent(title: "magentacloud-app.sharing.create", data: ["": ""]) +// self.touchUpInsideButtonMenu(sender) + self.touchUpInsideButtonMenu(sender as Any) + } + + @IBAction func touchUpInsideButtonMenu(_ sender: Any) { + + guard let metadata = metadata else { return } + let isFilesSharingPublicPasswordEnforced = NCCapabilities.Capabilities().capabilityFileSharingPubPasswdEnforced + let shares = NCManageDatabase.shared.getTableShares(metadata: metadata) + + if isFilesSharingPublicPasswordEnforced && shares.firstShareLink == nil { + let alertController = UIAlertController(title: NSLocalizedString("_enforce_password_protection_", comment: ""), message: "", preferredStyle: .alert) + alertController.addTextField { (textField) in + textField.isSecureTextEntry = true + } + alertController.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .default) { (action:UIAlertAction) in }) + let okAction = UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default) {[weak self] (action:UIAlertAction) in + let password = alertController.textFields?.first?.text + self?.networking?.createShareLink(password: password ?? "") + } + + alertController.addAction(okAction) + + present(alertController, animated: true, completion:nil) + } else if shares.firstShareLink == nil { + networking?.createShareLink(password: "") + } else { + networking?.createShareLink(password: "") + } + + } - func checkEnforcedPassword(shareType: Int, completion: @escaping (String?) -> Void) { - guard capabilities.fileSharingPubPasswdEnforced, - shareType == NCShareCommon.shareTypeLink || shareType == NCShareCommon.shareTypeEmail - else { return completion(nil) } - - self.present(UIAlertController.password(titleKey: "_enforce_password_protection_", completion: completion), animated: true) + private func createShareAndReload(password: String) { + networking?.createShareLink(password: password) + + // Delay to wait for DB update or async API completion + DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { + self.reloadData() + } } + @IBAction func selectContactClicked(_ sender: Any) { let cnPicker = CNContactPickerViewController() cnPicker.delegate = self cnPicker.displayedPropertyKeys = [CNContactEmailAddressesKey] cnPicker.predicateForEnablingContact = NSPredicate(format: "emailAddresses.@count > 0") cnPicker.predicateForSelectionOfProperty = NSPredicate(format: "emailAddresses.@count > 0") + self.present(cnPicker, animated: true) } + + func checkEnforcedPassword(shareType: Int, completion: @escaping (String?) -> Void) { + guard NCCapabilities.Capabilities().capabilityFileSharingPubPasswdEnforced, + shareType == shareCommon.SHARE_TYPE_LINK || shareType == shareCommon.SHARE_TYPE_EMAIL + else { return completion(nil) } + + self.present(UIAlertController.password(titleKey: "_enforce_password_protection_", completion: completion), animated: true) + } } -// MARK: - NCShareNetworkingDelegate + // MARK: - NCShareNetworkingDelegate extension NCShare: NCShareNetworkingDelegate { func readShareCompleted() { NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataNCShare) - reloadData() +// self.reloadData() } func shareCompleted() { - NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataNCShare) - reloadData() +// NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataNCShare) +// self.reloadData() + // Allow DB async save to finish before reload + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { + self.reloadData() + } } func unShareCompleted() { - reloadData() +// NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataNCShare) + // Same buffer for consistency + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { + self.reloadData() + } } +// func unShareCompleted() { +// DispatchQueue.main.async { +// self.reloadData() +// } +// } func updateShareWithError(idShare: Int) { - reloadData() + self.reloadData() } func getSharees(sharees: [NKSharee]?) { - guard let sharees else { - return - } - - // close keyboard - self.view.endEditing(true) + guard let sharees else { return } dropDown = DropDown() let appearance = DropDown.appearance() - // Setting up the blur effect - let blurEffect = UIBlurEffect(style: .light) // You can choose .dark, .extraLight, or .light - let blurEffectView = UIVisualEffectView(effect: blurEffect) - blurEffectView.frame = CGRect(x: 0, y: 0, width: 500, height: 20) - - appearance.backgroundColor = .systemBackground + appearance.backgroundColor = .secondarySystemGroupedBackground appearance.cornerRadius = 10 - appearance.shadowColor = .black - appearance.shadowOpacity = 0.2 - appearance.shadowRadius = 30 + appearance.shadowColor = UIColor(white: 0.5, alpha: 1) + appearance.shadowOpacity = 0.9 + appearance.shadowRadius = 25 appearance.animationduration = 0.25 appearance.textColor = .darkGray - - let account = NCManageDatabase.shared.getTableAccount(account: metadata.account) - let existingShares = NCManageDatabase.shared.getTableShares(metadata: metadata) + appearance.setupMaskedCorners([.layerMaxXMaxYCorner, .layerMinXMaxYCorner]) for sharee in sharees { - if sharee.shareWith == account?.user { continue } // do not show your own account - if let shares = existingShares.share, shares.contains(where: {$0.shareWith == sharee.shareWith}) { continue } // do not show already existing sharees - if metadata.ownerDisplayName == sharee.shareWith { continue } // do not show owner of the share var label = sharee.label - if sharee.shareType == NCShareCommon.shareTypeTeam { + if sharee.shareType == shareCommon.SHARE_TYPE_CIRCLE { label += " (\(sharee.circleInfo), \(sharee.circleOwner))" } - dropDown.dataSource.append(label) } - dropDown.anchorView = searchField - dropDown.bottomOffset = CGPoint(x: 10, y: searchField.bounds.height) - dropDown.width = searchField.bounds.width - 20 - dropDown.direction = .bottom + dropDown.anchorView = textField + dropDown.bottomOffset = CGPoint(x: 0, y: textField?.bounds.height ?? 0) + dropDown.width = textField?.bounds.width ?? 0 + if (UIDevice.current.userInterfaceIdiom == .phone || UIDevice.current.orientation.isLandscape), UIScreen.main.bounds.width < 1111 { + dropDown.topOffset = CGPoint(x: 0, y: -(textField?.bounds.height ?? 0)) + dropDown.direction = .top + } else { + dropDown.bottomOffset = CGPoint(x: 0, y: (textField?.bounds.height ?? 0) - 80) + dropDown.direction = .any + } dropDown.cellNib = UINib(nibName: "NCSearchUserDropDownCell", bundle: nil) dropDown.customCellConfiguration = { (index: Index, _, cell: DropDownCell) in @@ -304,6 +661,8 @@ extension NCShare: NCShareNetworkingDelegate { } dropDown.selectionAction = { index, _ in + self.textField?.text = "" + self.textField?.resignFirstResponder() let sharee = sharees[index] guard let advancePermission = UIStoryboard(name: "NCShare", bundle: nil).instantiateViewController(withIdentifier: "NCShareAdvancePermission") as? NCShareAdvancePermission, @@ -327,6 +686,19 @@ extension NCShare: NCShareNetworkingDelegate { func downloadLimitSet(to limit: Int, by token: String) { database.createDownloadLimit(account: metadata.account, count: 0, limit: limit, token: token) } + + func checkIsCollaboraFile() -> Bool { + guard let metadata = metadata else { + return false + } + + // EDITORS + let editors = utility.editorsDirectEditing(account: metadata.account, contentType: metadata.contentType) + let availableRichDocument = utility.isTypeFileRichDocument(metadata) + + // RichDocument: Collabora + return (availableRichDocument && editors.count == 0) + } } // MARK: - UITableViewDelegate @@ -334,8 +706,25 @@ extension NCShare: NCShareNetworkingDelegate { extension NCShare: UITableViewDelegate { func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return 60 + guard let sectionType = ShareSection(rawValue: indexPath.section) else { return 0 } + + switch sectionType { + case .header: + return 210 + + case .linkByEmail: + let isPad = UIDevice.current.userInterfaceIdiom == .pad + if isCurrentUser { + return 130 + } else { + return isPad ? (canReshare ? 200 : 220) : 220 + } + + case .links, .emails: + return 60 + } } + } // MARK: - UITableViewDataSource @@ -343,104 +732,192 @@ extension NCShare: UITableViewDelegate { extension NCShare: UITableViewDataSource { func numberOfSections(in tableView: UITableView) -> Int { - return 2 + ShareSection.allCases.count } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - var numRows = shares.share?.count ?? 0 - if section == 0 { - if metadata.e2eEncrypted, capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV12 { - numRows = 1 - } else { - // don't allow link creation if reshare is disabled - numRows = shares.firstShareLink != nil || canReshare ? 2 : 1 - } + guard let sectionType = ShareSection(rawValue: section) else { return 0 } + + switch sectionType { + case .header: + return 0 + case .linkByEmail: + return 1 + case .links: + return shareLinks.count + case .emails: + return shareEmails.count } - return numRows } 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() } + guard let sectionType = ShareSection(rawValue: indexPath.section) else { return UITableViewCell() } + + switch sectionType { + case .header: + return UITableViewCell() // Empty row + case .linkByEmail: + guard let cell = tableView.dequeueReusableCell(withIdentifier: "NCShareEmailFieldCell", for: indexPath) as? NCShareEmailFieldCell else { + return UITableViewCell() + } + cell.searchField.addTarget(self, action: #selector(searchFieldDidEndOnExit(textField:)), for: .editingDidEndOnExit) + cell.searchField.addTarget(self, action: #selector(searchFieldDidChange(textField:)), for: .editingChanged) + cell.btnContact.addTarget(self, action: #selector(selectContactClicked(_:)), for: .touchUpInside) + cell.setupCell(with: metadata) + return cell + + case .links: + let tableShare = shareLinks[indexPath.row] + guard let cell = tableView.dequeueReusableCell(withIdentifier: "cellLink", for: indexPath) as? NCShareLinkCell else { + return UITableViewCell() + } cell.delegate = self - if metadata.e2eEncrypted, capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV12 { - cell.tableShare = shares.firstShareLink + if indexPath.row == 0 { + cell.configure(with: tableShare, at: indexPath, isDirectory: metadata.directory, title: "") } else { - if indexPath.row == 0 { - cell.isInternalLink = true - } else if shares.firstShareLink?.isInvalidated != true { - cell.tableShare = shares.firstShareLink - } + let linkNumber = " \(indexPath.row + 1)" + cell.configure(with: tableShare, at: indexPath, isDirectory: metadata.directory, title: linkNumber) } - cell.isDirectory = metadata.directory - cell.setupCellUI() - shareLinksCount += 1 + return cell + + case .emails: + let tableShare = shareEmails[indexPath.row] + guard let cell = tableView.dequeueReusableCell(withIdentifier: "cellUser", for: indexPath) as? NCShareUserCell else { + return UITableViewCell() + } + cell.delegate = self + cell.configure(with: tableShare, at: indexPath, isDirectory: metadata.directory, userId: session.userId) return cell } + } - guard let tableShare = shares.share?[indexPath.row] else { return UITableViewCell() } + func numberOfRows(in section: Int) -> Int { + return tableView(tableView, numberOfRowsInSection: section) + } + + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + guard let sectionType = ShareSection(rawValue: section) else { return nil } + + switch sectionType { + case .header: + let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: NCShareAdvancePermissionHeader.reuseIdentifier) as! NCShareAdvancePermissionHeader + headerView.ocId = metadata.ocId + headerView.setupUI(with: metadata, linkCount: shareLinks.count, emailCount: shareEmails.count) + return headerView + + case .linkByEmail: + return nil + + case .links: + if isCurrentUser || canReshare { + let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "NCShareEmailLinkHeaderView") as! NCShareEmailLinkHeaderView + headerView.configure(text: NSLocalizedString("_share_copy_link_", comment: "")) + return headerView + } + return nil - // LINK, EMAIL - if tableShare.shareType == NCShareCommon.shareTypeLink || tableShare.shareType == NCShareCommon.shareTypeEmail { - if let cell = tableView.dequeueReusableCell(withIdentifier: "cellLink", for: indexPath) as? NCShareLinkCell { - cell.indexPath = indexPath - cell.tableShare = tableShare - cell.isDirectory = metadata.directory - cell.delegate = self - cell.setupCellUI(titleAppendString: String(shareLinksCount)) - if tableShare.shareType == NCShareCommon.shareTypeLink { shareLinksCount += 1 } - return cell + case .emails: + if (isCurrentUser || canReshare) && numberOfRows(in: section) > 0 { + let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "NCShareEmailLinkHeaderView") as! NCShareEmailLinkHeaderView + headerView.configure(text: NSLocalizedString("_share_shared_with_", comment: "")) + return headerView } - } else { - // USER / GROUP etc. - if let cell = tableView.dequeueReusableCell(withIdentifier: "cellUser", for: indexPath) as? NCShareUserCell { - cell.indexPath = indexPath - cell.tableShare = tableShare - cell.isDirectory = metadata.directory - cell.delegate = self - cell.setupCellUI(userId: session.userId, session: session, metadata: metadata) - - return cell + return nil + } + } + + func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + guard let sectionType = ShareSection(rawValue: section) else { return 0 } + + switch sectionType { + case .header: + return 190 + case .linkByEmail: + return 0 + case .links: + return (isCurrentUser || canReshare) ? 44 : 0 + case .emails: + return ((isCurrentUser || canReshare) && numberOfRows(in: section) > 0) ? 44 : 0 + } + } + + func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { + guard isCurrentUser || canReshare, + let sectionType = ShareSection(rawValue: section) else { + return nil + } + + switch sectionType { + case .links: + let footer = tableView.dequeueReusableHeaderFooterView(withIdentifier: CreateLinkFooterView.reuseIdentifier) as! CreateLinkFooterView + footer.createButtonAction = { [weak self] in + self?.createLinkClicked(nil) + } + return footer + + case .emails: + if numberOfRows(in: section) == 0 { + return tableView.dequeueReusableHeaderFooterView(withIdentifier: NoSharesFooterView.reuseIdentifier) } + return nil + case .header, .linkByEmail: + return nil + } + } + + func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { + guard isCurrentUser || canReshare, + let sectionType = ShareSection(rawValue: section) else { + return 0.001 } - return UITableViewCell() + switch sectionType { + case .links: + return 80 + case .emails: + return numberOfRows(in: section) == 0 ? 100 : 80 + case .header, .linkByEmail: + return 0.001 + } } + + } -// MARK: - CNContactPickerDelegate +//MARK: CNContactPickerDelegate extension NCShare: CNContactPickerDelegate { func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) { if contact.emailAddresses.count > 1 { - showEmailList(arrEmail: contact.emailAddresses.map({$0.value as String}), sender: picker) + showEmailList(arrEmail: contact.emailAddresses.map({$0.value as String})) } else if let email = contact.emailAddresses.first?.value as? String { - searchField?.text = email + textField?.text = email networking?.getSharees(searchString: email) } } - - func showEmailList(arrEmail: [String], sender: Any?) { + + func contactPickerDidCancel(_ picker: CNContactPickerViewController) { + self.keyboardWillHide(notification: Notification(name: Notification.Name("dismiss"))) + } + + func showEmailList(arrEmail: [String]) { var actions = [NCMenuAction]() for email in arrEmail { actions.append( NCMenuAction( title: email, - icon: utility.loadImage(named: "email", colors: [NCBrandColor.shared.iconImageColor]), + icon: utility.loadImage(named: "email").imageColor(NCBrandColor.shared.brandElement), selected: false, on: false, - sender: sender, action: { _ in - self.searchField?.text = email + self.textField?.text = email self.networking?.getSharees(searchString: email) } ) ) } DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { - self.presentMenu(with: actions, sender: sender) + self.presentMenu(with: actions) } } } @@ -449,25 +926,27 @@ extension NCShare: CNContactPickerDelegate { extension NCShare: UISearchBarDelegate { func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { - NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(searchSharees(_:)), object: nil) + NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(searchSharees), object: nil) if searchText.isEmpty { dropDown.hide() } else { - perform(#selector(searchSharees(_:)), with: nil, afterDelay: 1) + perform(#selector(searchSharees), with: nil, afterDelay: 0.5) } } - @objc private func searchSharees(_ sender: Any?) { - // https://stackoverflow.com/questions/25471114/how-to-validate-an-e-mail-address-in-swift + @objc private func searchSharees() { +// // https://stackoverflow.com/questions/25471114/how-to-validate-an-e-mail-address-in-swift func isValidEmail(_ email: String) -> Bool { +// let emailRegEx = "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-\\u00a1-\\uffff]+\\.[A-Za-z\\u00a1-\\uffff]{2,64}$" let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}" let emailPred = NSPredicate(format: "SELF MATCHES %@", emailRegEx) return emailPred.evaluate(with: email) } - guard let searchString = searchField.text, !searchString.isEmpty else { return } - if searchString.contains("@"), !isValidEmail(searchString) { return } + guard let searchString = textField?.text, !searchString.isEmpty else { return } + if searchString.contains("@"), !utility.validateEmail(searchString) { return } networking?.getSharees(searchString: searchString) } + } diff --git a/iOSClient/Share/NCShareCommentsCell.swift b/iOSClient/Share/NCShareCommentsCell.swift index 59cdf78c81..b537f6559d 100644 --- a/iOSClient/Share/NCShareCommentsCell.swift +++ b/iOSClient/Share/NCShareCommentsCell.swift @@ -54,8 +54,9 @@ class NCShareCommentsCell: UITableViewCell, NCCellProtocol { override func awakeFromNib() { super.awakeFromNib() - let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapAvatarImage(_:))) + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapAvatarImage)) imageItem?.addGestureRecognizer(tapGesture) + buttonMenu.setImage(UIImage(named: "shareMenu")!.image(color: .lightGray, size: 50), for: .normal) } @objc func tapAvatarImage(_ sender: UITapGestureRecognizer) { diff --git a/iOSClient/Share/NCShareCommon.swift b/iOSClient/Share/NCShareCommon.swift index 9d920adf7d..9b05aea1a1 100644 --- a/iOSClient/Share/NCShareCommon.swift +++ b/iOSClient/Share/NCShareCommon.swift @@ -23,26 +23,27 @@ import UIKit import DropDown -enum NCShareCommon { - static let shareTypeUser = 0 - static let shareTypeGroup = 1 - static let shareTypeLink = 3 - static let shareTypeEmail = 4 - static let shareTypeContact = 5 - static let shareTypeFederated = 6 - static let shareTypeTeam = 7 - static let shareTypeGuest = 8 - static let shareTypeFederatedGroup = 9 - static let shareTypeRoom = 10 +class NCShareCommon: NSObject { - static let itemTypeFile = "file" - static let itemTypeFolder = "folder" + // swiftlint:disable identifier_name + let SHARE_TYPE_USER = 0 + let SHARE_TYPE_GROUP = 1 + let SHARE_TYPE_LINK = 3 + let SHARE_TYPE_EMAIL = 4 + let SHARE_TYPE_CONTACT = 5 + let SHARE_TYPE_REMOTE = 6 + let SHARE_TYPE_CIRCLE = 7 + let SHARE_TYPE_GUEST = 8 + let SHARE_TYPE_REMOTE_GROUP = 9 + let SHARE_TYPE_ROOM = 10 + // swiftlint:enable identifier_name + + func createLinkAvatar(imageName: String, colorCircle: UIColor) -> UIImage? { - static func createLinkAvatar(imageName: String, colorCircle: UIColor) -> UIImage? { let size: CGFloat = 200 let bottomImage = UIImage(named: "circle_fill")!.image(color: colorCircle, size: size / 2) - let topImage = NCUtility().loadImage(named: imageName, colors: [NCBrandColor.shared.iconImageColor]) + let topImage = UIImage(named: imageName)!.image(color: .white, size: size / 2) UIGraphicsBeginImageContextWithOptions(CGSize(width: size, height: size), false, UIScreen.main.scale) bottomImage.draw(in: CGRect(origin: CGPoint.zero, size: CGSize(width: size, height: size))) topImage.draw(in: CGRect(origin: CGPoint(x: size / 4, y: size / 4), size: CGSize(width: size / 2, height: size / 2))) @@ -52,7 +53,7 @@ enum NCShareCommon { return image } - static func copyLink(link: String, viewController: UIViewController, sender: Any) { + func copyLink(link: String, viewController: UIViewController, sender: Any) { let objectsToShare = [link] let activityViewController = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil) @@ -68,31 +69,74 @@ enum NCShareCommon { } } - static func getImageShareType(shareType: Int) -> UIImage? { - + func getImageShareType(shareType: Int, isDropDown:Bool = false) -> UIImage? { + switch shareType { - case NCShareCommon.shareTypeUser: - return UIImage(named: "shareTypeUser")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) - case NCShareCommon.shareTypeGroup: - return UIImage(named: "shareTypeGroup")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) - case NCShareCommon.shareTypeLink: - return UIImage(named: "shareTypeLink")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) - case NCShareCommon.shareTypeEmail: - return UIImage(named: "shareTypeEmail")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) - case NCShareCommon.shareTypeContact: - return UIImage(named: "shareTypeUser")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) - case NCShareCommon.shareTypeFederated: - return UIImage(named: "shareTypeUser")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) - case NCShareCommon.shareTypeTeam: - return UIImage(named: "shareTypeTeam")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) - case NCShareCommon.shareTypeGuest: - return UIImage(named: "shareTypeUser")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) - case NCShareCommon.shareTypeFederatedGroup: - return UIImage(named: "shareTypeGroup")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) - case NCShareCommon.shareTypeRoom: - return UIImage(named: "shareTypeRoom")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) + case SHARE_TYPE_USER: + return UIImage(named: "shareTypeEmail")?.imageColor(NCBrandColor.shared.label) + case self.SHARE_TYPE_GROUP: + return UIImage(named: "shareTypeGroup")?.imageColor(NCBrandColor.shared.label) + case self.SHARE_TYPE_LINK: + return UIImage(named: "shareTypeLink")?.imageColor(NCBrandColor.shared.label) + case self.SHARE_TYPE_EMAIL: + return UIImage(named: isDropDown ? "email" : "shareTypeUser")?.imageColor(NCBrandColor.shared.label) + case self.SHARE_TYPE_CONTACT: + return UIImage(named: "shareTypeUser")?.imageColor(NCBrandColor.shared.label) + case self.SHARE_TYPE_REMOTE: + return UIImage(named: isDropDown ? "shareTypeUser" : "shareTypeEmail")?.imageColor(NCBrandColor.shared.label) + case self.SHARE_TYPE_CIRCLE: + return UIImage(named: "shareTypeCircles")?.imageColor(NCBrandColor.shared.label) + case self.SHARE_TYPE_GUEST: + return UIImage(named: "shareTypeUser")?.imageColor(NCBrandColor.shared.label) + case self.SHARE_TYPE_REMOTE_GROUP: + return UIImage(named: "shareTypeGroup")?.imageColor(NCBrandColor.shared.label) + case self.SHARE_TYPE_ROOM: + return UIImage(named: "shareTypeRoom")?.imageColor(NCBrandColor.shared.label) default: - return UIImage(named: "shareTypeUser")?.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal) + return UIImage(named: "shareTypeUser")?.imageColor(NCBrandColor.shared.label) + } + } + + func isLinkShare(shareType: Int) -> Bool { + return shareType == SHARE_TYPE_LINK + } + + func isExternalUserShare(shareType: Int) -> Bool { + return shareType == SHARE_TYPE_EMAIL + } + + func isInternalUser(shareType: Int) -> Bool { + return shareType == SHARE_TYPE_USER + } + + func isFileTypeAllowedForEditing(fileExtension: String, shareType: Int) -> Bool { + if fileExtension == "md" || fileExtension == "txt" { + return true + } else { + return isInternalUser(shareType: shareType) } } + + func isEditingEnabled(isDirectory: Bool, fileExtension: String, shareType: Int) -> Bool { + if !isDirectory {//file + return isFileTypeAllowedForEditing(fileExtension: fileExtension, shareType: shareType) + } else { + return true + } + } + + func isFileDropOptionVisible(isDirectory: Bool, shareType: Int) -> Bool { + return (isDirectory && (isLinkShare(shareType: shareType) || isExternalUserShare(shareType: shareType))) + } + + func isCurrentUserIsFileOwner(fileOwnerId: String) -> Bool { + if let currentUser = NCManageDatabase.shared.getActiveTableAccount(), currentUser.userId == fileOwnerId { + return true + } + return false + } + + func canReshare(withPermission permission: String) -> Bool { + return permission.contains(NCPermissions().permissionCanShare) + } } diff --git a/iOSClient/Share/NCShareEmailFieldCell.swift b/iOSClient/Share/NCShareEmailFieldCell.swift new file mode 100644 index 0000000000..7b8643fe08 --- /dev/null +++ b/iOSClient/Share/NCShareEmailFieldCell.swift @@ -0,0 +1,175 @@ +// +// NCShareEmailFieldCell.swift +// Nextcloud +// +// Created by A200020526 on 01/06/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +import UIKit +import MarqueeLabel +import NextcloudKit + +enum Tag { + static let searchField = 999 +} + +class NCShareEmailFieldCell: UITableViewCell { + + @IBOutlet weak var searchField: UITextField! + @IBOutlet weak var labelOrLink: UILabel! + @IBOutlet weak var btnContact: UIButton! + @IBOutlet weak var labelSeparator1: UILabel! + @IBOutlet weak var labelSeparator2: UILabel! + @IBOutlet weak var labelSendLinkByMail: UILabel! + @IBOutlet weak var labelSharedWithBy: UILabel! + @IBOutlet weak var labelResharingAllowed: UILabel! + @IBOutlet weak var topConstraintResharingView: NSLayoutConstraint! + @IBOutlet weak var viewOrLinkSeparator: UIView! + + var ocId = "" + + override func awakeFromNib() { + super.awakeFromNib() + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + } + + func setupCell(with metadata: tableMetadata) { + contentView.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + ocId = metadata.ocId + + configureSearchField() + configureContactButton() + configureLabels() + updateCanReshareUI() + + setNeedsLayout() + layoutIfNeeded() + } + + private func configureSearchField() { + searchField.layer.cornerRadius = 5 + searchField.layer.masksToBounds = true + searchField.layer.borderWidth = 1 + searchField.layer.borderColor = NCBrandColor.shared.label.cgColor + searchField.text = "" + searchField.textColor = NCBrandColor.shared.label + searchField.attributedPlaceholder = NSAttributedString( + string: NSLocalizedString("_shareLinksearch_placeholder_", comment: ""), + attributes: [.foregroundColor: NCBrandColor.shared.gray60] + ) + searchField.tag = Tag.searchField + setDoneButton(sender: searchField) + } + + private func configureContactButton() { + btnContact.layer.cornerRadius = 5 + btnContact.layer.masksToBounds = true + btnContact.layer.borderWidth = 1 + btnContact.layer.borderColor = NCBrandColor.shared.label.cgColor + btnContact.tintColor = NCBrandColor.shared.label + let contactImage = NCUtility().loadImage(named: "contact").image(color: NCBrandColor.shared.label, size: 24) + btnContact.setImage(contactImage, for: .normal) + } + + private func configureLabels() { + labelOrLink.text = NSLocalizedString("_share_or_", comment: "") + labelSendLinkByMail.text = NSLocalizedString("_share_send_link_by_mail_", comment: "") + labelSharedWithBy.text = NSLocalizedString("_share_received_shares_text_", comment: "") + labelResharingAllowed.text = NSLocalizedString("_share_reshare_allowed_", comment: "") + + labelSendLinkByMail.textColor = NCBrandColor.shared.label + labelSharedWithBy.textColor = NCBrandColor.shared.label + labelResharingAllowed.textColor = NCBrandColor.shared.label + } + + func updateCanReshareUI() { + guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return } + + let isCurrentUser = NCShareCommon().isCurrentUserIsFileOwner(fileOwnerId: metadata.ownerId) + let canReshare = (metadata.sharePermissionsCollaborationServices & NCPermissions().permissionShareShare) != 0 + + labelSharedWithBy.isHidden = isCurrentUser + labelResharingAllowed.isHidden = isCurrentUser + + if !canReshare { + searchField.isUserInteractionEnabled = false + searchField.alpha = 0.5 + btnContact.isEnabled = false + btnContact.alpha = 0.5 + } + + if !isCurrentUser { + let ownerName = metadata.ownerDisplayName + let fullText = NSLocalizedString("_share_received_shares_text_", comment: "") + " " + ownerName + let attributed = NSMutableAttributedString(string: fullText) + + if let range = fullText.range(of: ownerName) { + let nsRange = NSRange(range, in: fullText) + attributed.addAttribute(.font, value: UIFont.boldSystemFont(ofSize: 16), range: nsRange) + } + + labelSharedWithBy.attributedText = attributed + labelSharedWithBy.numberOfLines = 0 + + labelResharingAllowed.text = canReshare + ? NSLocalizedString("_share_reshare_allowed_", comment: "") + : NSLocalizedString("_share_reshare_not_allowed_", comment: "") + + topConstraintResharingView.constant = 15 + } else { + topConstraintResharingView.constant = 0 + } + + viewOrLinkSeparator.isHidden = !canReshare + } + + func updateShareUI(ocId: String, count: Int) { + guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return } + + let isCurrentUser = NCShareCommon().isCurrentUserIsFileOwner(fileOwnerId: metadata.ownerId) + let canReshare = (metadata.sharePermissionsCollaborationServices & NCPermissions().permissionShareShare) != 0 + + if !isCurrentUser { + if canReshare { + labelOrLink.isHidden = true + labelSeparator1.isHidden = true + labelSeparator2.isHidden = true + } + } + } + + @objc func cancelDatePicker() { + self.searchField.endEditing(true) + } + + private func setDoneButton(sender: UITextField) { + let toolbar = UIToolbar() + toolbar.sizeToFit() + let doneButton = UIBarButtonItem( + title: NSLocalizedString("_done_", comment: ""), + style: .plain, + target: self, + action: #selector(cancelDatePicker) + ) + let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) + toolbar.setItems([space, doneButton], animated: false) + sender.inputAccessoryView = toolbar + } + + @IBAction func touchUpInsideFavorite(_ sender: UIButton) { + // Hook for favorite action if needed + } + + @IBAction func touchUpInsideDetails(_ sender: UIButton) { + // Hook for toggling detail visibility if needed + } + + @objc func longTap(_ sender: UIGestureRecognizer) { + let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_copied_path_") + NCContentPresenter().showInfo(error: error) + } +} diff --git a/iOSClient/Share/NCShareEmailFieldCell.xib b/iOSClient/Share/NCShareEmailFieldCell.xib new file mode 100644 index 0000000000..cfeb42cc45 --- /dev/null +++ b/iOSClient/Share/NCShareEmailFieldCell.xib @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iOSClient/Share/NCShareEmailLinkHeaderView.swift b/iOSClient/Share/NCShareEmailLinkHeaderView.swift new file mode 100644 index 0000000000..9502164891 --- /dev/null +++ b/iOSClient/Share/NCShareEmailLinkHeaderView.swift @@ -0,0 +1,43 @@ +// +// NCShareEmailLinkHeaderView.swift +// Nextcloud +// +// Created by A106551118 on 12/08/25. +// Copyright © 2025 Marino Faggiana. All rights reserved. +// + +import UIKit + +class NCShareEmailLinkHeaderView: UITableViewHeaderFooterView { + private let label = UILabel() + static let reuseIdentifier = "NCShareEmailLinkHeaderView" + + override init(reuseIdentifier: String?) { + super.init(reuseIdentifier: reuseIdentifier) + setup() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setup() + } + + private func setup() { + contentView.backgroundColor = .clear + label.translatesAutoresizingMaskIntoConstraints = false + label.font = .systemFont(ofSize: 17, weight: .semibold) + label.textColor = NCBrandColor.shared.textColor + contentView.addSubview(label) + + NSLayoutConstraint.activate([ + label.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 20), + label.heightAnchor.constraint(equalToConstant: 30), + label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 15), + label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -15), + ]) + } + + func configure(text: String) { + label.text = text + } +} diff --git a/iOSClient/Share/NCShareHeader.swift b/iOSClient/Share/NCShareHeader.swift index 3d38815179..c484c88592 100644 --- a/iOSClient/Share/NCShareHeader.swift +++ b/iOSClient/Share/NCShareHeader.swift @@ -1,5 +1,5 @@ // -// NCShareHeader.swift +// NCShareAdvancePermissionHeader.swift // Nextcloud // // Created by T-systems on 10/08/21. @@ -22,52 +22,113 @@ // import UIKit -import TagListView -class NCShareHeader: UIView { +class NCShareAdvancePermissionHeader: UITableViewHeaderFooterView { @IBOutlet weak var imageView: UIImageView! @IBOutlet weak var fileName: UILabel! @IBOutlet weak var info: UILabel! + @IBOutlet weak var favorite: UIButton! @IBOutlet weak var fullWidthImageView: UIImageView! - @IBOutlet weak var fileNameTopConstraint: NSLayoutConstraint! - @IBOutlet weak var tagListView: TagListView! - private var heightConstraintWithImage: NSLayoutConstraint? - private var heightConstraintWithoutImage: NSLayoutConstraint? + static let reuseIdentifier = "NCShareAdvancePermissionHeader" + var ocId = "" + let utility = NCUtility() + let utilityFileSystem = NCUtilityFileSystem() + func setupUI(with metadata: tableMetadata) { - let utilityFileSystem = NCUtilityFileSystem() - if let image = NCUtility().getImage(ocId: metadata.ocId, etag: metadata.etag, ext: NCGlobal.shared.previewExt1024, userId: metadata.userId, urlBase: metadata.urlBase) { + backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + fileName.textColor = NCBrandColor.shared.label + info.textColor = NCBrandColor.shared.textInfo + + let isShare = metadata.permissions.contains(NCPermissions().permissionShared) + + if let image = NCUtility().getImage(ocId: metadata.ocId, etag: metadata.etag, ext: NCGlobal.shared.previewExt1024) { fullWidthImageView.image = image fullWidthImageView.contentMode = .scaleAspectFill - imageView.image = fullWidthImageView.image imageView.isHidden = true } else { - if metadata.directory { - imageView.image = metadata.e2eEncrypted ? NCImageCache.shared.getFolderEncrypted(account: metadata.account) : NCImageCache.shared.getFolder(account: metadata.account) + imageView.isHidden = false + if metadata.e2eEncrypted { + imageView.image = NCImageCache.shared.getFolderEncrypted() + } else if isShare { + imageView.image = NCImageCache.shared.getFolderSharedWithMe() + } else if !metadata.shareType.isEmpty { + imageView.image = metadata.shareType.contains(3) + ? NCImageCache.shared.getFolderPublic() + : NCImageCache.shared.getFolderSharedWithMe() + } else if metadata.directory { + imageView.image = NCImageCache.shared.getFolder() } else if !metadata.iconName.isEmpty { imageView.image = NCUtility().loadImage(named: metadata.iconName, useTypeIconFile: true, account: metadata.account) } else { imageView.image = NCImageCache.shared.getImageFile() } - - fileNameTopConstraint.constant -= 45 } fileName.text = metadata.fileNameView - fileName.textColor = NCBrandColor.shared.textColor - info.textColor = NCBrandColor.shared.textColor2 - info.text = utilityFileSystem.transformedSize(metadata.size) + ", " + NCUtility().getRelativeDateTitle(metadata.date as Date) + fileName.textColor = NCBrandColor.shared.fileFolderName - tagListView.addTags(Array(metadata.tags)) - - setNeedsLayout() - layoutIfNeeded() + updateFavoriteIcon(isFavorite: metadata.favorite) + info.text = utilityFileSystem.transformedSize(metadata.size) + ", " + utility.getRelativeDateTitle(metadata.date as Date) } + + func setupUI(with metadata: tableMetadata, linkCount: Int, emailCount: Int) { + contentView.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + fileName.textColor = NCBrandColor.shared.label + info.textColor = NCBrandColor.shared.textInfo + +// let isShare = metadata.permissions.contains(NCPermissions().permissionShared) + let hasShares = (linkCount > 0 || emailCount > 0) + + if let image = NCUtility().getImage(ocId: metadata.ocId, + etag: metadata.etag, + ext: NCGlobal.shared.previewExt1024) { + fullWidthImageView.image = image + fullWidthImageView.contentMode = .scaleAspectFill + imageView.isHidden = true + } else { + imageView.isHidden = false + if metadata.e2eEncrypted { + imageView.image = NCImageCache.shared.getFolderEncrypted() + } else if hasShares { + imageView.image = NCImageCache.shared.getFolderSharedWithMe() + } else if !metadata.shareType.isEmpty { + imageView.image = metadata.shareType.contains(3) + ? NCImageCache.shared.getFolderPublic() + : NCImageCache.shared.getFolderSharedWithMe() + } else if metadata.directory { + imageView.image = NCImageCache.shared.getFolder() + } else if !metadata.iconName.isEmpty { + imageView.image = NCUtility().loadImage(named: metadata.iconName, + useTypeIconFile: true, + account: metadata.account) + } else { + imageView.image = NCImageCache.shared.getImageFile() + } + } + + fileName.text = metadata.fileNameView + fileName.textColor = NCBrandColor.shared.fileFolderName - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - if fullWidthImageView.image != nil { - imageView.isHidden = traitCollection.verticalSizeClass != .compact + updateFavoriteIcon(isFavorite: metadata.favorite) + info.text = utilityFileSystem.transformedSize(metadata.size) + ", " + utility.getRelativeDateTitle(metadata.date as Date) + } + + private func updateFavoriteIcon(isFavorite: Bool) { + let color = isFavorite ? NCBrandColor.shared.yellowFavorite : NCBrandColor.shared.textInfo + favorite.setImage(utility.loadImage(named: "star.fill", colors: [color], size: 24), for: .normal) + } + + @IBAction func touchUpInsideFavorite(_ sender: UIButton) { + guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return } + NCNetworking.shared.favoriteMetadata(metadata) { error in + if error == .success { + guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(metadata.ocId) else { return } + self.updateFavoriteIcon(isFavorite: metadata.favorite) + } else { + NCContentPresenter().showError(error: error) + } } } } diff --git a/iOSClient/Share/NCShareHeader.xib b/iOSClient/Share/NCShareHeader.xib index 55ffce6cab..69ae9e03bd 100644 --- a/iOSClient/Share/NCShareHeader.xib +++ b/iOSClient/Share/NCShareHeader.xib @@ -1,131 +1,128 @@ - - + + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + - - + + - - - - - - - - - - + + + diff --git a/iOSClient/Share/NCShareHeaderView.xib b/iOSClient/Share/NCShareHeaderView.xib index 44b83d3fc7..b7384fb2ec 100644 --- a/iOSClient/Share/NCShareHeaderView.xib +++ b/iOSClient/Share/NCShareHeaderView.xib @@ -1,149 +1,176 @@ - + - - + - - + + - - + + - - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + - + - - - - - - - - - - - - - - - + + diff --git a/iOSClient/Share/NCShareLinkCell.swift b/iOSClient/Share/NCShareLinkCell.swift index 8f42838e6c..d70df0a755 100644 --- a/iOSClient/Share/NCShareLinkCell.swift +++ b/iOSClient/Share/NCShareLinkCell.swift @@ -23,22 +23,27 @@ import UIKit class NCShareLinkCell: UITableViewCell { - @IBOutlet private weak var imageItem: UIImageView! - @IBOutlet private weak var labelTitle: UILabel! - @IBOutlet private weak var descriptionLabel: UILabel! + @IBOutlet weak var labelTitle: UILabel! + @IBOutlet weak var buttonDetail: UIButton! + @IBOutlet weak var buttonCopy: UIButton! + @IBOutlet weak var btnQuickStatus: UIButton! + @IBOutlet weak var imagePermissionType: UIImageView! + @IBOutlet weak var imageExpiredDateSet: UIImageView! + @IBOutlet weak var imagePasswordSet: UIImageView! + @IBOutlet weak var imageAllowedPermission: UIImageView! + @IBOutlet weak var imageRightArrow: UIImageView! @IBOutlet weak var labelQuickStatus: UILabel! - @IBOutlet weak var statusStackView: UIStackView! - @IBOutlet private weak var menuButton: UIButton! - @IBOutlet private weak var copyButton: UIButton! - @IBOutlet weak var imageDownArrow: UIImageView! + @IBOutlet weak var leadingContraintofImageRightArrow: NSLayoutConstraint! + + private let iconShareSize: CGFloat = 200 - var tableShare: tableShare? - var isDirectory = false weak var delegate: NCShareLinkCellDelegate? + + var tableShare: tableShare? var isInternalLink = false + var isDirectory = false var indexPath = IndexPath() - let utility = NCUtility() override func prepareForReuse() { super.prepareForReuse() @@ -46,83 +51,87 @@ class NCShareLinkCell: UITableViewCell { tableShare = nil } - func setupCellUI(titleAppendString: String? = nil) { - var menuImageName = "ellipsis" + override func awakeFromNib() { + super.awakeFromNib() + setupCellAppearance() + } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + if previousTraitCollection?.userInterfaceStyle != traitCollection.userInterfaceStyle { + setupCellAppearance() + } + } - menuButton.isHidden = isInternalLink - descriptionLabel.isHidden = !isInternalLink - copyButton.isHidden = !isInternalLink && tableShare == nil - statusStackView.isHidden = isInternalLink + func configure(with share: tableShare?, at indexPath: IndexPath, isDirectory: Bool, title: String) { + self.tableShare = share + self.indexPath = indexPath + self.isDirectory = isDirectory + setupCellAppearance(titleAppendString: title) - copyButton.setImage(UIImage(systemName: "doc.on.doc")?.withTintColor(.label, renderingMode: .alwaysOriginal), for: .normal) - copyButton.accessibilityLabel = NSLocalizedString("_copy_", comment: "") +// let shareLinksCountString = shareLinksCount > 0 ? String(shareLinksCount) : "" +// setupCellAppearance(titleAppendString: shareLinksCountString) +// setupCellAppearance(titleAppendString: String(shareLinksCount)) + } - menuButton.accessibilityLabel = NSLocalizedString("_more_", comment: "") - menuButton.accessibilityIdentifier = "showShareLinkDetails" + private func setupCellAppearance(titleAppendString: String? = nil) { + contentView.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + labelTitle.textColor = NCBrandColor.shared.label + labelQuickStatus.textColor = NCBrandColor.shared.shareBlueColor - if isInternalLink { - labelTitle.text = NSLocalizedString("_share_internal_link_", comment: "") - descriptionLabel.text = NSLocalizedString("_share_internal_link_des_", comment: "") - imageItem.image = NCUtility().loadImage(named: "square.and.arrow.up.circle.fill", colors: [NCBrandColor.shared.iconImageColor2]) - } else { - labelTitle.text = NSLocalizedString("_share_link_", comment: "") + buttonDetail.setTitleColor(NCBrandColor.shared.shareBlackColor, for: .normal) + buttonCopy.setImage(UIImage(named: "share")?.image(color: NCBrandColor.shared.brand, size: 24), for: .normal) - if let titleAppendString { - labelTitle.text?.append(" (\(titleAppendString))") - } + imageRightArrow.image = UIImage(named: "rightArrow")?.imageColor(NCBrandColor.shared.shareBlueColor) + imageExpiredDateSet.image = UIImage(named: "calenderNew")?.imageColor(NCBrandColor.shared.shareBlueColor) + imagePasswordSet.image = UIImage(named: "lockNew")?.imageColor(NCBrandColor.shared.shareBlueColor) - if let tableShare = tableShare { - if !tableShare.label.isEmpty { - labelTitle.text? += " (\(tableShare.label))" - } + buttonDetail.setTitle(NSLocalizedString("_share_details_", comment: ""), for: .normal) + labelTitle.text = NSLocalizedString("_share_link_", comment: "") + + if let tableShare = tableShare, let titleAppendString { + if !tableShare.label.isEmpty { + labelTitle.text? += " (\(tableShare.label))" } else { - menuImageName = "plus" - menuButton.accessibilityLabel = NSLocalizedString("_add_", comment: "") - menuButton.accessibilityIdentifier = "addShareLink" + labelTitle.text?.append(" \(titleAppendString)") } - - imageItem.image = NCUtility().loadImage(named: "link.circle.fill", colors: [NCBrandColor.shared.getElement(account: tableShare?.account)]) - menuButton.setImage(NCUtility().loadImage(named: menuImageName, colors: [NCBrandColor.shared.iconImageColor]), for: .normal) } + updatePermissionUI() + } - labelTitle.textColor = NCBrandColor.shared.textColor - - statusStackView.isHidden = true + private func updatePermissionUI() { + guard let tableShare = tableShare else { return } - if let tableShare { - statusStackView.isHidden = false - labelQuickStatus.text = NSLocalizedString("_custom_permissions_", comment: "") + let permissions = NCPermissions() - if NCSharePermissions.canEdit(tableShare.permissions, isDirectory: isDirectory) { // Can edit - labelQuickStatus.text = NSLocalizedString("_share_editing_", comment: "") - } - if NCSharePermissions.getPermissionValue(canRead: false, canCreate: true, canEdit: false, canDelete: false, canShare: false, isDirectory: isDirectory) == tableShare.permissions { // File request - labelQuickStatus.text = NSLocalizedString("_share_file_drop_", comment: "") - } - if NCSharePermissions.getPermissionValue(canCreate: false, canEdit: false, canDelete: false, canShare: true, isDirectory: isDirectory) == tableShare.permissions { // Read only - labelQuickStatus.text = NSLocalizedString("_share_read_only_", comment: "") - } - - if tableShare.shareType == NCShareCommon.shareTypeEmail { - labelTitle.text = tableShare.shareWithDisplayname - imageItem.image = NCUtility().loadImage(named: "envelope.circle.fill", colors: [NCBrandColor.shared.getElement(account: tableShare.account)]) - } + if tableShare.permissions == permissions.permissionCreateShare { + labelQuickStatus.text = NSLocalizedString("_share_quick_permission_everyone_can_just_upload_", comment: "") + imagePermissionType.image = UIImage(named: "upload")?.imageColor(NCBrandColor.shared.shareBlueColor) + } else if permissions.isAnyPermissionToEdit(tableShare.permissions) { + labelQuickStatus.text = NSLocalizedString("_share_quick_permission_everyone_can_edit_", comment: "") + imagePermissionType.image = UIImage(named: "editNew")?.imageColor(NCBrandColor.shared.shareBlueColor) + } else { + labelQuickStatus.text = NSLocalizedString("_share_quick_permission_everyone_can_only_view_", comment: "") + imagePermissionType.image = UIImage(named: "showPasswordNew")?.imageColor(NCBrandColor.shared.shareBlueColor) } - statusStackView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(openQuickStatus))) - labelQuickStatus.textColor = NCBrandColor.shared.customer - imageDownArrow.image = utility.loadImage(named: "arrowtriangle.down.circle", colors: [NCBrandColor.shared.customer]) + imagePasswordSet.isHidden = tableShare.password.isEmpty + imageExpiredDateSet.isHidden = (tableShare.expirationDate == nil) + + leadingContraintofImageRightArrow.constant = (imagePasswordSet.isHidden && imageExpiredDateSet.isHidden) ? 0 : 5 } - @IBAction func touchUpCopy(_ sender: Any) { + // MARK: - Actions + + @IBAction func touchUpInsideCopy(_ sender: Any) { delegate?.tapCopy(with: tableShare, sender: sender) } - @IBAction func touchUpMenu(_ sender: Any) { + @IBAction func touchUpInsideDetail(_ sender: Any) { delegate?.tapMenu(with: tableShare, sender: sender) } - @objc func openQuickStatus(_ sender: UITapGestureRecognizer) { + @IBAction func quickStatusClicked(_ sender: UIButton) { delegate?.quickStatus(with: tableShare, sender: sender) } } diff --git a/iOSClient/Share/NCShareLinkCell.xib b/iOSClient/Share/NCShareLinkCell.xib index d5810a5294..9783995c5e 100755 --- a/iOSClient/Share/NCShareLinkCell.xib +++ b/iOSClient/Share/NCShareLinkCell.xib @@ -1,149 +1,152 @@ - + - - - + - - + + - - + + - - + + + + + + - - - - + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + - + - - - - - - - - - - - - - + + + + diff --git a/iOSClient/Share/NCShareNavigationTitleSetting.swift b/iOSClient/Share/NCShareNavigationTitleSetting.swift index 9804dea108..b2c8866ee1 100644 --- a/iOSClient/Share/NCShareNavigationTitleSetting.swift +++ b/iOSClient/Share/NCShareNavigationTitleSetting.swift @@ -18,7 +18,7 @@ extension NCShareNavigationTitleSetting where Self: UIViewController { func setNavigationTitle() { title = NSLocalizedString("_share_", comment: "") + " – " - if share.shareType == NCShareCommon.shareTypeLink { + if share.shareType == NCShareCommon().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/NCShareNetworking.swift b/iOSClient/Share/NCShareNetworking.swift index 1fe339f505..935c9e61e9 100644 --- a/iOSClient/Share/NCShareNetworking.swift +++ b/iOSClient/Share/NCShareNetworking.swift @@ -36,32 +36,32 @@ class NCShareNetworking: NSObject { self.view = view self.delegate = delegate self.session = session - super.init() } - private func readDownloadLimit(account: String, token: String) async throws -> NKDownloadLimit? { - return try await withCheckedThrowingContinuation { continuation in - NextcloudKit.shared.getDownloadLimit(account: account, token: token) { limit, error in - if error != .success { - continuation.resume(throwing: error.error) - return - } else { - continuation.resume(returning: limit) - } - } - } - } - - func readDownloadLimits(account: String, tokens: [String]) async throws { - for token in tokens { - self.database.deleteDownloadLimit(byAccount: account, shareToken: token) - if let downloadLimit = try await readDownloadLimit(account: account, token: token) { - self.database.createDownloadLimit(account: account, count: downloadLimit.count, limit: downloadLimit.limit, token: token) - } - } - } - +// private func readDownloadLimit(account: String, token: String) async throws -> NKDownloadLimit? { +// return try await withCheckedThrowingContinuation { continuation in +// NextcloudKit.shared.getDownloadLimit(account: account, token: token) { limit, error in +// if error != .success { +// continuation.resume(throwing: error.error) +// return +// } else { +// continuation.resume(returning: limit) +// } +// } +// } +// } +// +// func readDownloadLimits(account: String, tokens: [String]) async throws { +// for token in tokens { +// self.database.deleteDownloadLimit(byAccount: account, shareToken: token) +// if let downloadLimit = try await readDownloadLimit(account: account, token: token) { +// self.database.createDownloadLimit(account: account, count: downloadLimit.count, limit: downloadLimit.limit, token: token) +// } +// } +// } + + // MARK: - Read func readShare(showLoadingIndicator: Bool) { if showLoadingIndicator { NCActivityIndicator.shared.start(backgroundView: view) @@ -69,26 +69,13 @@ class NCShareNetworking: NSObject { let filenamePath = utilityFileSystem.getFileNamePath(metadata.fileName, serverUrl: metadata.serverUrl, session: session) let parameter = NKShareParameter(path: filenamePath) - NextcloudKit.shared.readShares(parameters: parameter, account: metadata.account) { task in - Task { - let identifier = await NCNetworking.shared.networkingTasks.createIdentifier(account: self.metadata.account, - path: filenamePath, - name: "readShares") - await NCNetworking.shared.networkingTasks.track(identifier: identifier, task: task) - } - } completion: { account, shares, _, error in + NextcloudKit.shared.readShares(parameters: parameter, account: metadata.account) { account, shares, _, error in if error == .success, let shares = shares { self.database.deleteTableShare(account: account, path: "/" + filenamePath) let home = self.utilityFileSystem.getHomeServer(session: self.session) self.database.addShare(account: self.metadata.account, home: home, shares: shares) - NextcloudKit.shared.getGroupfolders(account: account) { task in - Task { - let identifier = await NCNetworking.shared.networkingTasks.createIdentifier(account: account, - name: "getGroupfolders") - await NCNetworking.shared.networkingTasks.track(identifier: identifier, task: task) - } - } completion: { account, results, _, error in + NextcloudKit.shared.getGroupfolders(account: account) { account, results, _, error in if showLoadingIndicator { NCActivityIndicator.shared.stop() } @@ -97,11 +84,8 @@ class NCShareNetworking: NSObject { } Task { - try? await self.readDownloadLimits(account: account, tokens: shares.map(\.token)) - - Task { @MainActor in - self.delegate?.readShareCompleted() - } + try await self.readDownloadLimits(account: account, tokens: shares.map(\.token)) + self.delegate?.readShareCompleted() } } } else { @@ -114,28 +98,50 @@ class NCShareNetworking: NSObject { } } - func createShare(_ shareable: Shareable, downloadLimit: DownloadLimitViewModel) { + // MARK: - Create Share Link + func createShareLink(password: String?) { NCActivityIndicator.shared.start(backgroundView: view) let filenamePath = utilityFileSystem.getFileNamePath(metadata.fileName, serverUrl: metadata.serverUrl, session: session) - let capabilities = NCNetworking.shared.capabilities[self.metadata.account] ?? NKCapabilities.Capabilities() - - NextcloudKit.shared.createShare(path: filenamePath, - shareType: shareable.shareType, - shareWith: shareable.shareWith, - publicUpload: false, - note: shareable.note, - hideDownload: false, - password: shareable.password, - permissions: shareable.permissions, - attributes: shareable.attributes, - account: metadata.account) { task in - Task { - let identifier = await NCNetworking.shared.networkingTasks.createIdentifier(account: self.metadata.account, - path: filenamePath, - name: "createShare") - await NCNetworking.shared.networkingTasks.track(identifier: identifier, task: task) + + NextcloudKit.shared.createShareLink(path: filenamePath, account: metadata.account) { [weak self] account, share, _, error in + guard let self = self else { return } + NCActivityIndicator.shared.stop() + + if error == .success, let share = share { + let home = self.utilityFileSystem.getHomeServer(session: self.session) + self.database.addShare(account: self.metadata.account, home: home, shares: [share]) + + if !self.metadata.contentType.contains("directory") { + AnalyticsHelper.shared.trackEventWithMetadata(eventName: .EVENT__SHARE_FILE, metadata: self.metadata) + } + + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDidCreateShareLink) + // 🔄 ensure we sync DB + UI with server + self.readShare(showLoadingIndicator: false) + } else { + NCContentPresenter().showError(error: error) } - } completion: { _, share, _, error in + + self.delegate?.shareCompleted() + } + } + + // MARK: - Create Share (user/email/group) + func createShare(_ shareable: Shareable, downloadLimit: DownloadLimitViewModel) { + NCActivityIndicator.shared.start(backgroundView: view) + let filenamePath = utilityFileSystem.getFileNamePath(metadata.fileName, serverUrl: metadata.serverUrl, session: session) + + NextcloudKit.shared.createShare( + path: filenamePath, + shareType: shareable.shareType, + shareWith: shareable.shareWith, + password: shareable.password, + note: shareable.note, + permissions: shareable.permissions, + attributes: shareable.attributes, + account: metadata.account + ) { [weak self] _, share, _, error in + guard let self = self else { return } NCActivityIndicator.shared.stop() if error == .success, let share = share { @@ -143,23 +149,29 @@ class NCShareNetworking: NSObject { let home = self.utilityFileSystem.getHomeServer(session: self.session) self.database.addShare(account: self.metadata.account, home: home, shares: [share]) + let directory = self.metadata.directory + if shareable.hasChanges(comparedTo: share) { self.updateShare(shareable, downloadLimit: downloadLimit) // Download limit update should happen implicitly on share update. } else { - if case let .limited(limit, _) = downloadLimit, - capabilities.fileSharingDownloadLimit, - shareable.shareType == NCShareCommon.shareTypeLink, - shareable.itemType == NCShareCommon.itemTypeFile { - self.setShareDownloadLimit(limit, token: share.token) + if share.shareType == NCShareCommon().SHARE_TYPE_LINK && !directory { + if case let .limited(limit, _) = downloadLimit, NCCapabilities.shared.getCapabilities(account: self.metadata.account).capabilityFileSharingDownloadLimit { + self.setShareDownloadLimit(limit, token: share.token) + } } } - Task { - await NCNetworking.shared.transferDispatcher.notifyAllDelegates { delegate in - delegate.transferRequestData(serverUrl: self.metadata.serverUrl) - } + if !self.metadata.contentType.contains("directory") { + AnalyticsHelper.shared.trackEventWithMetadata(eventName: .EVENT__SHARE_FILE, metadata: self.metadata) } + + NotificationCenter.default.postOnMainThread( + name: NCGlobal.shared.notificationCenterUpdateShare, + userInfo: ["account": self.metadata.account, "serverUrl": self.metadata.serverUrl] + ) + // 🔄 ensure consistency + self.readShare(showLoadingIndicator: false) } else { NCContentPresenter().showError(error: error) } @@ -168,67 +180,75 @@ class NCShareNetworking: NSObject { } } + // MARK: - Unshare func unShare(idShare: Int) { NCActivityIndicator.shared.start(backgroundView: view) - NextcloudKit.shared.deleteShare(idShare: idShare, account: metadata.account) { task in - Task { - let identifier = await NCNetworking.shared.networkingTasks.createIdentifier(account: self.metadata.account, - path: "_\(idShare)", - name: "deleteShare") - await NCNetworking.shared.networkingTasks.track(identifier: identifier, task: task) - } - } completion: { account, _, error in + NextcloudKit.shared.deleteShare(idShare: idShare, account: metadata.account) { [weak self] account, _, error in + guard let self = self else { return } NCActivityIndicator.shared.stop() if error == .success { self.database.deleteTableShare(account: account, idShare: idShare) self.delegate?.unShareCompleted() - Task { - await NCNetworking.shared.transferDispatcher.notifyAllDelegates { delegate in - delegate.transferRequestData(serverUrl: self.metadata.serverUrl) - } - } + NotificationCenter.default.postOnMainThread( + name: NCGlobal.shared.notificationCenterUpdateShare, + userInfo: ["account": self.metadata.account, "serverUrl": self.metadata.serverUrl] + ) + // 🔄 reload to avoid missing/duplicate shares + self.readShare(showLoadingIndicator: false) } else { NCContentPresenter().showError(error: error) } } } + // MARK: - Update Share func updateShare(_ shareable: Shareable, downloadLimit: DownloadLimitViewModel) { NCActivityIndicator.shared.start(backgroundView: view) - NextcloudKit.shared.updateShare(idShare: shareable.idShare, password: shareable.password, expireDate: shareable.formattedDateString, permissions: shareable.permissions, note: shareable.note, label: shareable.label, hideDownload: shareable.hideDownload, attributes: shareable.attributes, account: metadata.account) { task in - Task { - let identifier = await NCNetworking.shared.networkingTasks.createIdentifier(account: self.metadata.account, - path: "_\(shareable.idShare)", - name: "updateShare") - await NCNetworking.shared.networkingTasks.track(identifier: identifier, task: task) - } - } completion: { _, share, _, error in + NextcloudKit.shared.updateShare( + idShare: shareable.idShare, + password: shareable.password, + expireDate: shareable.formattedDateString, + permissions: shareable.permissions, + note: shareable.note, + label: shareable.label, + hideDownload: shareable.hideDownload, + attributes: shareable.attributes, + account: metadata.account + ) { [weak self] _, share, _, error in + guard let self = self else { return } NCActivityIndicator.shared.stop() if error == .success, let share = share { let home = self.utilityFileSystem.getHomeServer(session: self.session) - let capabilities = NCNetworking.shared.capabilities[self.metadata.account] ?? NKCapabilities.Capabilities() - self.database.addShare(account: self.metadata.account, home: home, shares: [share]) self.delegate?.readShareCompleted() - if capabilities.fileSharingDownloadLimit, - shareable.shareType == NCShareCommon.shareTypeLink, - shareable.itemType == NCShareCommon.itemTypeFile { - if case let .limited(limit, _) = downloadLimit { - self.setShareDownloadLimit(limit, token: share.token) - } else { - self.removeShareDownloadLimit(token: share.token) - } - } - - Task { - await NCNetworking.shared.transferDispatcher.notifyAllDelegates { delegate in - delegate.transferRequestData(serverUrl: self.metadata.serverUrl) + let directory = self.metadata.directory + +// if capabilities.fileSharingDownloadLimit, +// shareable.shareType == NCShareCommon.shareTypeLink, +// shareable.itemType == NCShareCommon.itemTypeFile { + if share.shareType == NCShareCommon().SHARE_TYPE_LINK && !directory{ + if NCCapabilities.shared.getCapabilities(account: self.metadata.account).capabilityFileSharingDownloadLimit { + if case let .limited(limit, _) = downloadLimit { + self.setShareDownloadLimit(limit, token: share.token) + } else { + self.removeShareDownloadLimit(token: share.token) + } } } + + NotificationCenter.default.postOnMainThread( + name: NCGlobal.shared.notificationCenterUpdateShare, + userInfo: ["account": self.metadata.account, "serverUrl": self.metadata.serverUrl] + ) + NotificationCenter.default.postOnMainThread( + name: NCGlobal.shared.notificationCenterReloadDataNCShare + ) + // 🔄 refresh again from server + self.readShare(showLoadingIndicator: false) } else { NCContentPresenter().showError(error: error) self.delegate?.updateShareWithError(idShare: shareable.idShare) @@ -238,14 +258,7 @@ class NCShareNetworking: NSObject { func getSharees(searchString: String) { NCActivityIndicator.shared.start(backgroundView: view) - NextcloudKit.shared.searchSharees(search: searchString, account: metadata.account) { task in - Task { - let identifier = await NCNetworking.shared.networkingTasks.createIdentifier(account: self.metadata.account, - path: searchString, - name: "searchSharees") - await NCNetworking.shared.networkingTasks.track(identifier: identifier, task: task) - } - } completion: { _, sharees, _, error in + NextcloudKit.shared.searchSharees(search: searchString, account: metadata.account) { _, sharees, _, error in NCActivityIndicator.shared.stop() if error == .success { @@ -262,18 +275,35 @@ class NCShareNetworking: NSObject { /// /// Remove the download limit on the share, if existent. /// - func removeShareDownloadLimit(token: String) { - let capabilities = NCNetworking.shared.capabilities[self.metadata.account] ?? NKCapabilities.Capabilities() + private func readDownloadLimit(account: String, token: String) async throws -> NKDownloadLimit? { + return try await withCheckedThrowingContinuation { continuation in + NextcloudKit.shared.getDownloadLimit(account: account, token: token) { limit, error in + if error != .success { + continuation.resume(throwing: error.error) + return + } else { + continuation.resume(returning: limit) + } + } + } + } - if !capabilities.fileSharingDownloadLimit || token.isEmpty { - return + func readDownloadLimits(account: String, tokens: [String]) async throws { + for token in tokens { + self.database.deleteDownloadLimit(byAccount: account, shareToken: token) + if let downloadLimit = try await readDownloadLimit(account: account, token: token) { + self.database.createDownloadLimit(account: account, count: downloadLimit.count, limit: downloadLimit.limit, token: token) + } } + } + func removeShareDownloadLimit(token: String) { + if !NCCapabilities.shared.getCapabilities(account: self.metadata.account).capabilityFileSharingDownloadLimit || token.isEmpty { + return + } NCActivityIndicator.shared.start(backgroundView: view) - NextcloudKit.shared.removeShareDownloadLimit(account: metadata.account, token: token) { error in NCActivityIndicator.shared.stop() - if error == .success { self.delegate?.downloadLimitRemoved(by: token) } else { @@ -282,23 +312,13 @@ class NCShareNetworking: NSObject { } } - /// - /// Set the download limit for the share. - /// - /// - Parameter limit: The new download limit to set. - /// func setShareDownloadLimit(_ limit: Int, token: String) { - let capabilities = NCNetworking.shared.capabilities[self.metadata.account] ?? NKCapabilities.Capabilities() - - if !capabilities.fileSharingDownloadLimit || token.isEmpty { + if !NCCapabilities.shared.getCapabilities(account: self.metadata.account).capabilityFileSharingDownloadLimit || token.isEmpty { return } - NCActivityIndicator.shared.start(backgroundView: view) - NextcloudKit.shared.setShareDownloadLimit(account: metadata.account, token: token, limit: limit) { error in NCActivityIndicator.shared.stop() - if error == .success { self.delegate?.downloadLimitSet(to: limit, by: token) } else { diff --git a/iOSClient/Share/NCSharePaging.swift b/iOSClient/Share/NCSharePaging.swift index df80a42657..c1e9fc0a2b 100644 --- a/iOSClient/Share/NCSharePaging.swift +++ b/iOSClient/Share/NCSharePaging.swift @@ -29,7 +29,7 @@ import MarqueeLabel import TagListView protocol NCSharePagingContent { - var textField: UIView? { get } + var textField: UITextField? { get } } class NCSharePaging: UIViewController { @@ -50,20 +50,18 @@ class NCSharePaging: UIViewController { view.backgroundColor = .systemBackground title = NSLocalizedString("_details_", comment: "") - navigationItem.leftBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_close_", comment: ""), style: .plain, target: self, action: #selector(exitTapped(_:))) - + navigationItem.leftBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_cancel_", comment: ""), style: .done, target: self, action: #selector(exitTapped)) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(applicationDidEnterBackground(notification:)), name: UIApplication.didEnterBackgroundNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(applicationDidEnterBackground(notification:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidEnterBackground), object: nil) // *** MUST BE THE FIRST ONE *** pagingViewController.metadata = metadata pagingViewController.backgroundColor = .systemBackground pagingViewController.menuBackgroundColor = .systemBackground pagingViewController.selectedBackgroundColor = .systemBackground - pagingViewController.indicatorColor = NCBrandColor.shared.getElement(account: metadata.account) - pagingViewController.textColor = NCBrandColor.shared.textColor - pagingViewController.selectedTextColor = NCBrandColor.shared.getElement(account: metadata.account) + pagingViewController.textColor = .label + pagingViewController.selectedTextColor = .label // Pagination addChild(pagingViewController) @@ -75,16 +73,14 @@ class NCSharePaging: UIViewController { height: 1, zIndex: Int.max, spacing: .zero, - insets: .zero + insets: UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5) ) - pagingViewController.borderOptions = .visible(height: 1, zIndex: Int.max, insets: .zero) - // Contrain the paging view to all edges. pagingViewController.view.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ pagingViewController.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), - pagingViewController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor), + pagingViewController.view.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), pagingViewController.view.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), pagingViewController.view.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor) ]) @@ -98,6 +94,7 @@ class NCSharePaging: UIViewController { pagingViewController.select(index: 0) } + (pagingViewController.view as? NCSharePagingView)?.setupConstraints() pagingViewController.reloadMenu() } @@ -108,38 +105,34 @@ class NCSharePaging: UIViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - - navigationController?.setNavigationBarAppearance() - - let capabilities = NCNetworking.shared.capabilities[metadata.account] ?? NKCapabilities.Capabilities() - - if !capabilities.fileSharingApiEnabled && !capabilities.filesComments && capabilities.activity.isEmpty { + if NCCapabilities.shared.disableSharesView(account: metadata.account) { self.dismiss(animated: false, completion: nil) } -// pagingViewController.menuItemSize = .fixed( -// width: self.view.bounds.width / CGFloat(self.pages.count), -// height: 40) + pagingViewController.menuItemSize = .fixed( + width: self.view.bounds.width / CGFloat(self.pages.count), + height: 40) } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - Task { - await NCNetworking.shared.transferDispatcher.notifyAllDelegates { delegate in - delegate.transferReloadData(serverUrl: metadata.serverUrl, status: nil) - } - } + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": metadata.serverUrl]) } deinit { NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardDidShowNotification, object: nil) NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil) - NotificationCenter.default.removeObserver(self, name: UIApplication.didEnterBackgroundNotification, object: nil) } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) - self.currentVC?.textField?.resignFirstResponder() + + coordinator.animate(alongsideTransition: nil) { _ in + self.pagingViewController.menuItemSize = .fixed( + width: self.view.bounds.width / CGFloat(self.pages.count), + height: 40) + self.currentVC?.textField?.resignFirstResponder() + } } // MARK: - NotificationCenter & Keyboard & TextField @@ -163,7 +156,7 @@ class NCSharePaging: UIViewController { view.frame.origin.y = 0 } - @objc func exitTapped(_ sender: Any?) { + @objc func exitTapped() { self.dismiss(animated: true, completion: nil) } @@ -175,6 +168,7 @@ class NCSharePaging: UIViewController { // MARK: - PagingViewController Delegate extension NCSharePaging: PagingViewControllerDelegate { + func pagingViewController(_ pagingViewController: PagingViewController, willScrollToItem pagingItem: PagingItem, startingViewController: UIViewController, destinationViewController: UIViewController) { currentVC?.textField?.resignFirstResponder() @@ -185,8 +179,10 @@ extension NCSharePaging: PagingViewControllerDelegate { // MARK: - PagingViewController DataSource extension NCSharePaging: PagingViewControllerDataSource { + func pagingViewController(_: PagingViewController, viewControllerAt index: Int) -> UIViewController { - let height: CGFloat = 50 + + let height = pagingViewController.options.menuHeight + NCSharePagingView.headerHeight + NCSharePagingView.tagHeaderHeight if pages[index] == .activity { guard let viewController = UIStoryboard(name: "NCActivity", bundle: nil).instantiateInitialViewController() as? NCActivity else { @@ -230,9 +226,14 @@ extension NCSharePaging: PagingViewControllerDataSource { // MARK: - Header class NCShareHeaderViewController: PagingViewController { + public var image: UIImage? public var metadata = tableMetadata() + public var activityEnabled = true + public var commentsEnabled = true + public var sharingEnabled = true + override func loadView() { view = NCSharePagingView( options: options, @@ -244,11 +245,11 @@ class NCShareHeaderViewController: PagingViewController { } class NCSharePagingView: PagingView { + + static let headerHeight: CGFloat = 90 + static var tagHeaderHeight: CGFloat = 0 var metadata = tableMetadata() - let utilityFileSystem = NCUtilityFileSystem() - let utility = NCUtility() public var headerHeightConstraint: NSLayoutConstraint? - var header: NCShareHeader? // MARK: - View Life Cycle @@ -262,84 +263,75 @@ class NCSharePagingView: PagingView { fatalError("init(coder:) has not been implemented") } - override func setupConstraints() { - guard let headerView = Bundle.main.loadNibNamed("NCShareHeader", owner: self, options: nil)?.first as? NCShareHeader else { return } - header = headerView - headerView.backgroundColor = .systemBackground - - let dateFormatter = DateFormatter() - dateFormatter.dateStyle = .short - dateFormatter.timeStyle = .short - dateFormatter.locale = Locale.current - - headerView.setupUI(with: metadata) - - addSubview(headerView) - - collectionView.translatesAutoresizingMaskIntoConstraints = false - headerView.translatesAutoresizingMaskIntoConstraints = false - pageView.translatesAutoresizingMaskIntoConstraints = false - - NSLayoutConstraint.activate([ - collectionView.leadingAnchor.constraint(equalTo: leadingAnchor), - collectionView.trailingAnchor.constraint(equalTo: trailingAnchor), - collectionView.heightAnchor.constraint(equalToConstant: options.menuHeight), - collectionView.topAnchor.constraint(equalTo: headerView.bottomAnchor), - - headerView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor), - headerView.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor), - headerView.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor), - - pageView.leadingAnchor.constraint(equalTo: leadingAnchor), - pageView.trailingAnchor.constraint(equalTo: trailingAnchor), - pageView.bottomAnchor.constraint(equalTo: bottomAnchor), - pageView.topAnchor.constraint(equalTo: headerView.bottomAnchor) - ]) - } } class NCShareHeaderView: UIView { @IBOutlet weak var imageView: UIImageView! - @IBOutlet weak var path: MarqueeLabel! + @IBOutlet weak var fileName: UILabel! @IBOutlet weak var info: UILabel! - @IBOutlet weak var creation: UILabel! - @IBOutlet weak var upload: UILabel! @IBOutlet weak var favorite: UIButton! - @IBOutlet weak var details: UIButton! - @IBOutlet weak var tagListView: TagListView! - + @IBOutlet weak var labelSharing: UILabel! + @IBOutlet weak var labelSharingInfo: UILabel! + @IBOutlet weak var fullWidthImageView: UIImageView! + @IBOutlet weak var canShareInfoView: UIView! + @IBOutlet weak var sharedByLabel: UILabel! + @IBOutlet weak var resharingAllowedLabel: UILabel! + @IBOutlet weak var sharedByImageView: UIImageView! + @IBOutlet weak var constraintTopSharingLabel: NSLayoutConstraint! + let utility = NCUtility() var ocId = "" override func awakeFromNib() { super.awakeFromNib() - let longGesture = UILongPressGestureRecognizer(target: self, action: #selector(longTap(_:))) - path.addGestureRecognizer(longGesture) + setupUI() } + func setupUI() { + labelSharing.text = NSLocalizedString("_sharing_", comment: "") + labelSharingInfo.text = NSLocalizedString("_sharing_message_", comment: "") + + if UIScreen.main.bounds.width < 376 { + constraintTopSharingLabel.constant = 15 + } + } + + func updateCanReshareUI() { + let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) + var isCurrentUser = true + if let ownerId = metadata?.ownerId, !ownerId.isEmpty { + isCurrentUser = NCShareCommon().isCurrentUserIsFileOwner(fileOwnerId: ownerId) + } + var canReshare: Bool { + guard let metadata = metadata else { return true } + return ((metadata.sharePermissionsCollaborationServices & NCPermissions().permissionShareShare) != 0) + } + canShareInfoView.isHidden = isCurrentUser + labelSharingInfo.isHidden = !isCurrentUser + + if !isCurrentUser { + sharedByImageView.image = UIImage(named: "cloudUpload")?.image(color: .systemBlue, size: 26) + let ownerName = metadata?.ownerDisplayName ?? "" + sharedByLabel.text = NSLocalizedString("_shared_with_you_by_", comment: "") + " " + ownerName + let resharingAllowedMessage = NSLocalizedString("_share_reshare_allowed_", comment: "") + " " + NSLocalizedString("_sharing_message_", comment: "") + let resharingNotAllowedMessage = NSLocalizedString("_share_reshare_not_allowed_", comment: "") + resharingAllowedLabel.text = canReshare ? resharingAllowedMessage : resharingNotAllowedMessage + } + } + @IBAction func touchUpInsideFavorite(_ sender: UIButton) { guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return } NCNetworking.shared.favoriteMetadata(metadata) { error in if error == .success { guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(metadata.ocId) else { return } - self.favorite.setImage(NCUtility().loadImage( - named: "star.fill", - colors: metadata.favorite ? [NCBrandColor.shared.yellowFavorite] : [NCBrandColor.shared.iconImageColor2], - size: 20), for: .normal) + if metadata.favorite { + self.favorite.setImage(self.utility.loadImage(named: "star.fill", colors: [NCBrandColor.shared.yellowFavorite], size: 24), for: .normal) + } else { + self.favorite.setImage(self.utility.loadImage(named: "star.fill", colors: [NCBrandColor.shared.textInfo], size: 24), for: .normal) + } } else { NCContentPresenter().showError(error: error) } } } - - @IBAction func touchUpInsideDetails(_ sender: UIButton) { - creation.isHidden = !creation.isHidden - upload.isHidden = !upload.isHidden - } - - @objc func longTap(_ sender: UIGestureRecognizer) { - UIPasteboard.general.string = path.text - let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_copied_path_") - NCContentPresenter().showInfo(error: error) - } } diff --git a/iOSClient/Share/NCShareUserCell.swift b/iOSClient/Share/NCShareUserCell.swift index 427304106b..a50a15b0a0 100644 --- a/iOSClient/Share/NCShareUserCell.swift +++ b/iOSClient/Share/NCShareUserCell.swift @@ -26,127 +26,124 @@ import NextcloudKit class NCShareUserCell: UITableViewCell, NCCellProtocol { - @IBOutlet weak var imageItem: UIImageView! + // MARK: - IBOutlets @IBOutlet weak var labelTitle: UILabel! @IBOutlet weak var buttonMenu: UIButton! - @IBOutlet weak var imageStatus: UIImageView! - @IBOutlet weak var status: UILabel! @IBOutlet weak var btnQuickStatus: UIButton! @IBOutlet weak var labelQuickStatus: UILabel! - @IBOutlet weak var imageDownArrow: UIImageView! - - private var index = IndexPath() - + @IBOutlet weak var imagePermissionType: UIImageView! + @IBOutlet weak var imageRightArrow: UIImageView! + @IBOutlet weak var imageExpiredDateSet: UIImageView! + @IBOutlet weak var imagePasswordSet: UIImageView! + @IBOutlet weak var imageAllowedPermission: UIImageView! + @IBOutlet weak var leadingContraintofImageRightArrow: NSLayoutConstraint! + + // MARK: - Properties + private var indexPathInternal = IndexPath() var tableShare: tableShare? - var isDirectory = false - let utility = NCUtility() + var isDirectory: Bool = false weak var delegate: NCShareUserCellDelegate? var indexPath: IndexPath { - get { return index } - set { index = newValue } - } - var fileAvatarImageView: UIImageView? { - return imageItem + get { indexPathInternal } + set { indexPathInternal = newValue } } + var fileUser: String? { get { return tableShare?.shareWith } set {} } - func setupCellUI(userId: String, session: NCSession.Session, metadata: tableMetadata) { - guard let tableShare = tableShare else { - return - } - self.accessibilityCustomActions = [UIAccessibilityCustomAction( - name: NSLocalizedString("_show_profile_", comment: ""), - target: self, - selector: #selector(tapAvatarImage(_:)))] - labelTitle.text = (tableShare.shareWithDisplayname.isEmpty ? tableShare.shareWith : tableShare.shareWithDisplayname) - - let type = getTypeString(tableShare) - if !type.isEmpty { - labelTitle.text?.append(" (\(type))") - } + // MARK: - Lifecycle + override func awakeFromNib() { + super.awakeFromNib() + setupCellUIAppearance() + } - labelTitle.lineBreakMode = .byTruncatingMiddle - labelTitle.textColor = NCBrandColor.shared.textColor - isUserInteractionEnabled = true - labelQuickStatus.isHidden = false - imageDownArrow.isHidden = false - buttonMenu.isHidden = false - buttonMenu.accessibilityLabel = NSLocalizedString("_more_", comment: "") - imageItem.image = NCShareCommon.getImageShareType(shareType: tableShare.shareType) - - let status = utility.getUserStatus(userIcon: tableShare.userIcon, userStatus: tableShare.userStatus, userMessage: tableShare.userMessage) - imageStatus.image = status.statusImage - 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 + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + if previousTraitCollection?.userInterfaceStyle != traitCollection.userInterfaceStyle { + setupCellUIAppearance() } + } - btnQuickStatus.accessibilityHint = NSLocalizedString("_user_sharee_footer_", comment: "") - btnQuickStatus.setTitle("", for: .normal) - btnQuickStatus.contentHorizontalAlignment = .left + // MARK: - Configure + func configure(with share: tableShare?, at indexPath: IndexPath, isDirectory: Bool, userId: String) { + self.indexPath = indexPath + self.tableShare = share + self.isDirectory = isDirectory + setupCellUI(userId: userId) + } - if NCSharePermissions.canEdit(tableShare.permissions, isDirectory: isDirectory) { // Can edit - labelQuickStatus.text = NSLocalizedString("_share_editing_", comment: "") - } else if tableShare.permissions == NCSharePermissions.permissionReadShare { // Read only - labelQuickStatus.text = NSLocalizedString("_share_read_only_", comment: "") - } else { // Custom permissions - labelQuickStatus.text = NSLocalizedString("_custom_permissions_", comment: "") - } + // MARK: - UI Setup + private func setupCellUIAppearance() { + contentView.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + buttonMenu.contentMode = .scaleAspectFill + buttonMenu.setImage(NCImageCache.images.buttonMore.image(color: NCBrandColor.shared.brand, size: 24), for: .normal) + labelQuickStatus.textColor = NCBrandColor.shared.shareBlueColor + labelTitle.textColor = NCBrandColor.shared.label + imageRightArrow.image = UIImage(named: "rightArrow")?.imageColor(NCBrandColor.shared.shareBlueColor) + imageExpiredDateSet.image = UIImage(named: "calenderNew")?.imageColor(NCBrandColor.shared.shareBlueColor) + imagePasswordSet.image = UIImage(named: "lockNew")?.imageColor(NCBrandColor.shared.shareBlueColor) + + imagePermissionType.image = imagePermissionType.image?.imageColor(NCBrandColor.shared.shareBlueColor) + updatePermissionUI() + } - let fileName = NCSession.shared.getFileName(urlBase: session.urlBase, user: tableShare.shareWith) - let results = NCManageDatabase.shared.getImageAvatarLoaded(fileName: fileName) + private func updatePermissionUI() { + guard let tableShare = tableShare else { return } - imageItem.contentMode = .scaleAspectFill + let permissions = NCPermissions() - if tableShare.shareType == NCShareCommon.shareTypeTeam { - imageItem.image = utility.loadImage(named: "custom.person.3.circle.fill", colors: [NCBrandColor.shared.iconImageColor2]) - } else if results.image == nil { - imageItem.image = utility.loadUserImage(for: tableShare.shareWith, displayName: tableShare.shareWithDisplayname, urlBase: metadata.urlBase) + if tableShare.permissions == permissions.permissionCreateShare { + labelQuickStatus.text = NSLocalizedString("_share_quick_permission_everyone_can_just_upload_", comment: "") + imagePermissionType.image = UIImage(named: "upload")?.imageColor(NCBrandColor.shared.shareBlueColor) + } else if permissions.isAnyPermissionToEdit(tableShare.permissions) { + labelQuickStatus.text = NSLocalizedString("_share_quick_permission_everyone_can_edit_", comment: "") + imagePermissionType.image = UIImage(named: "editNew")?.imageColor(NCBrandColor.shared.shareBlueColor) } else { - imageItem.image = results.image + labelQuickStatus.text = NSLocalizedString("_share_quick_permission_everyone_can_only_view_", comment: "") + imagePermissionType.image = UIImage(named: "showPasswordNew")?.imageColor(NCBrandColor.shared.shareBlueColor) } - if !(results.tblAvatar?.loaded ?? false), - NCNetworking.shared.downloadAvatarQueue.operations.filter({ ($0 as? NCOperationDownloadAvatar)?.fileName == fileName }).isEmpty { - NCNetworking.shared.downloadAvatarQueue.addOperation(NCOperationDownloadAvatar(user: tableShare.shareWith, fileName: fileName, account: metadata.account, view: self)) - } + imagePasswordSet.isHidden = tableShare.password.isEmpty + imageExpiredDateSet.isHidden = (tableShare.expirationDate == nil) + + leadingContraintofImageRightArrow.constant = (imagePasswordSet.isHidden && imageExpiredDateSet.isHidden) ? 0 : 5 } - private func getTypeString(_ tableShare: tableShareV2) -> String { - switch tableShare.shareType { - case NCShareCommon.shareTypeFederated: - return NSLocalizedString("_remote_", comment: "") - case NCShareCommon.shareTypeFederatedGroup: - return NSLocalizedString("_remote_group_", comment: "") - case NCShareCommon.shareTypeRoom: - return NSLocalizedString("_conversation_", comment: "") - default: - return "" - } - } + private func setupCellUI(userId: String) { + guard let tableShare = tableShare else { return } - override func awakeFromNib() { - super.awakeFromNib() - let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapAvatarImage(_:))) - imageItem?.addGestureRecognizer(tapGesture) + let permissions = NCPermissions() + labelTitle.text = tableShare.shareWithDisplayname - labelQuickStatus.textColor = NCBrandColor.shared.customer - imageDownArrow.image = utility.loadImage(named: "arrowtriangle.down.circle", colors: [NCBrandColor.shared.customer]) - } + let isOwner = tableShare.uidOwner == userId || tableShare.uidFileOwner == userId + isUserInteractionEnabled = isOwner + buttonMenu.isHidden = !isOwner + buttonMenu.accessibilityLabel = NSLocalizedString("_more_", comment: "") - @objc func tapAvatarImage(_ sender: UITapGestureRecognizer) { - delegate?.showProfile(with: tableShare, sender: sender) + btnQuickStatus.setTitle("", for: .normal) + btnQuickStatus.isEnabled = true + btnQuickStatus.accessibilityHint = NSLocalizedString("_user_sharee_footer_", comment: "") + btnQuickStatus.contentHorizontalAlignment = .left + + setupCellUIAppearance() +// let permissionValue = tableShare.permissions +// +// if permissionValue == permissions.permissionCreateShare { +// labelQuickStatus.text = NSLocalizedString("_share_quick_permission_everyone_can_just_upload_", comment: "") +// imagePermissionType.image = UIImage(named: "upload")?.imageColor(NCBrandColor.shared.shareBlueColor) +// } else if permissions.isAnyPermissionToEdit(permissionValue) { +// labelQuickStatus.text = NSLocalizedString("_share_quick_permission_everyone_can_edit_", comment: "") +// imagePermissionType.image = UIImage(named: "editNew")?.imageColor(NCBrandColor.shared.shareBlueColor) +// } else { +// labelQuickStatus.text = NSLocalizedString("_share_quick_permission_everyone_can_only_view_", comment: "") +// imagePermissionType.image = UIImage(named: "showPasswordNew")?.imageColor(NCBrandColor.shared.shareBlueColor) +// } } + // MARK: - Actions @IBAction func touchUpInsideMenu(_ sender: Any) { delegate?.tapMenu(with: tableShare, sender: sender) } @@ -154,6 +151,10 @@ class NCShareUserCell: UITableViewCell, NCCellProtocol { @IBAction func quickStatusClicked(_ sender: Any) { delegate?.quickStatus(with: tableShare, sender: sender) } + + @objc func tapAvatarImage(_ sender: UITapGestureRecognizer) { + delegate?.showProfile(with: tableShare, sender: sender) + } } protocol NCShareUserCellDelegate: AnyObject { @@ -162,80 +163,51 @@ protocol NCShareUserCellDelegate: AnyObject { func quickStatus(with tableShare: tableShare?, sender: Any) } -// MARK: - NCSearchUserDropDownCell - class NCSearchUserDropDownCell: DropDownCell, NCCellProtocol { @IBOutlet weak var imageItem: UIImageView! @IBOutlet weak var imageStatus: UIImageView! - @IBOutlet weak var status: UILabel! + @IBOutlet weak var statusLabel: UILabel! @IBOutlet weak var imageShareeType: UIImageView! - @IBOutlet weak var centerTitle: NSLayoutConstraint! + @IBOutlet weak var centerTitleConstraint: NSLayoutConstraint! + + private var userIdentifier: String = "" + private var currentIndexPath = IndexPath() - private var user: String = "" - private var index = IndexPath() - private let utilityFileSystem = NCUtilityFileSystem() + // MARK: - NCCellProtocol var indexPath: IndexPath { - get { return index } - set { index = newValue } + get { currentIndexPath } + set { currentIndexPath = newValue } } + var fileAvatarImageView: UIImageView? { - return imageItem + imageItem } + var fileUser: String? { - get { return user } - set { user = newValue ?? "" } + get { userIdentifier } + set { userIdentifier = newValue ?? "" } } + // MARK: - Setup + func setupCell(sharee: NKSharee, session: NCSession.Session) { let utility = NCUtility() - imageItem.image = NCShareCommon.getImageShareType(shareType: sharee.shareType) - imageShareeType.image = NCShareCommon.getImageShareType(shareType: sharee.shareType) - let status = utility.getUserStatus(userIcon: sharee.userIcon, userStatus: sharee.userStatus, userMessage: sharee.userMessage) + let shareCommon = NCShareCommon() - if let statusImage = status.statusImage { + imageShareeType.image = shareCommon.getImageShareType(shareType: sharee.shareType, isDropDown: true) + + let userStatus = utility.getUserStatus(userIcon: sharee.userIcon, + userStatus: sharee.userStatus, + userMessage: sharee.userMessage) + + if let statusImage = userStatus.statusImage { imageStatus.image = statusImage imageStatus.makeCircularBackground(withColor: .systemBackground) } - self.status.text = status.statusMessage - if self.status.text?.count ?? 0 > 0 { - centerTitle.constant = -5 - } else { - centerTitle.constant = 0 - } - - imageItem.image = utility.loadUserImage(for: sharee.shareWith, displayName: nil, urlBase: session.urlBase) - - let fileName = NCSession.shared.getFileName(urlBase: session.urlBase, user: sharee.shareWith) - let results = NCManageDatabase.shared.getImageAvatarLoaded(fileName: fileName) - - if results.image == nil { - let etag = NCManageDatabase.shared.getTableAvatar(fileName: fileName)?.etag - let fileNameLocalPath = utilityFileSystem.createServerUrl(serverUrl: utilityFileSystem.directoryUserData, fileName: fileName) - - NextcloudKit.shared.downloadAvatar( - user: sharee.shareWith, - fileNameLocalPath: fileNameLocalPath, - sizeImage: NCGlobal.shared.avatarSize, - avatarSizeRounded: NCGlobal.shared.avatarSizeRounded, - etagResource: etag, - account: session.account) { task in - Task { - let identifier = await NCNetworking.shared.networkingTasks.createIdentifier(account: session.account, - path: sharee.shareWith, - name: "downloadAvatar") - await NCNetworking.shared.networkingTasks.track(identifier: identifier, task: task) - } - } completion: { _, imageAvatar, _, etag, _, error in - if error == .success, let etag = etag, let imageAvatar = imageAvatar { - NCManageDatabase.shared.addAvatar(fileName: fileName, etag: etag) - self.imageItem.image = imageAvatar - } else if error.errorCode == NCGlobal.shared.errorNotModified, let imageAvatar = NCManageDatabase.shared.setAvatarLoaded(fileName: fileName) { - self.imageItem.image = imageAvatar - } - } - } + statusLabel.text = userStatus.statusMessage + centerTitleConstraint.constant = (statusLabel.text?.isEmpty == false) ? -5 : 0 } } diff --git a/iOSClient/Share/NoSharesFooterView.swift b/iOSClient/Share/NoSharesFooterView.swift new file mode 100644 index 0000000000..636b319a83 --- /dev/null +++ b/iOSClient/Share/NoSharesFooterView.swift @@ -0,0 +1,63 @@ +// +// NoSharesFooterView.swift +// Nextcloud +// +// Created by A106551118 on 12/08/25. +// Copyright © 2025 Marino Faggiana. All rights reserved. +// + + +import UIKit + +class NoSharesFooterView: UITableViewHeaderFooterView { + + static let reuseIdentifier = "NoSharesFooterView" + + private let titleLabel: UILabel = { + let label = UILabel() + label.font = .systemFont(ofSize: 17, weight: .semibold) + label.textColor = NCBrandColor.shared.textColor + label.text = NSLocalizedString("_share_shared_with_", comment: "") + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + + private let infoLabel: UILabel = { + let label = UILabel() + label.font = .systemFont(ofSize: 15, weight: .regular) + label.textColor = NCBrandColor.shared.textColor + label.text = NSLocalizedString("_share_no_shares_text_", comment: "") + label.numberOfLines = 0 + label.lineBreakMode = .byWordWrapping + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + + override init(reuseIdentifier: String?) { + super.init(reuseIdentifier: reuseIdentifier) + setupUI() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setupUI() + } + + private func setupUI() { + contentView.backgroundColor = .clear + contentView.addSubview(titleLabel) + contentView.addSubview(infoLabel) + + NSLayoutConstraint.activate([ + titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 20), + titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 15), + titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -15), + titleLabel.heightAnchor.constraint(equalToConstant: 25), + + infoLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 15), + infoLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 15), + infoLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -15), + infoLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor) + ]) + } +} diff --git a/iOSClient/Share/ShareDownloadLimitNetwork.swift b/iOSClient/Share/ShareDownloadLimitNetwork.swift new file mode 100644 index 0000000000..6cbd24e3a6 --- /dev/null +++ b/iOSClient/Share/ShareDownloadLimitNetwork.swift @@ -0,0 +1,151 @@ +// +// ShareDownloadLimitNetwork.swift +// Nextcloud +// +// Created by A118830248 on 11/11/21. +// Copyright © 2021 Marino Faggiana. All rights reserved. +// + +import Foundation +import SwiftyJSON +import NextcloudKit +import Alamofire + +class NMCCommunication: NSObject, XMLParserDelegate { + + public static let shared: NMCCommunication = { + let instance = NMCCommunication() + return instance + }() + + var message = "" + var foundCharacters = ""; + var downloadLimit = DownloadLimit() + private lazy var appDelegate = UIApplication.shared.delegate as? AppDelegate + var controller: NCMainTabBarController! + var session: NCSession.Session { + NCSession.shared.getSession(controller: controller) + } + + func getDownloadLimit(token: String, completion: @escaping (_ downloadLimit: DownloadLimit?, _ errorDescription: String) -> Void) { + let baseUrl = session.urlBase // NCBrandOptions.shared.loginBaseUrl + let endPoint = "/ocs/v2.php/apps/files_downloadlimit/\(token)/limit" + let path = baseUrl+endPoint + do { + var urlRequest = try URLRequest(url: URL(string: path)!, method: .get) + urlRequest.addValue("true", forHTTPHeaderField: "OCS-APIREQUEST") + + let sessionConfiguration = URLSessionConfiguration.default + let urlSession = URLSession(configuration: sessionConfiguration) + + let task = urlSession.dataTask(with: urlRequest) { [self] (data, response, error) in + guard error == nil else { + completion(nil, error?.localizedDescription ?? "") + return + } + + if let httpResponse = response as? HTTPURLResponse { + let statusCode = httpResponse.statusCode + print("url: \(String(describing: httpResponse.url))\nStatus Code: \(statusCode)") + if httpResponse.statusCode == 200 { + let parser = XMLParser(data: data!) + parser.delegate = self + parser.parse() + completion(self.downloadLimit, self.message) + } else { + completion(nil, "Invalid Response code: \(statusCode)") + } + } else { + completion(nil, error?.localizedDescription ?? "Invalid Response") + } + } + task.resume() + } catch { + completion(nil, error.localizedDescription) + } + } + + func setDownloadLimit(deleteLimit: Bool, limit: String, token: String, completion: @escaping (_ success: Bool, _ errorDescription: String) -> Void) { + let baseUrl = session.urlBase //NCBrandOptions.shared.loginBaseUrl + let endPoint = "/ocs/v2.php/apps/files_downloadlimit/\(token)/limit" + let path = baseUrl+endPoint + do { + + let method = deleteLimit ? HTTPMethod.delete : .put + var urlRequest = try URLRequest(url: URL(string: path)!, method: method) + + urlRequest.addValue("true", forHTTPHeaderField: "OCS-APIREQUEST") + urlRequest.addValue(authorizationToken(), forHTTPHeaderField: "Authorization") + urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type") + + let parameters = ["token": token, "limit": limit] + + let encoder = JSONEncoder() + let jsonData = try encoder.encode(parameters) + urlRequest.httpBody = jsonData + + let sessionConfiguration = URLSessionConfiguration.default + let urlSession = URLSession(configuration: sessionConfiguration) + + let task = urlSession.dataTask(with: urlRequest) { (data, response, error) in + guard error == nil else { + completion(false, error?.localizedDescription ?? "") + return + } + + if let httpResponse = response as? HTTPURLResponse { + let statusCode = httpResponse.statusCode + print("url: \(String(describing: httpResponse.url))\nStatus Code: \(statusCode)") + if httpResponse.statusCode == 200 { + completion(true, error?.localizedDescription ?? "") + } else { + completion(false, "Invalid Response code: \(statusCode)") + } + } else { + completion(false, error?.localizedDescription ?? "Invalid Response") + } + } + task.resume() + } catch { + completion(false, error.localizedDescription) + } + } + + public func authorizationToken() -> String { + let accountDetails = NCManageDatabase.shared.getAllTableAccount().first + let password = NCKeychain().getPassword(account: accountDetails?.account ?? "") + let password = NCKeychain().getPassword(account: accountDetails?.account ?? "") + let username = accountDetails?.user ?? "" + let credential = Data("\(username):\(password)".utf8).base64EncodedString() + return ("Basic \(credential)") + } + + + // MARK:- XML Parser Delegate + public func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) { + + } + public func parser(_ parser: XMLParser, foundCharacters string: String) { + self.foundCharacters += string; + } + + public func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { + if elementName == "limit" { + let limit = self.foundCharacters.replacingOccurrences(of: "\n", with: "") + self.downloadLimit.limit = Int(limit.trimmingCharacters(in: .whitespaces)) + } + if elementName == "count" { + let count = self.foundCharacters.replacingOccurrences(of: "\n", with: "") + self.downloadLimit.count = Int(count.trimmingCharacters(in: .whitespaces)) + } + if elementName == "message"{ + self.message = self.foundCharacters + } + self.foundCharacters = "" + } +} + +//struct DownloadLimit: Codable { +// var limit: Int? +// var count: Int? +//} diff --git a/iOSClient/Share/Shareable.swift b/iOSClient/Share/Shareable.swift index 374eebabb1..4b1f413aeb 100644 --- a/iOSClient/Share/Shareable.swift +++ b/iOSClient/Share/Shareable.swift @@ -16,11 +16,9 @@ protocol Shareable: AnyObject { var password: String { get set } var label: String { get set } var note: String { get set } - var downloadAndSync: Bool { get set } var expirationDate: NSDate? { get set } var shareWithDisplayname: String { get set } var attributes: String? { get set } - var itemType: String { get set } } // MARK: - Default Implementations @@ -31,7 +29,7 @@ extension Shareable { /// var formattedDateString: String? { guard let date = expirationDate else { - return nil + return "" } let dateFormatter = DateFormatter() @@ -56,44 +54,8 @@ extension Shareable { // MARK: - tableShare Extension -extension tableShare: Shareable { - var downloadAndSync: Bool { - get { - NCManageDatabase.shared.isAttributeDownloadEnabled(attributes: attributes) - } - set { - attributes = NCManageDatabase.shared.setAttibuteDownload(state: newValue) - } - } -} +extension tableShare: Shareable {} // MARK: - NKShare Extension -extension NKShare: Shareable { - var downloadAndSync: Bool { - get { - NCManageDatabase.shared.isAttributeDownloadEnabled(attributes: attributes) - } - set { - attributes = NCManageDatabase.shared.setAttibuteDownload(state: newValue) - } - } -} - -private func isAttributeDownloadEnabled(attributes: String?) -> Bool { - if let attributes = attributes, let data = attributes.data(using: .utf8) { - do { - if let json = try JSONSerialization.jsonObject(with: data) as? [Dictionary] { - for sub in json { - let key = sub["key"] as? String - let enabled = sub["enabled"] as? Bool - let scope = sub["scope"] as? String - if key == "download", scope == "permissions", let enabled = enabled { - return enabled - } - } - } - } catch let error as NSError { print(error) } - } - return true -} +extension NKShare: Shareable {} diff --git a/iOSClient/Share/TransientShare.swift b/iOSClient/Share/TransientShare.swift index 666b91b66c..33c8b0c30d 100644 --- a/iOSClient/Share/TransientShare.swift +++ b/iOSClient/Share/TransientShare.swift @@ -22,24 +22,18 @@ class TransientShare: Shareable { var note: String = "" var expirationDate: NSDate? var shareWithDisplayname: String = "" - var downloadAndSync = false - var itemType: String = "" var attributes: String? private init(shareType: Int, metadata: tableMetadata, password: String?) { - let capabilities = NCNetworking.shared.capabilities[metadata.account] ?? NKCapabilities.Capabilities() - - if metadata.e2eEncrypted, capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV12 { - self.permissions = NCSharePermissions.permissionCreateShare + if metadata.e2eEncrypted, NCCapabilities.shared.getCapabilities(account: metadata.account).capabilityE2EEApiVersion == NCGlobal.shared.e2eeVersionV12 { + self.permissions = NCPermissions().permissionCreateShare } else { - self.permissions = capabilities.fileSharingDefaultPermission & metadata.sharePermissionsCollaborationServices + self.permissions = NCCapabilities.shared.getCapabilities(account: metadata.account).capabilityFileSharingDefaultPermission & metadata.sharePermissionsCollaborationServices } self.shareType = shareType - self.itemType = metadata.isDirectory ? NCShareCommon.itemTypeFolder : NCShareCommon.itemTypeFile - if let password = password { self.password = password } @@ -48,9 +42,10 @@ class TransientShare: Shareable { convenience init(sharee: NKSharee, metadata: tableMetadata, password: String?) { self.init(shareType: sharee.shareType, metadata: metadata, password: password) self.shareWith = sharee.shareWith + self.shareWithDisplayname = sharee.label } static func shareLink(metadata: tableMetadata, password: String?) -> TransientShare { - TransientShare(shareType: NCShareCommon.shareTypeLink, metadata: metadata, password: password) + TransientShare(shareType: NCShareCommon().SHARE_TYPE_LINK, metadata: metadata, password: password) } } diff --git a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift index 8c82abf6db..77f8e55ead 100644 --- a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift +++ b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift @@ -48,11 +48,12 @@ extension NCTrashCellProtocol where Self: UICollectionViewCell { self.labelInfo?.text = dateFormatter.string(from: tableTrash.trashbinDeletionTime as Date) } if tableTrash.directory { - self.imageItem.image = NCImageCache.shared.getFolder(account: tableTrash.account) + self.imageItem.image = NCImageCache.shared.getFolder() } else { self.imageItem.image = image - self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) +// self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) } + self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) self.accessibilityLabel = tableTrash.trashbinFileName + ", " + (self.labelInfo?.text ?? "") } } diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.swift b/iOSClient/Trash/Cell/NCTrashGridCell.swift index 0fae0620f7..85ee0fd190 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.swift +++ b/iOSClient/Trash/Cell/NCTrashGridCell.swift @@ -2,23 +2,8 @@ // NCTrashGridCell.swift // Nextcloud // -// Created by Marino Faggiana on 19/03/2024. -// Copyright © 2024 Marino Faggiana. All rights reserved. -// -// Author Marino Faggiana -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . +// Created by A200073704 on 27/06/23. +// Copyright © 2023 Marino Faggiana. All rights reserved. // import UIKit @@ -31,18 +16,64 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { @IBOutlet weak var imageItem: UIImageView! @IBOutlet weak var imageSelect: UIImageView! + @IBOutlet weak var imageStatus: UIImageView! + @IBOutlet weak var imageFavorite: UIImageView! + @IBOutlet weak var imageLocal: UIImageView! @IBOutlet weak var labelTitle: UILabel! @IBOutlet weak var labelInfo: UILabel! - @IBOutlet weak var labelSubinfo: UILabel! @IBOutlet weak var buttonMore: UIButton! @IBOutlet weak var imageVisualEffect: UIVisualEffectView! + @IBOutlet weak var progressView: UIProgressView! - weak var delegate: NCTrashGridCellDelegate? - var objectId = "" + internal var objectId = "" var indexPath = IndexPath() var account = "" var user = "" + weak var delegate: NCTrashGridCellDelegate? + var namedButtonMore = "" + + var fileObjectId: String? { + get { return objectId } + set { objectId = newValue ?? "" } + } + var filePreviewImageView: UIImageView? { + get { return imageItem } + set { imageItem = newValue } + } + var fileUser: String? { + get { return user } + set { user = newValue ?? "" } + } + var fileTitleLabel: UILabel? { + get { return labelTitle } + set { labelTitle = newValue } + } + var fileInfoLabel: UILabel? { + get { return labelInfo } + set { labelInfo = newValue } + } + var fileProgressView: UIProgressView? { + get { return progressView } + set { progressView = newValue } + } + var fileSelectImage: UIImageView? { + get { return imageSelect } + set { imageSelect = newValue } + } + var fileStatusImage: UIImageView? { + get { return imageStatus } + set { imageStatus = newValue } + } + var fileLocalImage: UIImageView? { + get { return imageLocal } + set { imageLocal = newValue } + } + var fileFavoriteImage: UIImageView? { + get { return imageFavorite } + set { imageFavorite = newValue } + } + override func awakeFromNib() { super.awakeFromNib() initCell() @@ -66,9 +97,14 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { imageVisualEffect.clipsToBounds = true imageVisualEffect.alpha = 0.5 + progressView.tintColor = NCBrandColor.shared.brandElement + progressView.transform = CGAffineTransform(scaleX: 1.0, y: 0.5) + progressView.trackTintColor = .clear + labelTitle.text = "" labelInfo.text = "" - labelSubinfo.text = "" + labelTitle.textColor = .label + labelInfo.textColor = .systemGray } override func snapshotView(afterScreenUpdates afterUpdates: Bool) -> UIView? { @@ -79,16 +115,20 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { delegate?.tapMoreGridItem(with: objectId, image: imageItem.image, sender: sender) } + fileprivate func setA11yActions() { + let moreName = namedButtonMore == NCGlobal.shared.buttonMoreStop ? "_cancel_" : "_more_" + self.accessibilityCustomActions = [ UIAccessibilityCustomAction( - name: NSLocalizedString("_more_", comment: ""), + name: NSLocalizedString(moreName, comment: ""), target: self, selector: #selector(touchUpInsideMore(_:))) ] } - func setButtonMore(image: UIImage) { + func setButtonMore(named: String, image: UIImage) { + namedButtonMore = named buttonMore.setImage(image, for: .normal) setA11yActions() } @@ -99,19 +139,23 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { func selected(_ status: Bool, isEditMode: Bool, account: String) { if isEditMode { + imageSelect.isHidden = false buttonMore.isHidden = true accessibilityCustomActions = nil } else { + imageSelect.isHidden = true buttonMore.isHidden = false + imageVisualEffect.isHidden = true setA11yActions() } if status { + let traitCollectionUserInterfaceStyleDark = traitCollection.userInterfaceStyle == .dark + imageVisualEffect.effect = UIBlurEffect(style: traitCollectionUserInterfaceStyleDark ? .dark : .extraLight) + imageVisualEffect.backgroundColor = traitCollectionUserInterfaceStyleDark ? .black : .lightGray imageSelect.image = NCImageCache.shared.getImageCheckedYes() - imageSelect.isHidden = false imageVisualEffect.isHidden = false } else { - imageSelect.isHidden = true - imageVisualEffect.isHidden = true + imageSelect.image = NCImageCache.shared.getImageCheckedNo() } } @@ -121,8 +165,7 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { dateFormatter.timeStyle = .none dateFormatter.locale = Locale.current - labelInfo.text = dateFormatter.string(from: date as Date) - labelSubinfo.text = NCUtilityFileSystem().transformedSize(size) + labelInfo.text = dateFormatter.string(from: date as Date) + " · " + NCUtilityFileSystem().transformedSize(size) } func setAccessibility(label: String, value: String) { @@ -130,59 +173,3 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { accessibilityValue = value } } - -// MARK: - Grid Layout - -class NCTrashGridLayout: UICollectionViewFlowLayout { - - var heightLabelPlusButton: CGFloat = 60 - var marginLeftRight: CGFloat = 10 - var itemForLine: CGFloat = 3 - var itemWidthDefault: CGFloat = 140 - - // MARK: - View Life Cycle - - override init() { - super.init() - - sectionHeadersPinToVisibleBounds = false - - minimumInteritemSpacing = 1 - minimumLineSpacing = marginLeftRight - - self.scrollDirection = .vertical - self.sectionInset = UIEdgeInsets(top: 10, left: marginLeftRight, bottom: 0, right: marginLeftRight) - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override var itemSize: CGSize { - get { - if let collectionView = collectionView { - - if collectionView.frame.width < 400 { - itemForLine = 3 - } else { - itemForLine = collectionView.frame.width / itemWidthDefault - } - - let itemWidth: CGFloat = (collectionView.frame.width - marginLeftRight * 2 - marginLeftRight * (itemForLine - 1)) / itemForLine - let itemHeight: CGFloat = itemWidth + heightLabelPlusButton - - return CGSize(width: itemWidth, height: itemHeight) - } - - // Default fallback - return CGSize(width: itemWidthDefault, height: itemWidthDefault) - } - set { - super.itemSize = newValue - } - } - - override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint { - return proposedContentOffset - } -} diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.xib b/iOSClient/Trash/Cell/NCTrashGridCell.xib index 607f2744c6..91bd5f805d 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.xib +++ b/iOSClient/Trash/Cell/NCTrashGridCell.xib @@ -1,9 +1,9 @@ - - + + - + @@ -11,140 +11,130 @@ - - + + - + - - + + - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + - - - - - - - + + + + + + + + + + - + - - + - - - - - - - + diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift index 5bd89e1615..b9cfaf115a 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.swift +++ b/iOSClient/Trash/Cell/NCTrashListCell.swift @@ -46,6 +46,8 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { weak var delegate: NCTrashListCellDelegate? var objectId = "" var account = "" + var indexPath = IndexPath() + let utility = NCUtility() override func awakeFromNib() { super.awakeFromNib() @@ -72,8 +74,11 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { ] - imageRestore.image = NCUtility().loadImage(named: "arrow.counterclockwise", colors: [NCBrandColor.shared.iconImageColor]) - imageMore.image = NCUtility().loadImage(named: "trash", colors: [.red]) + imageRestore.image = utility.loadImage(named: "restore", colors: [NCBrandColor.shared.iconColor]) + + imageMore.image = UIImage(systemName: "trash") + imageMore.tintColor = NCBrandColor.shared.iconColor + imageItem.layer.cornerRadius = 6 imageItem.layer.masksToBounds = true @@ -108,8 +113,11 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { } if status { var blurEffectView: UIView? - blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterial)) - blurEffectView?.backgroundColor = .lightGray + var blurEffect: UIVisualEffect? + let traitCollectionUserInterfaceStyleDark = traitCollection.userInterfaceStyle == .dark + blurEffect = UIBlurEffect(style: traitCollectionUserInterfaceStyleDark ? .dark : .extraLight) + blurEffectView = UIVisualEffectView(effect: blurEffect) + blurEffectView?.backgroundColor = traitCollectionUserInterfaceStyleDark ? .black : .lightGray blurEffectView?.frame = self.bounds blurEffectView?.autoresizingMask = [.flexibleWidth, .flexibleHeight] imageSelect.image = NCImageCache.shared.getImageCheckedYes() diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index 8995ce177c..c14ce8b394 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -23,19 +23,24 @@ import UIKit import RealmSwift +import Foundation // MARK: UICollectionViewDelegate extension NCTrash: UICollectionViewDelegate { + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + guard let resultTableTrash = datasource?[indexPath.item] else { return } + guard !isEditMode else { - if let index = selectOcId.firstIndex(of: resultTableTrash.fileId) { - selectOcId.remove(at: index) + if let index = fileSelect.firstIndex(of: resultTableTrash.fileId) { + fileSelect.remove(at: index) } else { - selectOcId.append(resultTableTrash.fileId) + fileSelect.append(resultTableTrash.fileId) } collectionView.reloadItems(at: [indexPath]) - tabBarSelect.update(selectOcId: selectOcId) + tabBarSelect.update(selectOcId: fileSelect) + setNavigationRightItems() return } @@ -51,7 +56,10 @@ extension NCTrash: UICollectionViewDelegate { // MARK: UICollectionViewDataSource extension NCTrash: UICollectionViewDataSource { + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + emptyDataSet?.numberOfItemsInSection(datasource?.count ?? 0, section: section) + setNavigationRightItems() return datasource?.count ?? 0 } @@ -65,10 +73,11 @@ extension NCTrash: UICollectionViewDataSource { cell = listCell } else { let gridCell = (collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as? NCTrashGridCell)! - gridCell.setButtonMore(image: NCImageCache.shared.getImageButtonMore()) + gridCell.setButtonMore(named: NCGlobal.shared.buttonMoreMore, image: NCImageCache.shared.getImageButtonMore()) gridCell.delegate = self cell = gridCell } + guard let resultTableTrash = datasource?[indexPath.item] else { return cell } cell.imageItem.contentMode = .scaleAspectFit @@ -76,20 +85,16 @@ extension NCTrash: UICollectionViewDataSource { if resultTableTrash.iconName.isEmpty { image = NCImageCache.shared.getImageFile() } else { - image = NCUtility().loadImage(named: resultTableTrash.iconName, useTypeIconFile: true, account: resultTableTrash.account) + image = UIImage(named: resultTableTrash.iconName) } - if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, - etag: resultTableTrash.fileName, - ext: NCGlobal.shared.previewExt512, - userId: session.userId, - urlBase: session.urlBase) { + if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, etag: resultTableTrash.fileName, ext: NCGlobal.shared.previewExt512) { image = imageIcon cell.imageItem.contentMode = .scaleAspectFill } else { if resultTableTrash.hasPreview { if NCNetworking.shared.downloadThumbnailTrashQueue.operations.filter({ ($0 as? NCOperationDownloadThumbnailTrash)?.fileId == resultTableTrash.fileId }).isEmpty { - NCNetworking.shared.downloadThumbnailTrashQueue.addOperation(NCOperationDownloadThumbnailTrash(fileId: resultTableTrash.fileId, fileName: resultTableTrash.fileName, session: session, collectionView: collectionView)) + NCNetworking.shared.downloadThumbnailTrashQueue.addOperation(NCOperationDownloadThumbnailTrash(fileId: resultTableTrash.fileId, fileName: resultTableTrash.fileName, account: session.account, collectionView: collectionView)) } } } @@ -97,8 +102,7 @@ extension NCTrash: UICollectionViewDataSource { cell.account = resultTableTrash.account cell.objectId = resultTableTrash.fileId cell.setupCellUI(tableTrash: resultTableTrash, image: image) - cell.selected(selectOcId.contains(resultTableTrash.fileId), isEditMode: isEditMode, account: resultTableTrash.account) - + cell.selected(fileSelect.contains(resultTableTrash.fileId), isEditMode: isEditMode, account: resultTableTrash.account) return cell } @@ -142,17 +146,34 @@ extension NCTrash: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { if kind == UICollectionView.elementKindSectionHeader { - guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFirstHeaderEmptyData", for: indexPath) as? NCSectionFirstHeaderEmptyData - else { return NCSectionFirstHeaderEmptyData() } - header.emptyImage.image = utility.loadImage(named: "trash", colors: [NCBrandColor.shared.getElement(account: session.account)]) - header.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "") - header.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "") + + guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionHeaderMenu", for: indexPath) as? NCSectionHeaderMenu + else { return UICollectionReusableView() } + + if layoutForView?.layout == NCGlobal.shared.layoutGrid { + header.setImageSwitchList() + header.buttonSwitch.accessibilityLabel = NSLocalizedString("_list_view_", comment: "") + } else { + header.setImageSwitchGrid() + header.buttonSwitch.accessibilityLabel = NSLocalizedString("_grid_view_", comment: "") + } + + header.delegate = self + header.setStatusButtonsView(enable: !(datasource?.isEmpty ?? false)) + header.setSortedTitle(layoutForView?.titleButtonHeader ?? "") + header.setButtonsView(height: NCGlobal.shared.heightButtonsView) + header.setRichWorkspaceHeight(0) + header.setSectionHeight(0) + header.setViewTransfer(isHidden: true) + return header + } else { guard let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as? NCSectionFooter - else { return NCSectionFooter() } + else { return UICollectionReusableView() } if let datasource { footer.setTitleLabel(setTextFooter(datasource: datasource)) + footer.separatorIsHidden(true) } return footer } @@ -161,13 +182,15 @@ extension NCTrash: UICollectionViewDataSource { // MARK: UICollectionViewDelegateFlowLayout extension NCTrash: UICollectionViewDelegateFlowLayout { + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { - var height: Double = 0 if let datasource, datasource.isEmpty { - height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: 0) + let height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: -20) + return CGSize(width: collectionView.frame.width, height: height) } - return CGSize(width: collectionView.frame.width, height: height) + return CGSize(width: collectionView.frame.width, height: NCGlobal.shared.heightButtonsView) } + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { return CGSize(width: collectionView.frame.width, height: 85) } diff --git a/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift b/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift index 677047688c..14b0e071ca 100644 --- a/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift +++ b/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift @@ -22,7 +22,7 @@ import Foundation import UIKit -extension NCTrash: NCTrashSelectTabBarDelegate { +extension NCTrash: NCTrashSelectTabBarDelegate, NCSelectableNavigationView { func onListSelected() { if layoutForView?.layout == NCGlobal.shared.layoutGrid { layoutForView?.layout = NCGlobal.shared.layoutList @@ -44,51 +44,81 @@ extension NCTrash: NCTrashSelectTabBarDelegate { } func selectAll() { - guard let datasource else { return } - if !selectOcId.isEmpty, datasource.count == selectOcId.count { - selectOcId = [] + if !fileSelect.isEmpty, datasource?.count == fileSelect.count { + fileSelect = [] } else { - selectOcId = datasource.compactMap({ $0.fileId }) + fileSelect = (datasource?.compactMap({ $0.fileId }))! } - tabBarSelect.update(selectOcId: selectOcId) + tabBarSelect.update(selectOcId: fileSelect) collectionView.reloadData() } func recover() { - let ids = selectOcId.map { $0 } + fileSelect.forEach(restoreItem) setEditMode(false) - - Task { - for id in ids { - await restoreItem(with: id) - } - } } func delete() { - let ids = selectOcId.map { $0 } + let ocIds = fileSelect.map { $0 } setEditMode(false) Task { - if ids.count > 0, ids.count == datasource?.count { + if ocIds.count > 0, ocIds.count == datasource?.count { await emptyTrash() } else { - await self.deleteItems(with: ids) + await self.deleteItems(with: ocIds) } } } func setEditMode(_ editMode: Bool) { - Task { - isEditMode = editMode - selectOcId.removeAll() + isEditMode = editMode + fileSelect.removeAll() - navigationItem.hidesBackButton = editMode - navigationController?.interactivePopGestureRecognizer?.isEnabled = !editMode - - await (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() - - collectionView.reloadData() + navigationController?.interactivePopGestureRecognizer?.isEnabled = !editMode + navigationItem.hidesBackButton = editMode + DispatchQueue.main.async { + self.collectionView.reloadData() + self.setNavigationRightItems() } } + + func setNavigationRightItems(enableMenu: Bool = false) { + if isEditMode { + let more = UIBarButtonItem(image: UIImage(systemName: "ellipsis"), style: .plain) { self.presentMenu(with: self.selectActions)} + navigationItem.rightBarButtonItems = [more] + } else { + let select = UIBarButtonItem(title: NSLocalizedString("_select_", comment: ""), style: UIBarButtonItem.Style.plain) { self.toggleSelect() } + let notification = UIBarButtonItem(image: UIImage(systemName: "bell"), style: .plain, action: tapNotification) + if layoutKey == NCGlobal.shared.layoutViewFiles { + navigationItem.rightBarButtonItems = [select, notification] + } else { + navigationItem.rightBarButtonItems = [select] + } + } + guard layoutKey == NCGlobal.shared.layoutViewFiles else { return } + navigationItem.title = titleCurrentFolder + } + + func createMenuActions() -> [NCMenuAction] { +// guard let layoutForView = NCManageDatabase.shared.getLayoutForView(account: session.account, key: layoutKey, serverUrl: "") else { return [] } +// +// let select = UIAction(title: NSLocalizedString("_select_", comment: ""), image: .init(systemName: "checkmark.circle"), attributes: datasource.isEmpty ? .disabled : []) { _ in +// self.setEditMode(true) +// } +// +// let list = UIAction(title: NSLocalizedString("_list_", comment: ""), image: .init(systemName: "list.bullet"), state: layoutForView.layout == NCGlobal.shared.layoutList ? .on : .off) { _ in +// self.onListSelected() +//// self.setNavigationRightItems() +// } +// +// let grid = UIAction(title: NSLocalizedString("_icons_", comment: ""), image: .init(systemName: "square.grid.2x2"), state: layoutForView.layout == NCGlobal.shared.layoutGrid ? .on : .off) { _ in +// self.onGridSelected() +//// self.setNavigationRightItems() +// } +// +// let viewStyleSubmenu = UIMenu(title: "", options: .displayInline, children: [list, grid]) +// + return []//[select, viewStyleSubmenu] + } } diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index 797fba1e7c..8a0d7c0ab2 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -25,49 +25,59 @@ import UIKit import NextcloudKit +import Realm import RealmSwift -class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate { +class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate, NCEmptyDataSetDelegate { @IBOutlet weak var collectionView: UICollectionView! var filePath = "" var titleCurrentFolder = NSLocalizedString("_trash_view_", comment: "") var blinkFileId: String? + var dataSourceTask: URLSessionTask? let utilityFileSystem = NCUtilityFileSystem() let database = NCManageDatabase.shared let utility = NCUtility() var isEditMode = false - var selectOcId: [String] = [] + var fileSelect: [String] = [] var tabBarSelect: NCTrashSelectTabBar! var datasource: [tableTrash]? var layoutForView: NCDBLayoutForView? var listLayout: NCListLayout! var gridLayout: NCGridLayout! var layoutKey = NCGlobal.shared.layoutViewTrash + var layoutType = NCGlobal.shared.layoutList let refreshControl = UIRefreshControl() var filename: String? - - @MainActor var session: NCSession.Session { NCSession.shared.getSession(controller: tabBarController) } - + var controller: NCMainTabBarController? { self.tabBarController as? NCMainTabBarController } + var serverUrl = "" + var selectableDataSource: [RealmSwiftObject] { datasource ?? [] } + private let appDelegate = (UIApplication.shared.delegate as? AppDelegate)! + var emptyDataSet: NCEmptyDataSet? + // MARK: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() - navigationController?.setNavigationBarAppearance() + + tabBarSelect = NCTrashSelectTabBar(tabBarController: tabBarController, delegate: self) + serverUrl = utilityFileSystem.getHomeServer(session: session) view.backgroundColor = .systemBackground + self.navigationController?.navigationBar.prefersLargeTitles = true collectionView.register(UINib(nibName: "NCTrashListCell", bundle: nil), forCellWithReuseIdentifier: "listCell") collectionView.register(UINib(nibName: "NCTrashGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell") - collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") +// collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") + collectionView.register(UINib(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu") collectionView.register(UINib(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter") collectionView.alwaysBounceVertical = true @@ -78,25 +88,26 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // Add Refresh Control collectionView.refreshControl = refreshControl - refreshControl.tintColor = NCBrandColor.shared.textColor2 - refreshControl.action(for: .valueChanged) { _ in - Task { - await self.loadListingTrash() - } - } + refreshControl.tintColor = .gray + refreshControl.addTarget(self, action: #selector(loadListingTrash), for: .valueChanged) + + // Empty + emptyDataSet = NCEmptyDataSet(view: collectionView, offset: NCGlobal.shared.heightButtonsView, delegate: self) + + NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSource), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSource), object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(changeLayout(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeLayout), object: nil) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - if tabBarSelect == nil { - tabBarSelect = NCTrashSelectTabBar(controller: tabBarController, viewController: self, delegate: self) - } + appDelegate.activeViewController = self navigationController?.setNavigationBarAppearance() navigationItem.title = titleCurrentFolder layoutForView = self.database.getLayoutForView(account: session.account, key: NCGlobal.shared.layoutViewTrash, serverUrl: "") + gridLayout.column = CGFloat(layoutForView?.columnGrid ?? 3) if layoutForView?.layout == NCGlobal.shared.layoutList { collectionView.collectionViewLayout = listLayout @@ -105,32 +116,74 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat } isEditMode = false + setNavigationRightItems() + + reloadDataSource() + loadListingTrash(nil) + + AnalyticsHelper.shared.trackEvent(eventName: .SCREEN_EVENT__DELETED_FILES) - Task { - await (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() - await self.reloadDataSource() - await loadListingTrash() - } } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - Task { - await NCNetworking.shared.networkingTasks.cancel(identifier: "NCTrash") - } - // Cancel Queue & Retrieves Properties NCNetworking.shared.downloadThumbnailTrashQueue.cancelAll() + dataSourceTask?.cancel() + isEditMode = false + } + + override func viewWillLayoutSubviews() { + super.viewWillLayoutSubviews() + + if let frame = tabBarController?.tabBar.frame { + tabBarSelect.hostingController?.view.frame = frame + } + } + + // MARK: - Layout + + @objc func changeLayout(_ notification: NSNotification) { + guard let userInfo = notification.userInfo as NSDictionary?, + let account = userInfo["account"] as? String, + let serverUrl = userInfo["serverUrl"] as? String, + let layoutForView = userInfo["layoutForView"] as? NCDBLayoutForView, + account == session.account, + serverUrl == self.serverUrl + else { return } + + self.layoutForView = self.database.setLayoutForView(layoutForView: layoutForView) + layoutForView.layout = layoutForView.layout + self.layoutType = layoutForView.layout +// self.reloadDataSource() + collectionView.reloadData() + + switch layoutForView.layout { + case NCGlobal.shared.layoutList: + self.collectionView.setCollectionViewLayout(self.listLayout, animated: true) + case NCGlobal.shared.layoutGrid: + self.collectionView.setCollectionViewLayout(self.gridLayout, animated: true) + default: + break + } + + self.collectionView.collectionViewLayout.invalidateLayout() + } + + // MARK: - Empty + + func emptyDataSetView(_ view: NCEmptyView) { + view.emptyImage.image = UIImage(named: "trash")?.image(color: .gray, size: UIScreen.main.bounds.width) + view.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "") + view.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "") } // MARK: TAP EVENT - func tapRestoreListItem(with id: String, image: UIImage?, sender: Any) { + func tapRestoreListItem(with ocId: String, image: UIImage?, sender: Any) { if !isEditMode { - Task { - await restoreItem(with: id) - } + restoreItem(with: ocId) } else if let button = sender as? UIView { let buttonPosition = button.convert(CGPoint.zero, to: collectionView) let indexPath = collectionView.indexPathForItem(at: buttonPosition) @@ -158,34 +211,53 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat } } + func tapButtonSwitch(_ sender: Any) { + if layoutForView?.layout == NCGlobal.shared.layoutGrid { + onListSelected() + } else { + onGridSelected() + } + } + + func tapButtonOrder(_ sender: Any) { + + let sortMenu = NCSortMenu() +// sortMenu.toggleMenu(viewController: self, account: appDelegate.account, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl) + sortMenu.toggleMenu(viewController: self, account: session.account, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl) + } + func longPressGridItem(with objectId: String, gestureRecognizer: UILongPressGestureRecognizer) { } func longPressMoreGridItem(with objectId: String, gestureRecognizer: UILongPressGestureRecognizer) { } // MARK: - DataSource - func reloadDataSource(withQueryDB: Bool = true) async { - let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) - - await (self.navigationController as? NCMainNavigationController)?.updateRightMenu() - - await MainActor.run { - self.datasource = results - self.collectionView.reloadData() - - guard let blinkFileId = self.blinkFileId else { return } - - for itemIx in 0.. Bool { - let fileExtension = (metadata.fileNameView as NSString).pathExtension - guard let capabilities = NCNetworking.shared.capabilities[metadata.account], - !fileExtension.isEmpty, - let mimeType = UTType(tag: fileExtension.uppercased(), tagClass: .filenameExtension, conformingTo: nil)?.identifier else { + @objc func isSimulatorOrTestFlight() -> Bool { + guard let path = Bundle.main.appStoreReceiptURL?.path else { + return false + } + return path.contains("CoreSimulator") || path.contains("sandboxReceipt") + } + + func isSimulator() -> Bool { + guard let path = Bundle.main.appStoreReceiptURL?.path else { return false } + return path.contains("CoreSimulator") + } + func isTypeFileRichDocument(_ metadata: tableMetadata) -> Bool { + guard metadata.fileNameView != "." else { return false } + let fileExtension = (metadata.fileNameView as NSString).pathExtension + guard !fileExtension.isEmpty else { return false } + guard let mimeType = UTType(tag: fileExtension.uppercased(), tagClass: .filenameExtension, conformingTo: nil)?.identifier else { return false } /// contentype - if !capabilities.richDocumentsMimetypes.filter({ $0.contains(metadata.contentType) || $0.contains("text/plain") }).isEmpty { + if !NCCapabilities.shared.getCapabilities(account: metadata.account).capabilityRichDocumentsMimetypes.filter({ $0.contains(metadata.contentType) || $0.contains("text/plain") }).isEmpty { return true } - /// mimetype - if !capabilities.richDocumentsMimetypes.isEmpty && mimeType.components(separatedBy: ".").count > 2 { + if !NCCapabilities.shared.getCapabilities(account: metadata.account).capabilityRichDocumentsMimetypes.isEmpty && mimeType.components(separatedBy: ".").count > 2 { let mimeTypeArray = mimeType.components(separatedBy: ".") let mimeType = mimeTypeArray[mimeTypeArray.count - 2] + "." + mimeTypeArray[mimeTypeArray.count - 1] - if !capabilities.richDocumentsMimetypes.filter({ $0.contains(mimeType) }).isEmpty { + if !NCCapabilities.shared.getCapabilities(account: metadata.account).capabilityRichDocumentsMimetypes.filter({ $0.contains(mimeType) }).isEmpty { return true } } @@ -57,32 +68,39 @@ final class NCUtility: NSObject, Sendable { } func editorsDirectEditing(account: String, contentType: String) -> [String] { - var names: [String] = [] - let capabilities = NCNetworking.shared.capabilities[account] + var editor: [String] = [] + guard let results = NCManageDatabase.shared.getDirectEditingEditors(account: account) else { return editor } - capabilities?.directEditingEditors.forEach { editor in - editor.mimetypes.forEach { mimetype in + for result: tableDirectEditingEditors in results { + for mimetype in result.mimetypes { if mimetype == contentType { - names.append(editor.name) + editor.append(result.editor) } // HARDCODE // https://github.com/nextcloud/text/issues/913 if mimetype == "text/markdown" && contentType == "text/x-markdown" { - names.append(editor.name) + editor.append(result.editor) } if contentType == "text/html" { - names.append(editor.name) + editor.append(result.editor) } } - - editor.optionalMimetypes.forEach { mimetype in + for mimetype in result.optionalMimetypes { if mimetype == contentType { - names.append(editor.name) + editor.append(result.editor) } } } + return Array(Set(editor)) + } - return Array(Set(names)) + func permissionsContainsString(_ metadataPermissions: String, permissions: String) -> Bool { + for char in permissions { + if metadataPermissions.contains(char) == false { + return false + } + } + return true } func getCustomUserAgentNCText() -> String { @@ -106,11 +124,11 @@ final class NCUtility: NSObject, Sendable { } } - func isQuickLookDisplayable(metadata: tableMetadata) -> Bool { + @objc func isQuickLookDisplayable(metadata: tableMetadata) -> Bool { return true } - func ocIdToFileId(ocId: String?) -> String? { + @objc func ocIdToFileId(ocId: String?) -> String? { guard let ocId = ocId else { return nil } let items = ocId.components(separatedBy: "oc") @@ -119,19 +137,15 @@ final class NCUtility: NSObject, Sendable { return String(intFileId) } - func getVersionBuild() -> String { - if let dictionary = Bundle.main.infoDictionary, - let version = dictionary["CFBundleShortVersionString"], - let build = dictionary["CFBundleVersion"] { - return "\(version).\(build)" - } - return "" - } - - func getVersionMaintenance() -> String { - if let dictionary = Bundle.main.infoDictionary, - let version = dictionary["CFBundleShortVersionString"] { - return "\(version)" + @objc func getVersionApp(withBuild: Bool = true) -> String { + if let dictionary = Bundle.main.infoDictionary { + if let version = dictionary["CFBundleShortVersionString"], let build = dictionary["CFBundleVersion"] { + if withBuild { + return "\(version).\(build)" + } else { + return "\(version)" + } + } } return "" } @@ -269,16 +283,91 @@ final class NCUtility: NSObject, Sendable { return (usedmegabytes, totalmegabytes) } - func getHeightHeaderEmptyData(view: UIView, portraitOffset: CGFloat, landscapeOffset: CGFloat) -> CGFloat { + func getHeightHeaderEmptyData(view: UIView, portraitOffset: CGFloat, landscapeOffset: CGFloat, isHeaderMenuTransferViewEnabled: Bool = false) -> CGFloat { var height: CGFloat = 0 if UIDevice.current.orientation.isPortrait { height = (view.frame.height / 2) - (view.safeAreaInsets.top / 2) + portraitOffset } else { - height = (view.frame.height / 2) + landscapeOffset + height = (view.frame.height / 2) + landscapeOffset + CGFloat(isHeaderMenuTransferViewEnabled ? 35 : 0) } return height } + + // E-mail validations + // 1. Basic Email Validator (ASCII only) + func isValidEmail(_ email: String) -> Bool { + let emailRegex = "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}$" + let predicate = NSPredicate(format: "SELF MATCHES[c] %@", emailRegex) + return predicate.evaluate(with: email) + } + + // 2. Manually Convert Unicode Domain to Punycode with German Char Support + func convertToPunycode(email: String) -> String? { + guard let atIndex = email.firstIndex(of: "@") else { return nil } + + let localPart = String(email[.. String? { + // Mapping of common German characters to their corresponding Punycode equivalents + var punycodeDomain = domain.lowercased() + + let germanCharToPunycode: [String: String] = [ + "ü": "xn--u-1fa", // ü → xn--u-1fa + "ä": "xn--a-1fa", // ä → xn--a-1fa + "ö": "xn--o-1fa", // ö → xn--o-1fa + "ß": "xn--ss-1fa", // ß → xn--ss-1fa + "é": "xn--e-1fa", // é → xn--e-1fa + "è": "xn--e-1f", // è → xn--e-1f + "à": "xn--a-1f", // à → xn--a-1f + ] + + // Replace each German character with the corresponding Punycode equivalent + for (char, punycode) in germanCharToPunycode { + punycodeDomain = punycodeDomain.replacingOccurrences(of: char, with: punycode) + } + + // If no change occurred, return the domain as it is (i.e., no Punycode needed) + return punycodeDomain + } + + // 4. IDN Email Validator (handles Unicode domain by converting to Punycode) + func isValidIDNEmail(_ email: String) -> Bool { + // Convert domain part to Punycode and validate using basic email regex + guard let punycodeEmail = convertToPunycode(email: email) else { + return false + } + + return isValidEmail(punycodeEmail) + } + + // 5. Unified Email Validation - Check for both basic and IDN emails + func validateEmail(_ email: String) -> Bool { + if isValidEmail(email) { + print("Valid ASCII email: \(email)") + return true + } else if isValidIDNEmail(email) { + print("Valid IDN email: \(email)") + return true + } else { + print("Invalid email: \(email)") + return false + } + + } + func formatBadgeCount(_ count: Int) -> String { if count <= 9999 { return "\(count)" diff --git a/iOSClient/Utility/NYMnemonic/languages/english.txt b/iOSClient/Utility/NYMnemonic/languages/english.txt index 942040ed50..13755ac8cf 100755 --- a/iOSClient/Utility/NYMnemonic/languages/english.txt +++ b/iOSClient/Utility/NYMnemonic/languages/english.txt @@ -1,2048 +1,2305 @@ -abandon -ability -able -about -above -absent -absorb -abstract -absurd -abuse -access -accident -account -accuse -achieve -acid -acoustic -acquire -across -act +aal +abend +abendrot +abenteuer +aberglaube +abfahrt +abfall +abtei +achse +acht +achtung +achtzig +acidum +acker +ackerbau +ackerhof action -actor -actress -actual -adapt -add -addict -address -adjust -admit -adult -advance -advice -aerobic -affair -afford -afraid -again -age -agent -agree -ahead -aim -air -airport -aisle -alarm -album -alcohol -alert -alien -all -alley -allow -almost -alone -alpha -already -also -alter -always -amateur -amazing -among -amount -amused -analyst -anchor -ancient -anger -angle -angry -animal -ankle -announce -annual -another -answer -antenna -antique -anxiety -any -apart -apology -appear -apple -approve +ada +adam +adel +adenauer +ader +aderlass +adidas +adieu +adjektiv +adolph +adonis +adria +adverb +advokat +angina +angler +ansicht +antonio +antrag +antrieb +antritt +antwort +anwalt +apache +apartheid +apartment +aperitif +apfel +apfelmus +apfelsine +apfeltorte +apfelwein +aphorismus +aphrodite +apokalypse +apoll +apollo +apologeten +apostel +apostroph +apostrophs +apotheke +apparat april -arch -arctic -area +apropos +apsis +apulien +aquarell +aragon +arbeit +archimedes +architekt +archiv +arden +areal arena -argue +arenen +argau +arge +argentinien +arglist +argonaut +argosy +argument +argus +argusaugen +argwohn +ariane +arie +aristokrat +aristoteles +arithmetik +arizona +arkade +arkadenhof +arkansas +arktisforscher arm -armed -armor +armada +armagnac +armando +armaturen +armband +armee +armenien +armenier +armfluegeln +armhaltung +armhebel +armkettchen +armlehnen +armreif +arms +armseligkeit +armsessel +armstrong +armut army -around -arrange +arnica +arno arrest -arrive -arrow -art -artefact -artist -artwork -ask -aspect -assault -asset -assist -assume -asthma -athlete +arroganz +arsch +arterie +arthur +arzt +asbest +asien +aspirant +astrologe +astrologie +astronaut +astronomie +asyl +atelier +atem +atemzug +atheist +atheisten +atheistin +athen +athene +athlet atom -attack -attend -attitude -attract -auction -audit -august -aunt -author +aubergine +auch +audienz +audienzen +audrey +auen +auerhahn auto -autumn -average -avocado -avoid -awake -aware -away -awesome -awful -awkward -axis baby -bachelor -bacon -badge -bag -balance -balcony +bach +backup +backware +backwaren +bad +badetuch +bahamas +bahn +balearen +bali +balkan ball -bamboo -banana -banner -bar -barely -bargain -barrel -base -basic -basket -battle -beach -bean -beauty -because -become -beef -before -begin -behave -behind -believe -below -belt -bench -benefit -best -betray -better -between -beyond -bicycle -bid -bike -bind -biology -bird -birth -bitter -black -blade -blame -blanket -blast -bleak -bless -blind -blood -blossom -blouse -blue -blur -blush -board -boat -body -boil -bomb -bone -bonus -book -boost -border -boring -borrow -boss -bottom -bounce -box -boy -bracket -brain -brand -brass -brave -bread -breeze -brick -bridge +band +bank +barbar +barbara +bargeld +baron +basketball +batterie +bau +bauernhof +bauherr +baum +bazar +bazille +bedarf +beere +beet +behauptung +beifall +beine +beischlaf +beitrag +belfast +belgien +bengel +benzin +berg +bert +berta +bier +bild +billionen +billy +bindegewebe +bindeglied +birmingham +birne +blaubeere +blaubeertorte +blech +blei +bleibe +blume +blut +bonsai +boa +bob +bock +bombe +boot +bordell brief -bright -bring -brisk -broccoli -broken +bronchitis bronze -broom -brother -brown -brush -bubble -buddy -budget -buffalo -build -bulb -bulk -bullet -bundle -bunker -burden -burger -burst +buchkritik +buchmacher +buckingham +budapest +buddha +bude +buch +buechse +buechsen +bueffel +buegels +buehler +buehne +bungalow +burda +bureau +burg +burgenland bus -business -busy +butler butter -buyer -buzz -cabbage -cabin -cable -cactus -cage -cake -call -calm -camera -camp -can -canal -cancel -candy -cannon -canoe -canvas -canyon -capable -capital -captain -car -carbon -card -cargo -carpet -carry -cart -case -cash -casino -castle -casual -cat -catalog -catch -category -cattle -caught -cause -caution -cave -ceiling -celery -cement -census -century -cereal -certain -chair -chalk -champion -change -chaos -chapter -charge -chase -chat -cheap -check -cheese +buxtehude +cafe +cafeteria +calabrien +calamares +calcutta +carlo +carol +carola +carton +charakter +chefkoch chef -cherry -chest -chicken -chief -child -chimney -choice -choose -chronic -chuckle -chunk -churn -cigar -cinnamon -circle -citizen -city -civil -claim -clap -clarify -claw -clay -clean -clerk -clever -click -client -cliff -climb -clinic -clip -clock -clog -close -cloth -cloud +chemie +cheyenne +chiffre +chromosom +circus +citroen clown club -clump -cluster -clutch -coach -coast -coconut -code -coffee -coil -coin -collect -color -column -combine -come -comfort -comic -common -company -concert -conduct -confirm -congress -connect -consider -control -convince -cook -cool -copper -copy -coral -core -corn -correct -cost -cotton -couch -country -couple -course -cousin -cover -coyote -crack -cradle -craft -cram -crane -crash -crater -crawl -crazy -cream -credit -creek -crew -cricket -crime -crisp -critic -crop -cross -crouch -crowd -crucial -cruel -cruise -crumble -crunch -crush -cry -crystal -cube -culture -cup -cupboard -curious -current -curtain -curve -cushion -custom -cute -cycle -dad -damage -damp -dance -danger -daring -dash -daughter -dawn -day -deal -debate -debris -decade -december -decide -decline -decorate -decrease -deer -defense -define -defy -degree -delay -deliver -demand -demise -denial -dentist -deny -depart -depend -deposit -depth -deputy -derive -describe -desert -design -desk -despair -destroy +clubmaster +cocktail +comune +dach +dachbalken +dachboden +dackel +daemon +dammbruch +dampfbad +dante +danton +datenbank +daten +daumen +daune +daunen +david +deckblatt +deckel +decoder +defizit +deich +deichbauer +dekan +dekor +dekorateur +dekret +delikt +demokrat +demut +denkfehler +denkmal +denkspiel +depot +destillat detail -detect -develop -device -devote -diagram -dial -diamond -diary -dice +detektiv +detroit +dezember +dialog diesel -diet -differ -digital -dignity +diesellok +dieter +diether +dietrich +digitaluhr +diktat +diktatur dilemma -dinner -dinosaur -direct -dirt -disagree -discover -disease -dish -dismiss -disorder -display -distance -divert -divide -divorce -dizzy -doctor -document -dog -doll -dolphin -domain -donate -donkey -donor -door -dose -double -dove -draft -dragon +diplomat +direkt +disco +dogma +doktor +doktorarbeit +dokument +dolch +donald +donaudelta +doping +dorf +dorne +dosis +drache +drachenboot +dracula +draht +drahtzaun drama -drastic -draw -dream +drecksack +dreher +drehung +drehzahl +drei +dreieck +dreiklang dress -drift -drill -drink -drip -drive -drop -drum -dry -duck -dumb -dune -during -dust -dutch -duty -dwarf -dynamic -eager -eagle -early -earn -earth -easily -east -easy +droge +drogen +drogenbaron +dubios +dublin +duell +duft +duftnote +dumm +dunkel +dunkelheit +durst +dynamik +dynamit +ebenbild echo -ecology -economy -edge -edit -educate -effort -egg -eight -either -elbow -elder -electric -elegant -element -elephant -elevator -elite -else -embark -embody -embrace -emerge +echos +ecke +eden +edens +edinburgh +edison +editieren +editor +editorial +edmund +efeu +efeus +effekt +egal +ehebruch +ehefrau +ehezwist +ehre +eiche +eichel +eid +eidechsen +eier +eierschale +eifel +eifer +eifersucht +eiffelturm +eigenheim +eigenleben +eigensinn +eile +eilgut +eiltempo +eimer +einband +einbau +einbruch +eingabe +einheit +einhorn +einklang +einladung +einlagen +einsamkeit +einsatz +einschlag +einschuss +einzelfall +eis +eisbaer +eisbecher +eisberg +eisbombe +eisdiele +eisen +eisenbahn +ekel +elektro +elektrik +elend +elfenbein +elsass +eltern +elternbeirat +email +emanuel +emanuela +emanzipation +embargo +emblem +embolie +embyro +emilia +eminenz +eminenzen emotion -employ -empower -empty -enable -enact -end -endless -endorse -enemy -energy -enforce -engage -engine -enhance -enjoy -enlist -enough -enrich -enroll -ensure -enter -entire -entry -envelope -episode -equal -equip -era -erase -erode +ende +endrunde +endung +endungen +engel +england +enkel +enkelin +entgelt +erbgut +erdoel +erhalt +erhaltes +erhaltung +erich +erika +eritrea +erkaeltung +erkenntis +ernte +eros erosion -error -erupt -escape -essay -essence -estate -eternal -ethics -evidence -evil -evoke -evolve -exact -example -excess -exchange -excite -exclude -excuse -execute -exercise -exhaust -exhibit -exile -exist -exit -exotic -expand -expect -expire -explain -expose -express -extend -extra -eye -eyebrow -fabric -face -faculty -fade -faint -faith +erst +erzeugung +eskorte +essig +etat +eule +exil +fabel +fabian +fabrik +fabrikant +faden +fahne +fahrgast +fahrer +fahrgeld +fahrrad +falke fall -false -fame -family -famous -fan -fancy -fantasy +fallbeil +falle +fallobst +fallschirm +faltboot +faltdach +fantasie +farbe farm -fashion -fat -fatal -father -fatigue -fault -favorite -feature -february -federal -fee -feed -feel -female -fence +farmer +farn +faruk +fasan +fass +fassade +fatalismus +fatalitaet +faulenzer +faulpelz +fauna +faust +favorit +fazit +fechter +feder +federung +fegefeuer +fehde +fehler +fehlmenge +feier +feierabend +feiertag +feigling +feind +feinkost +felder +felge +felix +fell +fenchel +fenster +fensterbank +ferien +fernglas +fernost +fernseher +fernsicht +fernweh +ferrari +festakt +festakte festival -fetch -fever -few -fiber -fiction -field +fett +feuer +feueralarm +feuerwerk +fiasko +fiat +fieber figure -file +fiktion film -filter -final -find -fine +filz +fimmel +finale +finanzhai +finderlohn finger -finish -fire -firm -first -fiscal -fish -fit +fink +firlefanz +firma +firmament +fisch +fischerboot +fischfang fitness -fix -flag -flame -flash -flat -flavor -flee -flight -flip -float -flock -floor -flower -fluid -flush -fly -foam -focus -fog -foil -fold -follow -food -foot -force -forest -forget -fork -fortune -forum -forward +flagge +fleiss +fleisch +fliege +fliegen +fliegenpilz +fliese +flinte +flipper +flirt +flo +flop +flora +florenz +florett +florida +floskel +flotte +flucht +fluchtauto +fluchtburg +flug +flugabwehr +flughafen +flunder +fluss +flusspferd +flutwelle +foen +folklore +folter +folterbank +folterknecht +forschung +forst +forstamt fossil -foster -found -fox -fragile -frame -frequent -fresh -friend -fringe -frog -front -frost -frown -frozen -fruit -fuel -fun -funny -furnace -fury -future -gadget -gain -galaxy -gallery -game -gap +foto +fotoapparat +foulspiel +foyer +fracht +frack +fragment +frankfurt +franzose +fratze +frei +freibier +freiheit +freitag +freizeit +freske +freude +freund +frevel +frieden +friesland +frikadelle +friseur +frist +frohnatur +frohsinn +frosch +frucht +fruehjahr +frust +fuchs +fuenf +furie +fuss +gabe +galaxie +galeere +galerie +galgen +galilei +galizien garage -garbage -garden -garlic -garment +garten +gartenzwerg gas -gasp -gate -gather -gauge -gaze -general -genius -genre -gentle -genuine -gesture -ghost -giant +gast +gasthof +gauda +gaudi +gaul +gaukler +gaumen +gauner +gazelle +geburtstag +gedanke +geduld +gefaengnis +gefecht +gehirn +geier +geist +geizhals +georg +getto +gewehr +ghetto gift -giggle -ginger -giraffe -girl -give -glad -glance -glare -glass -glide -glimpse -globe -gloom -glory -glove -glow -glue -goat -goddess -gold -good -goose +gina +gleis +glueck gorilla -gospel -gossip -govern -gown -grab -grace -grain -grant -grape -grass -gravity -great -green -grid -grief -grit -grocery -group -grow -grunt -guard -guess -guide -guilt -guitar -gun -gym -habit -hair -half -hammer -hamster -hand -happy -harbor -hard -harsh -harvest -hat -have -hawk -hazard -head -health -heart -heavy -hedgehog -height -hello -helmet -help -hen -hero -hidden -high -hill -hint -hip -hire -history -hobby -hockey -hold -hole -holiday -hollow -home -honey -hood -hope -horn -horror -horse -hospital -host +guido +gummi +gurke +gurkensalat +gurt +guru +haar +hafen +haft +haftbefehl +halbmond +halogen +hals +handball +handbremse +handgelenk +handtasche +hannelore +hantel +harlekin +harmonie +haschisch +harz +hausarrest +hausarzt +hausschwein +haut +hawaii +heck +heckteil +hehler +heike +heimat +heino +heinrich +heinz +heirat +hektik +held +helsinki +hemd +herbert +herbst +herz +heuchler +hexen +hexerei +himalaja +himalaya +himbeere +himmel +hindu +hintergrund +hintern +hippie +hippodamus +hippodrom +hirn +hitze +hobbie +hochmut +hoftor +hoheit +hollywood +holz hotel -hour -hover -hub -huge -human -humble -humor -hundred -hungry -hunt -hurdle -hurry -hurt -husband -hybrid -ice -icon -idea -identify -idle -ignore -ill -illegal -illness -image -imitate -immense -immune -impact -impose -improve -impulse -inch -include -income -increase +hubraum +huehnerdieb +huf +hund +hygiene +hymne +hypnose +idee +ignoranz +imbiss +immobilie +import index -indicate -indoor -industry -infant -inflict -inform -inhale -inherit -initial -inject -injury -inmate -inner -innocent -input -inquiry -insane -insect -inside -inspire -install -intact -interest -into -invest -invite -involve -iron -island -isolate -issue -item -ivory -jacket +indianer +indikator +induktion +industrie +infarkt +infekt +infektion +inferno +information +inka +inkasso +innovation +innsbruck +insasse +insekt +insekten +insel +inselstaat +instanz +instinkt +institut +instrument +intelligenz +intellekt +interesse +irak +iran +irrenhaus +irrsinn +irrtum +italien +ivan +jacht +jachtklub +jacke +jacob +jagd jaguar -jar +jahr +jahrbuchs +jahre +jahrmarkt +jahrzehnt +japan jazz -jealous -jeans -jelly -jewel -job -join -joke -journey -joy -judge -juice -jump -jungle -junior -junk -just -kangaroo -keen -keep -ketchup -key -kick -kid -kidney +jazzband +joker +jongleur +jordanien +josef +jubel +jucken +judo +judoka +jugend +junge +jurist +kabarett +kabel +kabine +kabrio +kabriolett +kabuki +kabul +kadaver +kader +kaernten +kaese +kaffee +kafka +kairo +kaiser +kakao +kaktee +kaktus +kalabrien +kalauer +kalb +kali +kalk +kalkulation +kalkutta +kalzium +kambodscha +kamel +kamera +kamerad +kamikaze +kamille +kamin +kanada +kanaille +kanal +kannibale +kanzlei +kapitol +kapitulation +kaplan +kappe +kapsel +kapuze +karambolage +karate +karosse +karosserie +karotte +karriere +karte +kartei +kartell +kartenspiel +Kartoffel +kartoffelbrei +karton +kasino +kaskade +kasko +kasse +kassel +kastanie +kastell +katamaran +katastrophe +katze +katzenauge +kehle +keim +kennziffer +kent +kentucky +keramik +kerbe +kerbel +kessel +kette +ketzer +keule +kiesgrube +killer +kilo +kilogramm +kilometer +kilowatt kind -kingdom -kiss -kit -kitchen -kite -kitten -kiwi -knee -knife -knock -know -lab -label +kinder +kirchturm +kirschbaum +kirsche +kitzel +klamotten +klang +klar +klarheit +klarinette +klartext +klassik +klausel +klavier +klee +kleider +klima +klinik +klischee +klo +klopapier +kloster +klotz +klub +knallfrosch +kneipe +knete +knetmasse +knick +knie +kniff +knoblauch +knochen +knopf +knopfloch +knospe +kobalt +kobold +kobra +kochbuch +koerper +koffein +koffer +kohle +kokain +kollege +kombi +kombination +komma +kommandant +kommando +kommentar +kommerz +kommissar +kommode +kommune +kompetenz +komplott +kompost +konfekt +konfetti +konflikt +kongo +konkurs +konrad +konsens +konsulat +konvoi +kopfball +kopie +kork +kottelet +krabbe +krach +kraehe +kraft +kraftakt +krakau +kralle +kram +krampf +kran +krankenhaus +krebs +kredit +krefeld +kreide +kreis +krempe +krempel +kreole +kresse +kreta +kreuz +kreuzberg +kreuzung +krieg +krim +krimi +kriminalbeamte +kriminalbeamtin +krippe +krise +krishna +kristall +kritik +kuba +kubanerin +kuckuck +kueche +kufe +kugel +kugellager +kultur +kumulation +kundin +kundschaft +kunst +kurbel +kurbelwelle +kybernetik labor -ladder -lady -lake -lamp -language -laptop -large -later -latin -laugh -laundry +laborant +laborleiter +labrador +labyrinth +lachs +laderaum +ladung +lage +lager +lagune +lamborghini +lamelle +lametta +lamm +lampe +landau +landgut +landung +landzunge +langeweile +languste +lanzarote +last +lauch +lauge +laune +lautsprecher lava -law -lawn -lawsuit -layer -lazy -leader -leaf -learn -leave -lecture -left -leg -legal -legend -leisure -lemon -lend -length -lens +lavendel +lawine +layout +lazarett +legierung +legion +leguan +lehre +lehrer +leiche +leierkasten +leim +leine +leinen +leinwand +leitern +lektion +lektorin +lemming +leonie +leonore leopard -lesson -letter -level -liar -liberty -library -license -life -lift -light -like -limb -limit -link -lion -liquid -list -little -live -lizard -load -loan -lobster -local -lock -logic -lonely -long -loop -lottery -loud -lounge -love -loyal -lucky -luggage -lumber -lunar -lunch -luxury -lyrics -machine -mad -magic -magnet -maid -mail -main -major -make -mammal -man -manage -mandate -mango -mansion -manual -maple -marble -march -margin +leopold +lerche +lermming +lettland +leuchtturm +libanon +libelle +libyen +licht +lichtung +lid +liebe +lied +lieferung +limonade +linienbus +linsensuppe +linz +lippe +lizenz +lorbeer +loreley +lorenzo +luder +ludwigshafen +luebeck +luegner +luegnerin +luemmel +lueneburg +luft +luftabwehr +lugano +luke +luna +luxus +macher +macht +machtwort +macke +madonna +madrid +maedchen +mafia +magazin +magnetspule +mai +mainz +mais +maiskolben +malaria +malediven +maler +mammon +mammut +mandel +mandelbaum +manitu +manko +mann +manschette +mantel +manuela +marburg marine -market -marriage -mask -mass -master -match +marita +mark +markt +marmor +marokko +marquise +marrakesch +mars +mascarpone +masche +maschine +maschinenbau material -math -matrix -matter -maximum -maze -meadow -mean -measure -meat -mechanic -medal -media -melody -melt -member -memory -mention -menu -mercy -merge -merit -merry -mesh -message -metal -method -middle -midnight -milk -million -mimic -mind -minimum -minor -minute -miracle -mirror -misery -miss -mistake -mix -mixed -mixture -mobile -model -modify -mom -moment -monitor -monkey -monster -month -moon -moral -more -morning -mosquito -mother -motion +materie +mathematik +matratze +medikament +medizin +meer +melodie +melone +mensch +mercedes +merkmal +metall +metropole +metropolis +metzger +michelangelo +migraene +mikado +minderheit +mineral +minus +module +moebel +mondlandung motor -mountain -mouse -move -movie -much -muffin -mule -multiply -muscle +motorblock +muecke +muenze +muschi museum -mushroom -music -must -mutual -myself -mystery -myth -naive -name -napkin -narrow -nasty -nation -nature -near -neck -need -negative -neglect -neither -nephew -nerve -nest -net -network -neutral -never -news -next -nice -night -noble -noise -nominee -noodle +mustang +mutation +mutti +nachbar +nachricht +nachtleben +nadelholz +nagasaki +nagel +nagellack +nahrung +nairobi +nase +nasenbein +nationalpark +natur +nazi +neapel +nebel +nebraska +nebukadnezar +neckar +neffe +negativ +nepal +netz +netzanschluss +neubau +neujahrstag +neumond +neun +nickel +nie +niete +nikolaus +nikotin +nordpol +norm normal -north -nose -notable -note -nothing -notice -novel -now -nuclear -number -nurse -nut -oak -obey -object -oblige -obscure -observe -obtain -obvious -occur -ocean -october -odor -off -offer -office -often -oil -okay -old -olive -olympic -omit -once -one -onion -online -only -open -opera -opinion -oppose -option +normanne +norwegen +nostalgie +not +notar +notausgang +nudel +nudelholz +nylon +oberst +oberteil +objekt +obligation +ofen +ofenheizung +ohren +oktober +oldtimer +oleg +olga +oligarch +oliven +oliver +olymp +olympia +opa +opel +operette +oper +opium +opiumkrieg +optiker +opus orange -orbit -orchard -order -ordinary -organ +orden +ordner +ordnung +oregon +organe +organen +organleiden +orgel orient -original -orphan -ostrich -other -outdoor -outer -output -outside -oval -oven -over -own -owner -oxygen -oyster -ozone -pact -paddle +orion +orkan +orlando +orleans +ornament +ortschaft +oscar +osiris +oskar +oslo +osnabrueck +ostern +otter +otto +ouvertuere +ovation +ozean +ozeandampfer +ozonschicht +paella +paganini page -pair -palace -palm -panda -panel -panic -panther -paper -parade -parent +paket +palaver +palermo +palette +palisade +palladium +panzerkreuzer +panzer +papa +papagalli +papagallo +papagei +papierkorb +pappe +pappeln +paradies +paraguay +parameter +parasit +pardon +parfuem park -parrot +parkallee +parkhaus +parkplatz +parkuhr +parkverbot +parlament +parole +paroli +partei party -pass -patch -path +partyraum +paruguay +parzelle +passau +passfoto +patent patient -patrol -pattern -pause -pave -payment -peace -peanut -pear -peasant -pelican -pen -penalty -pencil -people -pepper -perfect -permit +paul +paulette +paulus +pauschal +pavian +pavillon +pazifik +pelikan +pellkartoffel +pelz +peng person -pet -phone +peru +peruecke +perversion +pest +peter +petersilie +pfadfinder +pfalz +pfand +pfannkuchen +pfarrer +pfeil +pferch +pferd +pfirsich +pflaster +pflasters +pflegerin +pfoertner +phaenomen +phalanx +phantast +pharao +pharma +pharmazie +phase +phasen +philippsburg +philosoph +philosphie +phlegma +phon +phonetik photo -phrase -physical -piano -picnic -picture -piece -pig -pigeon -pill -pilot -pink -pioneer -pipe -pistol -pitch -pizza -place -planet -plastic -plate -play -please -pledge -pluck -plug -plunge -poem -poet -point -polar -pole +pianist +piazza +picasso +pickelgesicht +picknick +piemont +pietaet +pigment +pils +pingpong +pinguin +pinie +pinsel +pinselstrich +pinzette +pionier +pirat +piraten +pirelli +pirmasens +piroschka +plagiat +plagiator +plakat +plankton +planquadrat +planzahl +plasma +plastik +plateau +platin +pluralismus +plus +plutarch +pluto +plutonium +plymouth +pokalsieg +pokerspiel +pol +polareis +polarfuchs +polaris police -pond -pony -pool -popular -portion +polier +poliklinik +politur +polle +pollen +pomp +pompadour +pompeij +pomps +porsche +portwein +porzellan position -possible post -potato -pottery -poverty -powder -power -practice -praise -predict -prefer -prepare -present -pretty -prevent -price -pride -primary -print -priority -prison -private -prize +poster +postfach +postille +postkarte +potzblitz +praefekt +praeparat +praxis +prellung +premier +premiere +presse +priester problem -process -produce +produkt +produzent +profession +professor +professur +profiboxer +profil +profilneurose profit -program -project -promote -proof -property -prosper -protect -proud -provide -public -pudding -pull -pulp -pulse -pumpkin -punch -pupil -puppy -purchase -purity -purpose -purse -push -put -puzzle -pyramid -quality -quantum -quarter -question -quick -quit +prognose +programm +projekt +projektion +prokura +promille +prominenz +propeller +prophet +provision +pruefung +pruegel +puffer +punsch +pupillen +puppe +pyjama +pyramide +qualitaet +qualle +qualm +quartal +quasar +quatsch +quattro +quebec +quitte +quitten +quittungen quiz -quote -rabbit -raccoon -race -rack +rabe +rache +racheakt radar -radio -rail -rain -raise -rally -ramp -ranch -random -range -rapid -rare -rate -rather -raven -raw -razor -ready +radarschirm +radioskop +radium +raetsel +raffinerie +raffinesse +rahm +rahmen +rampe +rampenlicht +rang +rasse +rastatt +raster +rastplatz +ratte +rattengift +raudi +raumschiff +rauschgift +ravenna +ravensberg real -reason -rebel -rebuild -recall -receive -recipe -record -recycle -reduce -reflect -reform -refuse -region -regret -regular -reject -relax -release -relief -rely -remain -remember -remind -remove -render -renew -rent -reopen -repair -repeat -replace -report -require -rescue -resemble -resist -resource -response -result -retire -retreat -return -reunion -reveal -review -reward -rhythm -rib -ribbon -rice -rich -ride -ridge -rifle -right -rigid -ring -riot -ripple -risk -ritual -rival -river -road -roast -robot -robust -rocket -romance -roof -rookie -room +reale +rebell +rechner +rechtsform +redner +reflektion +reflex +regal +regel +regenwald +regenwurm +reinfall +reis +reise +reiz +reklame +rekrut +reparatur +reporter +reporterin +reservat +reserve +reservebank +respekt +ressort +rettich +revolutuion +revolver +rhythmus +riad +rialto +ribbentrop +rind +risiko +rivale +rivalin +robbe +robert +roberta +robin +roboter +rolle rose -rotate -rough -round -route -royal -rubber -rude -rug -rule -run -runway -rural -sad -saddle -sadness -safe -sail -salad -salmon +rund +rundfunk +russe +spiegel +saatgut +sabotage +saboteur +sachbuch +sack +sackgasse +saeugling +safari +safran +saftladen +saite salon -salt -salute -same -sample -sand -satisfy -satoshi -sauce -sausage -save -say -scale -scan -scare -scatter -scene -scheme -school -science -scissors -scorpion -scout -scrap -screen -script -scrub -sea -search -season -seat -second -secret -section -security -seed -seek -segment -select -sell -seminar -senior -sense -sentence -series -service -session -settle -setup -seven -shadow -shaft -shallow -share -shed -shell -sheriff -shield -shift -shine -ship -shiver -shock -shoe -shoot -shop -short -shoulder -shove -shrimp -shrug -shuffle -shy -sibling -sick -side -siege -sight -sign -silent -silk -silly -silver -similar -simple -since -sing -siren -sister -situate -six -size -skate -sketch -ski -skill -skin -skirt -skull -slab -slam -sleep -slender -slice -slide -slight -slim -slogan -slot -slow -slush -small -smart -smile -smoke -smooth -snack -snake -snap -sniff -snow -soap -soccer -social -sock +saloniki +sambia +samen +samenbank +sammlung +sanddorn +sandsack +sanftmut +sansibar +sardine +sarg +sarkasmus +satan +satire +sattel +schachspiel +schach +schachtel +schaden +schafe +schandmaul +schanghai +scharade +schatten +schatulle +schatz +schatzamt +schaumbad +scheck +scheidung +schein +scheintod +scheitel +schenkel +scherbe +scherzartikel +schick +schickeria +schicksal +schiebedach +schiffbau +schild +schilf +schirm +schinken +schlachtschiff +schlamassel +schlamm +schlampe +schlauch +schlauchboot +schleim +schlitzohr +schloss +schlosser +schluckauf +schlummer +schmerz +schmerzen +schmuggler +schmusekatze +schmutz +schnake +schnaps +schnapsglas +schnapsidee +schneehase +schneekette +schnee +schnitzel +schnitzerei +schnulze +schnurrbart +schock +schotte +schrank +schranke +schreck +schreibpult +schritt +schrott +schuh +schulden +schuljahr +schuss +schuster +schutz +schwager +schwalbe +schwamm +schwan +schwinger +seebaer +seenot +segen +segler +seide +seife +semester +semikolon +sender +serie +sidnay +sie +sieben +sieger +siegerin +signatur +sigrid +sigrun +silbe +silber +simbabwe +simulant +sintflut +sinus +sinuskurve +sirene +sizilianer +skelett soda -soft -solar -soldier -solid -solution -solve -someone -song -soon -sorry -sort -soul -sound -soup -source -south -space -spare -spatial -spawn -speak -special -speed -spell -spend -sphere -spice -spider -spike -spin -spirit -split -spoil -sponsor -spoon +sodawasser +sodbrennen +sodomie +solarzelle +sommer +sommertag +sommerurlaub +sommerzeit +sonne +sonnenfleck +sonntag +spalt +spatel +spaten +specht +spekulation +sphinx +spiegel +spiel +spielbeginn +spinner +spinnrad +spion +spionin +spirale +spital +spitzmaus +spitzname +spleen +spore +sporn +sportbund sport -spot -spray -spread -spring -spy -square -squeeze -squirrel -stable +sportwagen +spreu +sprichwort +sprung +staat +staatsanwalt +staatsbesuch stadium -staff -stage -stairs -stamp +stadt +staffel +staffelei +stamm +stammaktie stand -start -state -stay +standard +statut +statuten +staub +stausee steak -steel -stem -step +steinmetz stereo -stick -still -sting -stock -stomach -stone -stool -story -stove -strategy -street -strike -strong -struggle -student -stuff -stumble -style -subject -submit -subway -success -such -sudden -suffer -sugar -suggest -suit -summer -sun -sunny -sunset -super -supply -supreme -sure -surface -surge -surprise -surround -survey -suspect -sustain -swallow -swamp -swap -swarm -swear -sweet -swift -swim -swing -switch -sword +sternbild +stettin +steuer +stichflamme +stift +strahl +strasse +sturmflut +sydney +sylt +sylvester +symbiose symbol symptom -syrup +syndikat system -table -tackle +szenario +taeter +tafel tag -tail +tagbau talent -talk +taler +talg +talgdruese +tanger +tango +tangs tank -tape -target -task +tankanlage +tankwart +tante +tanzbaer +tara +tarantel +tarif +taschendieb +tasse taste -tattoo +tatare +tartaria +tatendrang +tatort +tatze +tau +taube +taucher +tausch +tausend taxi -teach +taxifahrer team -tell -ten -tenant -tennis -tent -term -test +teamarbeit +technics +technikerin +teddybaer +teekanne +teenager +teheran +teich +teil +teilchen +teilnahme +teint +telefon +temperatur +teneriffa +tenor +teppich +termin +terminal +terrine +terror +texas text -thank -that -theme -then -theory -there -they -thing -this -thought -three -thrive -throw -thumb -thunder +thailand +theater +theke +thema +thematik +theo +theodor +theologe +theorie +therapeut +therapie +theresa +therese +thermalbad +thesaurus +these +thomas +thriller +thunfisch +thymian +tibet +tick ticket -tide -tiger -tilt -timber -time -tiny -tip -tired -tissue -title -toast -tobacco -today -toddler -toe -together -toilet -token -tomato -tomorrow -tone -tongue -tonight -tool -tooth -top -topic -topple -torch -tornado -tortoise -toss +tiegel +tier +tierarzt +tilsiter +tinte +tintenfass +tintenfisch +tintenfleck +tippzettel +tips +tirol +tischler +titan +titanic +titel +titelbild +tivoli +toaster +tobak +tobsucht +todfeind +tofu +toilette +tokio +toleranz +tollwut +tolpatsch +tomaten +tonlage +tonleiter +tonnage +tonne +tonspur +tor +torchance +torpedo +torpedoboot +torraum +tortur total +toulouse +tour +tourenrad tourist -toward -tower -town -toy -track -trade -traffic -tragic -train +tournee +toyota +trab +trabant +tracht +tradition +trafalgar +tragbahre +tragik +trainer +trakt +traktor +tramper +trance transfer -trap -trash -travel -tray -treat -tree +transport +trapez +tratte +trauer +traum +trauma +traumberuf +treffen +treffer +treiber +treibhaus +treibsand +treibstoff trend -trial -tribe +trennung +trennwand +treppe +tresen +tresor +treue +treueid +treuhand +tribun trick -trigger -trim -trip -trophy -trouble -truck -true -truly -trumpet -trust -truth -try -tube -tuition -tumble -tuna +trickfilm +triebwerk +triest +trikot +trilogie +trinkgeld +tripolis +tritt +triumpf +triumph +troja +trojaner +trommelfell +trommler +trompeter +tropen +trottel +trubel +truhe +truppe +tschernobyl +tuberkulose +tuebingen +tuemmler +tuer +tuerkei +tuete +tugend +tulpe +tumult +tundra +tunesien +tunichtgut tunnel -turkey -turn -turtle -twelve -twenty -twice -twin -twist -two +turban +turbine +turbo +turm +turner +turnerin +turnier +tusch +tycoon +typ type -typical -ugly -umbrella -unable -unaware -uncle -uncover -under -undo -unfair -unfold -unhappy +typografie +tyrann +tyrannei +ufo +uebung +ufer +uganda +uhrwerk +uhrzeit +uhu +ukraine +umfrage +umkehr +umkreis +umleitung +umschau +umschrift +umschweif +umweg +umzug +unfall +unfug +ungarn +ungeduld +ungeheuer +unhold uniform -unique -unit -universe -unknown -unlock -until -unusual -unveil -update -upgrade -uphold -upon -upper -upset -urban -urge -usage -use -used -useful -useless -usual -utility -vacant -vacuum -vague -valid -valley -valve -van -vanish -vapor -various -vast -vault -vehicle -velvet -vendor -venture -venue +unikum +universal +universum +unterholz +unterleib +unternehmer +unterricht +untertan +unterteil +unzucht +uran +urkunde +urlaub +urmensch +urne +ursache +urteil +urwald +urwelt +urzeit +utopie +utrecht +vagabund +vampir +vandale +vanille +variation +vasall +vater +vatikan +vehemenz +vehikel +veilchen +vene +venedig +venezuela +ventilator +ventil +venus +verachtung +veranda verb -verify -version -very -vessel +verband +verbleib +verblendung +verbot +verbrecher +verbund +verdienst +verdun +verehrer +verein +verfall +verfasser +vergleich +verhalten +verhandlung +verkehr +verlag +verlust +verona +verputz +verrat +verse +vertrag +verwalter +verwalterin +verzehr +verzicht +verzug veteran -viable -vibrant -vicious -victory +veto +vetorecht +viadukt +vibration +victor video -view -village -vintage -violin -virtual -virus +vieh +viertel +vignette +viktoria +viktualie +villa +viola +violine +viper +viren +virginia visa -visit -visual -vital -vivid -vocal -voice -void -volcano -volume -vote -voyage -wage -wagon -wait -walk +visage +visier +vision +visum +vitamin +vitrine +vogel +vogt +vokabel +vokal +volk +volleyball +vollmond +volt +voltaire +vorbild +votum +voyeur +vulkan +wachs +wachtstum +wade +waehrung +waffe +waffel +wagemut +waggon +waise +wal +wald wall -walnut -want -warfare -warm -warrior -wash -wasp -waste -water -wave -way -wealth -weapon -wear -weasel -weather -web -wedding -weekend -weird -welcome -west -wet -whale -what -wheat -wheel -when -where -whip -whisper -wide -width -wife -wild -will -win -window -wine -wing -wink -winner +wallach +walter +walther +wand +wanne +warze +wassermann +weber +wecker +wehmut +weib +weinblatt +weizen +welle +welpe +welt +weltall +werbung +werft +werk +werkstoff +werktag +wermut +wert +wertung +werwolf +wesen +weser +wespe +wespennest +weste +westfalen +westwind +wette +wetter +whisky +wicht +wichtig +wickel +widder +widmung +wiedergabe +wiesel +wiener +wildwest +wille +willi +willy +wimpel +wimper +wind +windbeutel +windhose +windhund +winkel winter -wire -wisdom -wise -wish -witness +winterthur +wippe +wirbelwind +wirkung +wirrwarr +wirt +wirtshaus +wischer +witterung +witwe +witz +wladimir +woche +woelbung wolf -woman -wonder -wood -wool -word -work -world -worry -worth -wrap -wreck -wrestle -wrist -write -wrong -yard -year -yellow -you -young -youth +wohnsitz +wohnung +wolfgang +wolfram +wolfsburg +wolfshund +wolke +wolga +wolle +wollust +worms +wort +wrack +wucher +wucht +wunde +wunder +wurf +wurm +wurzel +wut +xerox +xerxes +xylograph +yacht +yangtse +yen +yeti +yoga +yokohama +yuppie +zack +zaehler +zahl +zahn +zahnarzt +zahnaerztin +zahnersatz +zahnfleisch +zahngold +zahnluecke +zahnpaste +zahnpflege +zahnrad +zahnschmelz +zange +zapfenstreich +zar +zarathustra +zauber +zauberei +zaum +zaun +zaunkoenig zebra +zeche +zeh +zehner +zeichen +zeichnung +zeigefinger +zeiger +zeile +zeit +zeitalter +zeitbombe +zeitung +zeitgeist +zelle +zellkern +zeltdach +zelt +zement +zensur +zentner +zentral +zentrum +zeppelin +zepter +zeremonie +zerfall zero +zettel +zeuge +zeugin +zeus +zicke +ziege +ziegel +ziffer +zigarette +zigarillo +zigarre +zigeuner +zigeunerin +zikade +zimmer +zimmermann +zimt +zinne +zinnsoldat +zins +zirkel +zisterne +zitadelle +zitat +zivilist +zoll +zombie zone zoo +zopf +zorro +zucht +zucker +zuegel +zugabe +zukunft +zunge +zuruf +zustand +zuzug +zwang +zweifel +zwerg +zwerchfell +zwilling +zwinger +zwist +zyanid +zyankali +zyklon +zyklop +zyklus +zylinder +zyniker +zypern +zypresse + +zyste diff --git a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift index 76829d0592..6ed1d5bd7c 100644 --- a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift +++ b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift @@ -24,6 +24,7 @@ import UIKit import MapKit import NextcloudKit +import Alamofire public protocol NCViewerMediaDetailViewDelegate: AnyObject { func downloadFullResolution() @@ -208,6 +209,7 @@ class NCViewerMediaDetailView: UIView { } if metadata.isImage && !utilityFileSystem.fileProviderStorageExists(metadata) && metadata.session.isEmpty { + downloadImageButton.tintColor = NCBrandColor.shared.brand downloadImageButton.setTitle(NSLocalizedString("_try_download_full_resolution_", comment: ""), for: .normal) downloadImageLabel.text = NSLocalizedString("_full_resolution_image_info_", comment: "") downloadImageButtonContainer.isHidden = false diff --git a/iOSClient/Viewer/NCViewerQuickLook/NCViewerQuickLook.swift b/iOSClient/Viewer/NCViewerQuickLook/NCViewerQuickLook.swift index c2d0f4d631..c0f1df1ef3 100644 --- a/iOSClient/Viewer/NCViewerQuickLook/NCViewerQuickLook.swift +++ b/iOSClient/Viewer/NCViewerQuickLook/NCViewerQuickLook.swift @@ -178,7 +178,7 @@ private var hasChangesQuickLook: Bool = false toolbarConfig.optionButtonFontSize = 16 toolbarConfig.optionButtonFontSizeForPad = 21 toolbarConfig.backgroundColor = .systemGray6 - toolbarConfig.foregroundColor = .systemBlue + toolbarConfig.foregroundColor = NCBrandColor.shared.customer var viewConfig = CropViewConfig() viewConfig.cropMaskVisualEffectType = .none