diff --git a/.xcode-version b/.xcode-version index adbc6d2b1..6dfe8b129 100644 --- a/.xcode-version +++ b/.xcode-version @@ -1 +1 @@ -15.1 +14.3.1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e3cc2f33..a17eb41f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,5 @@ # Table of Contents -* [Changelog for 12.1.0](#changelog-for-owncloud-ios-client-1210-2024-01-29) * [Changelog for 12.0.3](#changelog-for-owncloud-ios-client-1203-2023-08-31) * [Changelog for 12.0.2](#changelog-for-owncloud-ios-client-1202-2023-06-23) * [Changelog for 12.0.1](#changelog-for-owncloud-ios-client-1201-2023-06-15) @@ -22,112 +21,6 @@ * [Changelog for 11.5.1](#changelog-for-owncloud-ios-client-1151-2021-02-17) * [Changelog for 11.5.0](#changelog-for-owncloud-ios-client-1150-2021-02-10) * [Changelog for 11.4.5 versions and below](#changelog-for-1145-versions-and-below) -# Changelog for ownCloud iOS Client [12.1.0] (2024-01-29) -The following sections list the changes in ownCloud iOS Client 12.1.0 relevant to -ownCloud admins and users. - -[12.1.0]: https://github.com/owncloud/ios-app/compare/milestone/12.0.3...milestone/12.1.0 - -## Summary - -* Bugfix - Available offline badge: [#1128](https://github.com/owncloud/ios-app/issues/1128) -* Bugfix - File Provider fixes: [#1294](https://github.com/owncloud/ios-app/pull/1294) -* Bugfix - Open ownCloud Links in App: [#1295](https://github.com/owncloud/ios-app/issues/1295) -* Bugfix - Show message in File Provider if no account has been set up: [#1306](https://github.com/owncloud/ios-app/pull/1306) -* Bugfix - Disable Markup Edit Mode iOS 17: [#1309](https://github.com/owncloud/ios-app/issues/1309) -* Bugfix - Adopt log format: [#11224](https://github.com/owncloud/client/issues/11224) -* Change - New account wizard: [#1274](https://github.com/owncloud/ios-app/pull/1274) -* Change - Text recognition actions for images: [#1283](https://github.com/owncloud/ios-app/pull/1283) -* Change - File extension / suffix protection: [#1292](https://github.com/owncloud/ios-app/issues/1292) -* Change - Share Action Extension "Save to ownCloud": [#1293](https://github.com/owncloud/ios-app/issues/1293) -* Change - Link naming: [#1297](https://github.com/owncloud/ios-app/issues/1297) -* Change - Remove Extension Build Flag (Intents): [#6112](https://github.com/owncloud/enterprise/issues/6112) - -## Details - -* Bugfix - Available offline badge: [#1128](https://github.com/owncloud/ios-app/issues/1128) - - Available offline badge was there after making unavailable offline. - - https://github.com/owncloud/ios-app/issues/1128 - -* Bugfix - File Provider fixes: [#1294](https://github.com/owncloud/ios-app/pull/1294) - - This branch addresses found issues in the File Provider: - fixes unanswered - thumbnail requests (leading to infinite thumbnail responses) - fixes incorrect - error being returned in response to thumbnail requests - - https://github.com/owncloud/ios-app/pull/1294 - -* Bugfix - Open ownCloud Links in App: [#1295](https://github.com/owncloud/ios-app/issues/1295) - - Fixed existing feature intending to open files/folders in app, by clicking a - private link from outside. - - https://github.com/owncloud/ios-app/issues/1295 - -* Bugfix - Show message in File Provider if no account has been set up: [#1306](https://github.com/owncloud/ios-app/pull/1306) - - This PR makes the File Provider UI show a message if no account has been set up - yet, offering to open the app. Previously, the FP UI was briefly shown and then - dismissed. - - https://github.com/owncloud/ios-app/pull/1306 - -* Bugfix - Disable Markup Edit Mode iOS 17: [#1309](https://github.com/owncloud/ios-app/issues/1309) - - Fixed disabling edit mode in markup document view on iOS 17 - - https://github.com/owncloud/ios-app/issues/1309 - -* Bugfix - Adopt log format: [#11224](https://github.com/owncloud/client/issues/11224) - - Use common http log format for ownCloud clients. - - https://github.com/owncloud/client/issues/11224 - -* Change - New account wizard: [#1274](https://github.com/owncloud/ios-app/pull/1274) - - - reimplementation of the new account wizard - support for reordering accounts - in the sidebar via drag and drop - adds location breadcrumb dropdown in the - viewer - - https://github.com/owncloud/ios-app/pull/1274 - -* Change - Text recognition actions for images: [#1283](https://github.com/owncloud/ios-app/pull/1283) - - Adds VisonKit interactions to the image viewer, allowing to select and interact - with recognized content (f.ex. text) like in the Photos app. - - https://github.com/owncloud/ios-app/pull/1283 - -* Change - File extension / suffix protection: [#1292](https://github.com/owncloud/ios-app/issues/1292) - - Prevents users from removing or changing the suffix for new documents and - document scanner. - - https://github.com/owncloud/ios-app/issues/1292 - -* Change - Share Action Extension "Save to ownCloud": [#1293](https://github.com/owncloud/ios-app/issues/1293) - - Adds a share action extension "Save to ownCloud", which will open the share - sheet view. - - https://github.com/owncloud/ios-app/issues/1293 - -* Change - Link naming: [#1297](https://github.com/owncloud/ios-app/issues/1297) - - Adds a Name field for link shares, allowing to enter and edit the name of link - shares. - - https://github.com/owncloud/ios-app/issues/1297 - -* Change - Remove Extension Build Flag (Intents): [#6112](https://github.com/owncloud/enterprise/issues/6112) - - Adds a build flag to remove app extensions from a IPA build. - - https://github.com/owncloud/enterprise/issues/6112 - # Changelog for ownCloud iOS Client [12.0.3] (2023-08-31) The following sections list the changes in ownCloud iOS Client 12.0.3 relevant to ownCloud admins and users. diff --git a/changelog/12.1.0_2024-01-29/11224 b/changelog/12.1.0_2024-01-29/11224 deleted file mode 100644 index 8292539a8..000000000 --- a/changelog/12.1.0_2024-01-29/11224 +++ /dev/null @@ -1,5 +0,0 @@ -Bugfix: Adopt log format - -Use common http log format for ownCloud clients. - -https://github.com/owncloud/client/issues/11224 diff --git a/changelog/12.1.0_2024-01-29/1128 b/changelog/12.1.0_2024-01-29/1128 deleted file mode 100644 index df8a31810..000000000 --- a/changelog/12.1.0_2024-01-29/1128 +++ /dev/null @@ -1,5 +0,0 @@ -Bugfix: Available offline badge - -Available offline badge was there after making unavailable offline. - -https://github.com/owncloud/ios-app/issues/1128 diff --git a/changelog/12.1.0_2024-01-29/1274 b/changelog/12.1.0_2024-01-29/1274 deleted file mode 100644 index 3f0efe4ab..000000000 --- a/changelog/12.1.0_2024-01-29/1274 +++ /dev/null @@ -1,7 +0,0 @@ -Change: New account wizard - -- reimplementation of the new account wizard -- support for reordering accounts in the sidebar via drag and drop -- adds location breadcrumb dropdown in the viewer - -https://github.com/owncloud/ios-app/pull/1274 diff --git a/changelog/12.1.0_2024-01-29/1283 b/changelog/12.1.0_2024-01-29/1283 deleted file mode 100644 index 50bece0f9..000000000 --- a/changelog/12.1.0_2024-01-29/1283 +++ /dev/null @@ -1,5 +0,0 @@ -Change: Text recognition actions for images - -Adds VisonKit interactions to the image viewer, allowing to select and interact with recognized content (f.ex. text) like in the Photos app. - -https://github.com/owncloud/ios-app/pull/1283 diff --git a/changelog/12.1.0_2024-01-29/1292 b/changelog/12.1.0_2024-01-29/1292 deleted file mode 100644 index af21ca58a..000000000 --- a/changelog/12.1.0_2024-01-29/1292 +++ /dev/null @@ -1,5 +0,0 @@ -Change: File extension / suffix protection - -Prevents users from removing or changing the suffix for new documents and document scanner. - -https://github.com/owncloud/ios-app/issues/1292 diff --git a/changelog/12.1.0_2024-01-29/1293 b/changelog/12.1.0_2024-01-29/1293 deleted file mode 100644 index 70613b963..000000000 --- a/changelog/12.1.0_2024-01-29/1293 +++ /dev/null @@ -1,5 +0,0 @@ -Change: Share Action Extension "Save to ownCloud" - -Adds a share action extension "Save to ownCloud", which will open the share sheet view. - -https://github.com/owncloud/ios-app/issues/1293 diff --git a/changelog/12.1.0_2024-01-29/1294 b/changelog/12.1.0_2024-01-29/1294 deleted file mode 100644 index 2c4a7b9fc..000000000 --- a/changelog/12.1.0_2024-01-29/1294 +++ /dev/null @@ -1,7 +0,0 @@ -Bugfix: File Provider fixes - -This branch addresses found issues in the File Provider: -- fixes unanswered thumbnail requests (leading to infinite thumbnail responses) -- fixes incorrect error being returned in response to thumbnail requests - -https://github.com/owncloud/ios-app/pull/1294 diff --git a/changelog/12.1.0_2024-01-29/1295 b/changelog/12.1.0_2024-01-29/1295 deleted file mode 100644 index 3d65670ac..000000000 --- a/changelog/12.1.0_2024-01-29/1295 +++ /dev/null @@ -1,5 +0,0 @@ -Bugfix: Open ownCloud Links in App - -Fixed existing feature intending to open files/folders in app, by clicking a private link from outside. - -https://github.com/owncloud/ios-app/issues/1295 diff --git a/changelog/12.1.0_2024-01-29/1297 b/changelog/12.1.0_2024-01-29/1297 deleted file mode 100644 index ff9bee06c..000000000 --- a/changelog/12.1.0_2024-01-29/1297 +++ /dev/null @@ -1,5 +0,0 @@ -Change: Link naming - -Adds a Name field for link shares, allowing to enter and edit the name of link shares. - -https://github.com/owncloud/ios-app/issues/1297 diff --git a/changelog/12.1.0_2024-01-29/1306 b/changelog/12.1.0_2024-01-29/1306 deleted file mode 100644 index 693a42cef..000000000 --- a/changelog/12.1.0_2024-01-29/1306 +++ /dev/null @@ -1,5 +0,0 @@ -Bugfix: Show message in File Provider if no account has been set up - -This PR makes the File Provider UI show a message if no account has been set up yet, offering to open the app. Previously, the FP UI was briefly shown and then dismissed. - -https://github.com/owncloud/ios-app/pull/1306 diff --git a/changelog/12.1.0_2024-01-29/1309 b/changelog/12.1.0_2024-01-29/1309 deleted file mode 100644 index 0d751b7da..000000000 --- a/changelog/12.1.0_2024-01-29/1309 +++ /dev/null @@ -1,5 +0,0 @@ -Bugfix: Disable Markup Edit Mode iOS 17 - -Fixed disabling edit mode in markup document view on iOS 17 - -https://github.com/owncloud/ios-app/issues/1309 diff --git a/changelog/12.1.0_2024-01-29/6112 b/changelog/12.1.0_2024-01-29/6112 deleted file mode 100644 index 5f20f4ef0..000000000 --- a/changelog/12.1.0_2024-01-29/6112 +++ /dev/null @@ -1,5 +0,0 @@ -Change: Remove Extension Build Flag (Intents) - -Adds a build flag to remove app extensions from a IPA build. - -https://github.com/owncloud/enterprise/issues/6112 diff --git a/doc/BUILD_CUSTOMIZATION.md b/doc/BUILD_CUSTOMIZATION.md index 524eb1335..ce413fb34 100644 --- a/doc/BUILD_CUSTOMIZATION.md +++ b/doc/BUILD_CUSTOMIZATION.md @@ -36,7 +36,3 @@ Removes the following from the app: Removes the following from the app: - the `NSAppTransportSecurity` dictionary from the app's `Info.plist` - including the `NSAllowsArbitraryLoads` key that's needed to allow plain/unsecured HTTP connections -- -### `REMOVE_EXTENSION_INTENTS` - -Removes the Intents extension binary from the IPA after building the app with fastlane diff --git a/doc/CONFIGURATION.json b/doc/CONFIGURATION.json index c5c8f4bbd..0cdec2176 100644 --- a/doc/CONFIGURATION.json +++ b/doc/CONFIGURATION.json @@ -1,4 +1,43 @@ [ + { + "autoExpansion" : "none", + "category" : "Bookmarks", + "categoryTag" : "bookmarks", + "classIdentifier" : "account-settings", + "className" : "ownCloud.AccountSettingsProvider", + "description" : "The default name for the creation of new bookmarks.", + "flatIdentifier" : "account-settings.default-name", + "key" : "default-name", + "label" : "account-settings.default-name", + "status" : "supported", + "type" : "string" + }, + { + "autoExpansion" : "none", + "category" : "Bookmarks", + "categoryTag" : "bookmarks", + "classIdentifier" : "account-settings", + "className" : "ownCloud.AccountSettingsProvider", + "description" : "The default URL for the creation of new bookmarks.", + "flatIdentifier" : "account-settings.default-url", + "key" : "default-url", + "label" : "account-settings.default-url", + "status" : "supported", + "type" : "string" + }, + { + "autoExpansion" : "none", + "category" : "Bookmarks", + "categoryTag" : "bookmarks", + "classIdentifier" : "account-settings", + "className" : "ownCloud.AccountSettingsProvider", + "description" : "Controls whether the server URL in the text field during the creation of new bookmarks can be changed.", + "flatIdentifier" : "account-settings.url-editable", + "key" : "url-editable", + "label" : "account-settings.url-editable", + "status" : "supported", + "type" : "bool" + }, { "autoExpansion" : "none", "category" : "Actions", @@ -727,7 +766,6 @@ "categoryTag" : "branding", "classIdentifier" : "branding", "className" : "Branding", - "defaultValue" : true, "description" : "Indicates if the user can change the server URL for the account.", "flatIdentifier" : "branding.profile-allow-url-configuration", "key" : "profile-allow-url-configuration", @@ -872,47 +910,12 @@ "categoryTag" : "branding", "classIdentifier" : "branding", "className" : "Branding", - "description" : "Values to use in system-color-based themes for branded clients. Mutually exclusive with theme-definitions.", - "flatIdentifier" : "branding.theme-colors", - "key" : "theme-colors", - "label" : "Theme Colors", - "possibleKeys" : [ - { - "description" : "Color to use as tint/accent color for controls (in hex notation).", - "value" : "tint-color" - }, - { - "description" : "Color to use as background color for brand views (in hex notation).", - "value" : "branding-background-color" - }, - { - "description" : "The status bar style in the setup wizard, affecting the status bar text color. Can be either `default`, `black` or `white`.", - "value" : "setup-status-bar-style" - }, - { - "description" : "Color to fill file icons with (in hex notation).", - "value" : "file-icon-color" - }, - { - "description" : "Color to fill folder icons with (in hex notation).", - "value" : "folder-icon-color" - } - ], - "status" : "advanced", - "type" : "dictionary" - }, - { - "autoExpansion" : "none", - "category" : "Branding", - "categoryTag" : "branding", - "classIdentifier" : "branding", - "className" : "Branding", - "description" : "CSS records to add to the CSS space of system-color-based themes for branded clients. Mutually exclusive with theme-definitions.", - "flatIdentifier" : "branding.theme-css-records", - "key" : "theme-css-records", - "label" : "Theme CSS Records", + "description" : "Array of dictionaries, each specifying a theme.", + "flatIdentifier" : "branding.theme-definitions", + "key" : "theme-definitions", + "label" : "branding.theme-definitions", "status" : "advanced", - "type" : "stringArray" + "type" : "dictionaryArray" }, { "autoExpansion" : "none", @@ -920,12 +923,12 @@ "categoryTag" : "branding", "classIdentifier" : "branding", "className" : "Branding", - "description" : "Array of dictionaries, each specifying a theme.", - "flatIdentifier" : "branding.theme-definitions", - "key" : "theme-definitions", - "label" : "branding.theme-definitions", + "description" : "Dictionary defining generic colors that can be used in the definitions.", + "flatIdentifier" : "branding.theme-generic-colors", + "key" : "theme-generic-colors", + "label" : "branding.theme-generic-colors", "status" : "advanced", - "type" : "dictionaryArray" + "type" : "dictionary" }, { "autoExpansion" : "none", @@ -1102,19 +1105,6 @@ "status" : "supported", "type" : "string" }, - { - "autoExpansion" : "none", - "category" : "Build", - "categoryTag" : "build", - "classIdentifier" : "build", - "className" : "BuildOptions", - "description" : "Sets a custom version number for the app.", - "flatIdentifier" : "build.version-number", - "key" : "version-number", - "label" : "build.version-number", - "status" : "supported", - "type" : "string" - }, { "autoExpansion" : "none", "category" : "Connection", @@ -1849,14 +1839,6 @@ "description" : "Extension with the identifier simple-apm.", "value" : "simple-apm" }, - { - "description" : "Extension with the identifier system.dark.", - "value" : "system.dark" - }, - { - "description" : "Extension with the identifier system.light.", - "value" : "system.light" - }, { "description" : "Extension with the identifier web-finger.", "value" : "web-finger" @@ -2325,20 +2307,6 @@ "status" : "advanced", "type" : "bool" }, - { - "autoExpansion" : "none", - "category" : "Passcode", - "categoryTag" : "passcode", - "classIdentifier" : "passcode", - "className" : "AppLockSettings", - "defaultValue" : false, - "description" : "Controls wether the user MUST establish a passcode upon app installation, if NO device passcode protection is set.", - "flatIdentifier" : "passcode.enforced-by-device", - "key" : "enforced-by-device", - "label" : "passcode.enforced-by-device", - "status" : "advanced", - "type" : "bool" - }, { "autoExpansion" : "none", "category" : "Passcode", diff --git a/doc/configuration.adoc b/doc/configuration.adoc index bb8f82d08..22277debf 100644 --- a/doc/configuration.adoc +++ b/doc/configuration.adoc @@ -344,6 +344,24 @@ tag::bookmarks[] |Status +|account-settings.default-name +|string +| +|The default name for the creation of new bookmarks. +|supported `candidate` + +|account-settings.default-url +|string +| +|The default URL for the creation of new bookmarks. +|supported `candidate` + +|account-settings.url-editable +|bool +| +|Controls whether the server URL in the text field during the creation of new bookmarks can be changed. +|supported `candidate` + |bookmark.prepopulation |string | @@ -438,7 +456,7 @@ branding.can-edit-account + branding.profile-allow-url-configuration |bool -|`true` +| |Indicates if the user can change the server URL for the account. |advanced `candidate` @@ -522,49 +540,18 @@ branding.sidebar-links-title |Title for the sidebar links section. |advanced `candidate` -|**Theme Colors** + - + -branding.theme-colors -|dictionary -| -|Values to use in system-color-based themes for branded clients. Mutually exclusive with theme-definitions. -[cols="1,1"] -!=== -! Key -! Value -! `tint-color` -! Color to use as tint/accent color for controls (in hex notation). - -! `branding-background-color` -! Color to use as background color for brand views (in hex notation). - -! `setup-status-bar-style` -! The status bar style in the setup wizard, affecting the status bar text color. Can be either `default`, `black` or `white`. - -! `file-icon-color` -! Color to fill file icons with (in hex notation). - -! `folder-icon-color` -! Color to fill folder icons with (in hex notation). - -!=== - -|advanced `candidate` - -|**Theme CSS Records** + - + -branding.theme-css-records -|stringArray -| -|CSS records to add to the CSS space of system-color-based themes for branded clients. Mutually exclusive with theme-definitions. -|advanced `candidate` - |branding.theme-definitions |dictionaryArray | |Array of dictionaries, each specifying a theme. |advanced `candidate` +|branding.theme-generic-colors +|dictionary +| +|Dictionary defining generic colors that can be used in the definitions. +|advanced `candidate` + |**Documentation URL** + + branding.url-documentation @@ -681,12 +668,6 @@ tag::build[] |Set a custom app group identifier via Branding.plist parameter. This value will be set by fastlane. Changes OCAppGroupIdentifier, OCKeychainAccessGroupIdentifier only. Fastlane does not need the provisioning profile and certificate with the given app group identifer. Needs resigning with the correct provisioning profile and certificate. This is needed, if a customer is using an own resigning script which does not handle setting the app group identifier. |supported `candidate` -|build.version-number -|string -| -|Sets a custom version number for the app. -|supported `candidate` - |=== end::build[] @@ -1156,12 +1137,6 @@ tag::extensions[] ! `simple-apm` ! Extension with the identifier simple-apm. -! `system.dark` -! Extension with the identifier system.dark. - -! `system.light` -! Extension with the identifier system.light. - ! `web-finger` ! Extension with the identifier web-finger. @@ -1518,12 +1493,6 @@ tag::passcode[] |Controls wether the user MUST establish a passcode upon app installation. |advanced `candidate` -|passcode.enforced-by-device -|bool -|`false` -|Controls wether the user MUST establish a passcode upon app installation, if NO device passcode protection is set. -|advanced `candidate` - |passcode.lockDelay |int | diff --git a/enterprise/register/registerOwncloudApp.rb b/enterprise/register/registerOwncloudApp.rb index 2f3ace4bd..5babab647 100755 --- a/enterprise/register/registerOwncloudApp.rb +++ b/enterprise/register/registerOwncloudApp.rb @@ -1,14 +1,5 @@ #!/usr/bin/env ruby - # Copyright (C) 2023, ownCloud GmbH. - # - # This code is covered by the GNU Public License Version 3. - # - # For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ - # You should have received a copy of this license along with this program. If not, see . - - # Version 1.1.0 - require 'spaceship' class AppRegistration @@ -313,4 +304,3 @@ def prepareProfile(bundle_id, profileFilename, cert) register.prepareAppID("File Provider UI", "FileProviderUI.mobileprovision", groups, registrationType, "#{bundlePrefix}.ios-app.ownCloud-File-ProviderUI", cert) register.prepareAppID("Intent", "Intent.mobileprovision", groups, registrationType, "#{bundlePrefix}.ios-app.ownCloud-Intent", cert) register.prepareAppID("ShareExtension", "ShareExtension.mobileprovision", groups, registrationType,"#{bundlePrefix}.ios-app.ownCloud-Share-Extension", cert) -register.prepareAppID("ActionExtension", "ActionExtension.mobileprovision", groups, registrationType,"#{bundlePrefix}.ios-app.ownCloud-Action-Extension", cert) diff --git a/enterprise/resign/README.md b/enterprise/resign/README.md index 378a77cfe..b26f92855 100644 --- a/enterprise/resign/README.md +++ b/enterprise/resign/README.md @@ -16,8 +16,6 @@ This script allows you to resign the ownCloud App IPA file with a different Appl - `com.yourcompany.ios-app.ownCloud-Share-Extension` - - `com.yourcompany.ios-app.ownCloud-Action-Extension` - 2. Generate one App Group: - `group.com.yourcompany.ios-app` @@ -53,7 +51,6 @@ Create a text file containing a list of line-break separated domain names (FQN) - `FileProviderUI.mobileprovision` - `Intent.mobileprovision` - `ShareExtension.mobileprovision` - - `ActionExtension.mobileprovision` 5. Execute the script diff --git a/enterprise/resign/resignInspector.sh b/enterprise/resign/resignInspector.sh index 8edf6581b..53e8156aa 100755 --- a/enterprise/resign/resignInspector.sh +++ b/enterprise/resign/resignInspector.sh @@ -7,7 +7,7 @@ # For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ # You should have received a copy of this license along with this program. If not, see . - VERSION="1.1.0" + VERSION="1.0.0" #Define output formats BOLD="$(tput bold)" @@ -72,7 +72,7 @@ fi APPPATH="$APPTEMP/Payload/ownCloud.app" fi - declare -a LOCATIONS=( "$APPPATH/" "$APPPATH/PlugIns/ownCloud File Provider.appex" "$APPPATH/PlugIns/ownCloud File Provider UI.appex" "$APPPATH/PlugIns/ownCloud Intents.appex" "$APPPATH/PlugIns/ownCloud Share Extension.appex" "$APPPATH/PlugIns/ownCloud Action Extension.appex" ); + declare -a LOCATIONS=( "$APPPATH/" "$APPPATH/PlugIns/ownCloud File Provider.appex" "$APPPATH/PlugIns/ownCloud File Provider UI.appex" "$APPPATH/PlugIns/ownCloud Intents.appex" "$APPPATH/PlugIns/ownCloud Share Extension.appex" ); echo "${SUCCESS}Checking entitlements…${NC}" echo "" diff --git a/enterprise/resign/resignOwncloudApp b/enterprise/resign/resignOwncloudApp index 695fa9c67..f2fa208e7 100755 --- a/enterprise/resign/resignOwncloudApp +++ b/enterprise/resign/resignOwncloudApp @@ -7,7 +7,7 @@ # For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ # You should have received a copy of this license along with this program. If not, see . -VERSION="1.3.0" +VERSION="1.2.2" #Define output formats BOLD="$(tput bold)" @@ -64,12 +64,11 @@ FILEPROVIDER_MOBILEPROVISION="$PROVISIONING_DIR/FileProvider.mobileprovision" FILEPROVIDERUI_MOBILEPROVISION="$PROVISIONING_DIR/FileProviderUI.mobileprovision" INTENT_MOBILEPROVISION="$PROVISIONING_DIR/Intent.mobileprovision" SHAREEXTENSION_MOBILEPROVISION="$PROVISIONING_DIR/ShareExtension.mobileprovision" -ACTIONEXTENSION_MOBILEPROVISION="$PROVISIONING_DIR/ActionExtension.mobileprovision" ASSOCIATED_DOMAINS="domains.txt" -declare -a MOBILEPROVISIONS=( "$DISTRIBUTION_MOBILEPROVISION" "$FILEPROVIDER_MOBILEPROVISION" "$FILEPROVIDERUI_MOBILEPROVISION" "$INTENT_MOBILEPROVISION" "$SHAREEXTENSION_MOBILEPROVISION" "$ACTIONEXTENSION_MOBILEPROVISION" ); -declare -a ENTITLEMENTS=( "ownCloud.entitlements" "ownCloud_File_Provider.entitlements" "ownCloud_File_Provider_UI.entitlements" "ownCloud_Intents.entitlements" "ownCloud_Share_Extension.entitlements" "ownCloud_Action_Extension.entitlements" ); -declare -a LOCATIONS=( "$APPDIR" "$APPDIR/PlugIns/ownCloud File Provider.appex" "$APPDIR/PlugIns/ownCloud File Provider UI.appex" "$APPDIR/PlugIns/ownCloud Intents.appex" "$APPDIR/PlugIns/ownCloud Share Extension.appex" "$APPDIR/PlugIns/ownCloud Action Extension.appex" ); +declare -a MOBILEPROVISIONS=( "$DISTRIBUTION_MOBILEPROVISION" "$FILEPROVIDER_MOBILEPROVISION" "$FILEPROVIDERUI_MOBILEPROVISION" "$INTENT_MOBILEPROVISION" "$SHAREEXTENSION_MOBILEPROVISION" ); +declare -a ENTITLEMENTS=( "ownCloud.entitlements" "ownCloud_File_Provider.entitlements" "ownCloud_File_Provider_UI.entitlements" "ownCloud_Intents.entitlements" "ownCloud_Share_Extension.entitlements" ); +declare -a LOCATIONS=( "$APPDIR" "$APPDIR/PlugIns/ownCloud File Provider.appex" "$APPDIR/PlugIns/ownCloud File Provider UI.appex" "$APPDIR/PlugIns/ownCloud Intents.appex" "$APPDIR/PlugIns/ownCloud Share Extension.appex" ); declare -a BUNDLEIDS=(); # Abort script if script is running in a path which contains "Library", because this could cause resource fork problems diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 0f7640287..90cd7e1f1 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -39,8 +39,7 @@ platform :ios do "com.owncloud.ios-app.ownCloud-File-Provider" => "match AdHoc com.owncloud.ios-app.ownCloud-File-Provider", "com.owncloud.ios-app.ownCloud-File-ProviderUI" => "match AdHoc com.owncloud.ios-app.ownCloud-File-ProviderUI", "com.owncloud.ios-app.ownCloud-Intents" => "match AdHoc com.owncloud.ios-app.ownCloud-Intents", - "com.owncloud.ios-app.ownCloud-Share-Extension" => "match AdHoc com.owncloud.ios-app.ownCloud-Share-Extension", - "com.owncloud.ios-app.ownCloud-Action-Extension" => "match AdHoc com.owncloud.ios-app.ownCloud-Action-Extension" + "com.owncloud.ios-app.ownCloud-Share-Extension" => "match AdHoc com.owncloud.ios-app.ownCloud-Share-Extension" #Add more Provisioning Profiles when extensions are added } } @@ -181,13 +180,13 @@ platform :ios do prepare_metadata( create_release_notes: options[:create_release_notes], create_screenshots: options[:create_screenshots], - app_name: "ownCloud EMM", + app_name: "ownCloud", metadata_path: 'fastlane/metadata-emm/en-US/release_notes.txt' ) puts("Build EMM iOS App…") # Moving all EMM resources to the correct place - sh "cp -R ../ownCloud/Resources/Theming/com.owncloud.ios-app.emm/*.png ../ownCloud/Resources/Theming/branding-assets/" + sh "cp -R ../ownCloud/Resources/Theming/com.owncloud.ios-app.emm/* ../ownCloud/Resources/Theming/" # Build App owncloud_emm_build() @@ -223,8 +222,7 @@ platform :ios do puts("Build ownCloud Online iOS App…") # Moving all ownCloud.online resources to the correct place - sh "cp -R ../ownCloud/Resources/Theming/online.owncloud.ios-app/*.png ../ownCloud/Resources/Theming/branding-assets/" - sh "cp ../ownCloud/Resources/Theming/online.owncloud.ios-app/Branding.plist ../ownCloud/Resources/Theming/" + sh "cp -R ../ownCloud/Resources/Theming/online.owncloud.ios-app/* ../ownCloud/Resources/Theming/" # Build App owncloud_online_build() @@ -260,8 +258,6 @@ platform :ios do ENTERPRISE_INTENT_PROFILE: "match AppStore com.owncloud.ios-app.ownCloud-Intents", ENTERPRISE_SHARE_EXTENSION_ID: "com.owncloud.ios-app.ownCloud-Share-Extension", ENTERPRISE_SHARE_EXTENSION_PROFILE: "match AppStore com.owncloud.ios-app.ownCloud-Share-Extension", - ENTERPRISE_ACTION_EXTENSION_ID: "com.owncloud.ios-app.ownCloud-Action-Extension", - ENTERPRISE_ACTION_EXTENSION_PROFILE: "match AppStore com.owncloud.ios-app.ownCloud-Action-Extension", ENTERPRISE_APP_FW_ID: "com.owncloud.ownCloudApp", ENTERPRISE_TEAM: "4AP2STM4H5", ENTERPRISE_IDENTITY: "Apple Distribution: ownCloud GmbH (4AP2STM4H5)", @@ -287,8 +283,6 @@ platform :ios do ENTERPRISE_INTENT_PROFILE: "match AppStore com.owncloud.ios-app.emm.ownCloud-Intents", ENTERPRISE_SHARE_EXTENSION_ID: "com.owncloud.ios-app.emm.ownCloud-Share-Extension", ENTERPRISE_SHARE_EXTENSION_PROFILE: "match AppStore com.owncloud.ios-app.emm.ownCloud-Share-Extension", - ENTERPRISE_ACTION_EXTENSION_ID: "com.owncloud.ios-app.emm.ownCloud-Action-Extension", - ENTERPRISE_ACTION_EXTENSION_PROFILE: "match AppStore com.owncloud.ios-app.emm.ownCloud-Action-Extension", ENTERPRISE_APP_FW_ID: "com.owncloud.ownCloudApp.emm", ENTERPRISE_TEAM: "4AP2STM4H5", ENTERPRISE_IDENTITY: "Apple Distribution: ownCloud GmbH (4AP2STM4H5)", @@ -296,7 +290,7 @@ platform :ios do EXPORT_METHOD: "app-store", CONFIGURATION: "Release", BETA_APP_ICON: false, - APP_NAME: "ownCloud EMM", + APP_NAME: "ownCloud", URL_SCHEME: "owncloud-emm", IPA_NAME: "ownCloud-emm" ) @@ -314,8 +308,6 @@ lane :owncloud_online_build do ENTERPRISE_INTENT_PROFILE: "ownCloud online AppStore Intents", ENTERPRISE_SHARE_EXTENSION_ID: "online.owncloud.ios-app.ShareExtApp", ENTERPRISE_SHARE_EXTENSION_PROFILE: "ownCloud online AppStore Share Ext", - ENTERPRISE_ACTION_EXTENSION_ID: "online.owncloud.ios-app.Action-Extension", - ENTERPRISE_ACTION_EXTENSION_PROFILE: "ownCloud online AppStore Action Extension", ENTERPRISE_APP_FW_ID: "online.owncloud.ios-app.ownCloudApp", ENTERPRISE_TEAM: "4AP2STM4H5", ENTERPRISE_IDENTITY: "Apple Distribution: ownCloud GmbH", @@ -341,8 +333,6 @@ end ENTERPRISE_INTENT_PROFILE: "Adhoc ownCloud iOS App Intents", ENTERPRISE_SHARE_EXTENSION_ID: "com.owncloud.ios-app.ownCloud-Share-Extension", ENTERPRISE_SHARE_EXTENSION_PROFILE: "Adhoc ownCloud iOS App Share Extension", - ENTERPRISE_ACTION_EXTENSION_ID: "com.owncloud.ios-app.ownCloud-Action-Extension", - ENTERPRISE_ACTION_EXTENSION_PROFILE: "Adhoc ownCloud iOS App Action Extension", ENTERPRISE_APP_FW_ID: "com.owncloud.ownCloudApp", ENTERPRISE_TEAM: "4AP2STM4H5", ENTERPRISE_IDENTITY: "Apple Distribution: ownCloud GmbH", @@ -366,8 +356,6 @@ end ENTERPRISE_INTENT_PROFILE: "match AppStore com.owncloud.ios-app.ownCloud-Intents", ENTERPRISE_SHARE_EXTENSION_ID: "com.owncloud.ios-app.ownCloud-Share-Extension", ENTERPRISE_SHARE_EXTENSION_PROFILE: "match AppStore com.owncloud.ios-app.ownCloud-Share-Extension", - ENTERPRISE_ACTION_EXTENSION_ID: "com.owncloud.ios-app.ownCloud-Action-Extension", - ENTERPRISE_ACTION_EXTENSION_PROFILE: "match AppStore com.owncloud.ios-app.ownCloud-Action-Extension", ENTERPRISE_APP_FW_ID: "com.owncloud.ownCloudApp", ENTERPRISE_TEAM: "4AP2STM4H5", ENTERPRISE_IDENTITY: "Apple Distribution: ownCloud GmbH (4AP2STM4H5)", @@ -401,8 +389,6 @@ end ENTERPRISE_INTENT_PROFILE: "Adhoc ownCloud iOS App Intents", ENTERPRISE_SHARE_EXTENSION_ID: "com.owncloud.ios-app.ownCloud-Share-Extension", ENTERPRISE_SHARE_EXTENSION_PROFILE: "Adhoc ownCloud iOS App Share Extension", - ENTERPRISE_ACTION_EXTENSION_ID: "com.owncloud.ios-app.ownCloud-Action-Extension", - ENTERPRISE_ACTION_EXTENSION_PROFILE: "Adhoc ownCloud iOS App Action Extension", ENTERPRISE_APP_FW_ID: "com.owncloud.ownCloudApp", ENTERPRISE_TEAM: "4AP2STM4H5", ENTERPRISE_IDENTITY: "iPhone Distribution: ownCloud GmbH", @@ -416,18 +402,13 @@ end end lane :generate_appicon do - - iconPath = "ownCloud/Resources/Theming/branding-assets/" - iconName = "branding-icon.png" - outputIconPath = "../ownCloud/Resources/Assets.xcassets/" - outputIconName = "AppIcon.appiconset" - if File.exist?("../" + iconPath + iconName) - sh("rm -rf " + outputIconPath + outputIconName + "/*") + iconPath = "ownCloud/Resources/Theming/branding-icon.png" + if File.exist?("../" + iconPath) appicon( - appicon_image_file: iconPath + iconName, + appicon_image_file: iconPath, appicon_devices: [:ipad, :iphone, :ios_marketing], appicon_path: "ownCloud/Resources/Assets.xcassets/", - appicon_name: outputIconName + appicon_name: "AppIcon.appiconset" ) end end @@ -445,8 +426,6 @@ end ENTERPRISE_INTENT_PROFILE = values[:ENTERPRISE_INTENT_PROFILE] ENTERPRISE_SHARE_EXTENSION_ID = values[:ENTERPRISE_SHARE_EXTENSION_ID] ENTERPRISE_SHARE_EXTENSION_PROFILE = values[:ENTERPRISE_SHARE_EXTENSION_PROFILE] - ENTERPRISE_ACTION_EXTENSION_ID = values[:ENTERPRISE_ACTION_EXTENSION_ID] - ENTERPRISE_ACTION_EXTENSION_PROFILE = values[:ENTERPRISE_ACTION_EXTENSION_PROFILE] ENTERPRISE_APP_FW_ID = values[:ENTERPRISE_APP_FW_ID] ENTERPRISE_APP_SHARED_ID = "com.owncloud.ownCloudAppShared" ENTERPRISE_TEAM = values[:ENTERPRISE_TEAM] @@ -569,7 +548,7 @@ end # Check, if Branding.plist file exists and handle custom set values if File.exist?("../" + themePath) # Check for custom app version number - tmpCustomAppVersionNumber = get_info_plist_value(path: themePath, key: "build.version-number") + tmpCustomAppVersionNumber = get_info_plist_value(path: themePath, key: "app.version-number") if tmpCustomAppVersionNumber && !tmpCustomAppVersionNumber.empty? customAppVersionNumber = tmpCustomAppVersionNumber @@ -578,7 +557,6 @@ end set_info_plist_value(path: "ownCloud File Provider/Info.plist", key: "CFBundleShortVersionString", value: customAppVersionNumber) set_info_plist_value(path: "ownCloud File Provider UI/Info.plist", key: "CFBundleShortVersionString", value: customAppVersionNumber) set_info_plist_value(path: "ownCloud Share Extension/Info.plist", key: "CFBundleShortVersionString", value: customAppVersionNumber) - set_info_plist_value(path: "ownCloud Action Extension/Info.plist", key: "CFBundleShortVersionString", value: customAppVersionNumber) set_info_plist_value(path: "ownCloud Intents/Info.plist", key: "CFBundleShortVersionString", value: customAppVersionNumber) end @@ -602,7 +580,6 @@ end set_info_plist_value(path: "ownCloud File Provider/Info.plist", key: "CFBundleVersion", value: BUILD_NUMBER) set_info_plist_value(path: "ownCloud File Provider UI/Info.plist", key: "CFBundleVersion", value: BUILD_NUMBER) set_info_plist_value(path: "ownCloud Share Extension/Info.plist", key: "CFBundleVersion", value: BUILD_NUMBER) - set_info_plist_value(path: "ownCloud Action Extension/Info.plist", key: "CFBundleVersion", value: BUILD_NUMBER) set_info_plist_value(path: "ownCloud Intents/Info.plist", key: "CFBundleVersion", value: BUILD_NUMBER) end @@ -624,12 +601,6 @@ end set_info_plist_value(path: "ownCloud Share Extension/Info.plist", key: "CFBundleDisplayName", value: "Share to " + appName) set_info_plist_value(path: "ownCloud Share Extension/Info.plist", key: "CFBundleName", value: appName) - set_info_plist_value(path: "ownCloud Action Extension/Info.plist", key: "CFBundleDisplayName", value: "Save to " + appName) - set_info_plist_value(path: "ownCloud Action Extension/Info.plist", key: "CFBundleName", value: appName) - - sh("sed -i '' '/\"CFBundleDisplayName\" =/s/ownCloud/#{appName}/' '../ownCloud Action Extension/en.lproj/InfoPlist.strings'") - sh("sed -i '' '/\"CFBundleDisplayName\" =/s/ownCloud/#{appName}/' '../ownCloud Action Extension/de.lproj/InfoPlist.strings'") - update_app_identifier( xcodeproj: "ownCloud.xcodeproj", plist_path: "ownCloud/Resources/Info.plist", @@ -666,12 +637,6 @@ end app_identifier: ENTERPRISE_SHARE_EXTENSION_ID ) - update_app_identifier( - xcodeproj: "ownCloud.xcodeproj", - plist_path: "ownCloud Action Extension/Info.plist", - app_identifier: ENTERPRISE_ACTION_EXTENSION_ID - ) - update_app_group_identifiers( entitlements_file: "ownCloud/ownCloud.entitlements", app_group_identifiers: [APP_GROUP_IDENTIFIERS] @@ -717,15 +682,6 @@ end identifiers: [ENTERPRISE_TEAM + "." + APP_GROUP_IDENTIFIERS] ) - update_app_group_identifiers( - entitlements_file: "ownCloud Action Extension/ownCloud Action Extension.entitlements", - app_group_identifiers: [APP_GROUP_IDENTIFIERS] - ) - update_keychain_access_groups( - entitlements_file: "ownCloud Action Extension/ownCloud Action Extension.entitlements", - identifiers: [ENTERPRISE_TEAM + "." + APP_GROUP_IDENTIFIERS] - ) - set_info_plist_value(path: "ownCloud File Provider/Info.plist", key: "OCAppGroupIdentifier", value: OC_APP_GROUP_IDENTIFIERS) set_info_plist_value(path: "ownCloud File Provider/Info.plist", key: "OCKeychainAccessGroupIdentifier", value: OC_APP_GROUP_IDENTIFIERS) set_info_plist_value(path: "ownCloud File Provider/Info.plist", key: "NSExtension", subkey: "NSExtensionFileProviderDocumentGroup", value: APP_GROUP_IDENTIFIERS) @@ -735,8 +691,6 @@ end set_info_plist_value(path: "ownCloud Intents/Info.plist", key: "OCKeychainAccessGroupIdentifier", value: OC_APP_GROUP_IDENTIFIERS) set_info_plist_value(path: "ownCloud Share Extension/Info.plist", key: "OCAppGroupIdentifier", value: OC_APP_GROUP_IDENTIFIERS) set_info_plist_value(path: "ownCloud Share Extension/Info.plist", key: "OCKeychainAccessGroupIdentifier", value: OC_APP_GROUP_IDENTIFIERS) - set_info_plist_value(path: "ownCloud Action Extension/Info.plist", key: "OCAppGroupIdentifier", value: OC_APP_GROUP_IDENTIFIERS) - set_info_plist_value(path: "ownCloud Action Extension/Info.plist", key: "OCKeychainAccessGroupIdentifier", value: OC_APP_GROUP_IDENTIFIERS) set_info_plist_value(path: "ownCloud/Resources/Info.plist", key: "OCAppGroupIdentifier", value: OC_APP_GROUP_IDENTIFIERS) set_info_plist_value(path: "ownCloud/Resources/Info.plist", key: "OCKeychainAccessGroupIdentifier", value: OC_APP_GROUP_IDENTIFIERS) @@ -799,16 +753,6 @@ end targets: ["ownCloud Share Extension"] ) - automatic_code_signing( - path: "ownCloud.xcodeproj", - use_automatic_signing: false, - team_id: ENTERPRISE_TEAM, - code_sign_identity: ENTERPRISE_IDENTITY, - profile_name: ENTERPRISE_ACTION_EXTENSION_PROFILE, - bundle_identifier: ENTERPRISE_ACTION_EXTENSION_ID, - targets: ["ownCloud Action Extension"] - ) - automatic_code_signing( path: "ownCloud.xcodeproj", use_automatic_signing: false, @@ -876,17 +820,9 @@ end ENTERPRISE_APP_ID => ENTERPRISE_APP_PROFILE, ENTERPRISE_FP_ID => ENTERPRISE_FP_PROFILE, ENTERPRISE_INTENT_ID => ENTERPRISE_INTENT_PROFILE, - ENTERPRISE_SHARE_EXTENSION_ID => ENTERPRISE_SHARE_EXTENSION_PROFILE, - ENTERPRISE_ACTION_EXTENSION_ID => ENTERPRISE_ACTION_EXTENSION_PROFILE + ENTERPRISE_SHARE_EXTENSION_ID => ENTERPRISE_SHARE_EXTENSION_PROFILE } } ) - - - - if appBuildFlags.include? "REMOVE_EXTENSION_INTENTS" - sh "../removeExtension.sh \"../" + ipaName.gsub("/", "_") + "\" \"ownCloud Intents\"" - end - end end diff --git a/fastlane/metadata-emm/en-US/release_notes.txt b/fastlane/metadata-emm/en-US/release_notes.txt index b8958eb2e..e9ca129c0 100644 --- a/fastlane/metadata-emm/en-US/release_notes.txt +++ b/fastlane/metadata-emm/en-US/release_notes.txt @@ -1,32 +1,3 @@ -• New account wizard: -Introducing a new, intuitive account wizard user interface for a fast onboarding experience. +• Bug Fixes +Fixed File Provider, App Provider and layout issues. -• Reordering accounts: -Now you can easily reorder accounts in the sidebar by simply dragging and dropping them. - -• Location breadcrumb: -We have added a location breadcrumb dropdown in the file viewer, making it easier to navigate through your files. - -• Text recognition: -You can now perform text recognition actions on images. - -• File extension / suffix protection: -To prevent accidental removal or modification of the suffix for new documents and document scanner files, we have implemented file extension protection. - -• Share Action "Save to ownCloud": -We have added a new action called "Save to ownCloud" to the share sheet, allowing you to easily save files to your ownCloud account. - -• Link naming: -You can now enter and edit the name of link shares. - -• Sort by Last Used: -Introducing a new sorting method - “Last Used” - which allows you to sort items based on the most recently accessed ones. - -• Markup Edit Mode on iOS 17: -We have fixed the issue that was disabling the edit mode in the markup document view on iOS 17. - -• Open ownCloud Links in App: -We have resolved the issue with opening private links from third-party apps. - -• Bug Fixes: -We have addressed various issues with the File Provider and the app itself. \ No newline at end of file diff --git a/fastlane/metadata-owncloud-online/en-US/release_notes.txt b/fastlane/metadata-owncloud-online/en-US/release_notes.txt index b8958eb2e..e9ca129c0 100644 --- a/fastlane/metadata-owncloud-online/en-US/release_notes.txt +++ b/fastlane/metadata-owncloud-online/en-US/release_notes.txt @@ -1,32 +1,3 @@ -• New account wizard: -Introducing a new, intuitive account wizard user interface for a fast onboarding experience. +• Bug Fixes +Fixed File Provider, App Provider and layout issues. -• Reordering accounts: -Now you can easily reorder accounts in the sidebar by simply dragging and dropping them. - -• Location breadcrumb: -We have added a location breadcrumb dropdown in the file viewer, making it easier to navigate through your files. - -• Text recognition: -You can now perform text recognition actions on images. - -• File extension / suffix protection: -To prevent accidental removal or modification of the suffix for new documents and document scanner files, we have implemented file extension protection. - -• Share Action "Save to ownCloud": -We have added a new action called "Save to ownCloud" to the share sheet, allowing you to easily save files to your ownCloud account. - -• Link naming: -You can now enter and edit the name of link shares. - -• Sort by Last Used: -Introducing a new sorting method - “Last Used” - which allows you to sort items based on the most recently accessed ones. - -• Markup Edit Mode on iOS 17: -We have fixed the issue that was disabling the edit mode in the markup document view on iOS 17. - -• Open ownCloud Links in App: -We have resolved the issue with opening private links from third-party apps. - -• Bug Fixes: -We have addressed various issues with the File Provider and the app itself. \ No newline at end of file diff --git a/fastlane/metadata/en-US/release_notes.txt b/fastlane/metadata/en-US/release_notes.txt index b8958eb2e..e9ca129c0 100644 --- a/fastlane/metadata/en-US/release_notes.txt +++ b/fastlane/metadata/en-US/release_notes.txt @@ -1,32 +1,3 @@ -• New account wizard: -Introducing a new, intuitive account wizard user interface for a fast onboarding experience. +• Bug Fixes +Fixed File Provider, App Provider and layout issues. -• Reordering accounts: -Now you can easily reorder accounts in the sidebar by simply dragging and dropping them. - -• Location breadcrumb: -We have added a location breadcrumb dropdown in the file viewer, making it easier to navigate through your files. - -• Text recognition: -You can now perform text recognition actions on images. - -• File extension / suffix protection: -To prevent accidental removal or modification of the suffix for new documents and document scanner files, we have implemented file extension protection. - -• Share Action "Save to ownCloud": -We have added a new action called "Save to ownCloud" to the share sheet, allowing you to easily save files to your ownCloud account. - -• Link naming: -You can now enter and edit the name of link shares. - -• Sort by Last Used: -Introducing a new sorting method - “Last Used” - which allows you to sort items based on the most recently accessed ones. - -• Markup Edit Mode on iOS 17: -We have fixed the issue that was disabling the edit mode in the markup document view on iOS 17. - -• Open ownCloud Links in App: -We have resolved the issue with opening private links from third-party apps. - -• Bug Fixes: -We have addressed various issues with the File Provider and the app itself. \ No newline at end of file diff --git a/img/filetypes-tvg/application-pdf.tvg b/img/filetypes-tvg/application-pdf.tvg index 532446906..d1c1c517b 100644 --- a/img/filetypes-tvg/application-pdf.tvg +++ b/img/filetypes-tvg/application-pdf.tvg @@ -1 +1 @@ -{"defaults":{"pdfFileFillColor":"#dc5047"},"image":"\n\n \n<\/svg>\n","viewBox":"{{0, 0}, {16, 16}}"} \ No newline at end of file +{"defaults":{},"image":"\n\n \n<\/svg>\n","viewBox":"{{0, 0}, {16, 16}}"} \ No newline at end of file diff --git a/img/filetypes-tvg/x-office-document.tvg b/img/filetypes-tvg/x-office-document.tvg index f52918311..e124f34a9 100644 --- a/img/filetypes-tvg/x-office-document.tvg +++ b/img/filetypes-tvg/x-office-document.tvg @@ -1 +1 @@ -{"defaults":{"documentFileFillColor":"#49abea"},"image":"\n\n \n<\/svg>\n","viewBox":"{{0, 0}, {16, 16}}"} +{"defaults":{},"image":"\n\n \n<\/svg>\n","viewBox":"{{0, 0}, {16, 16}}"} \ No newline at end of file diff --git a/img/filetypes-tvg/x-office-presentation.tvg b/img/filetypes-tvg/x-office-presentation.tvg index 49e11c76a..c5efb948a 100644 --- a/img/filetypes-tvg/x-office-presentation.tvg +++ b/img/filetypes-tvg/x-office-presentation.tvg @@ -1 +1 @@ -{"image":"\n\n \n<\/svg>\n","defaults":{"presentationFileFillColor":"#f0965f"},"viewBox":"{{0, 0}, {16, 16}}"} \ No newline at end of file +{"defaults":{},"image":"\n\n \n<\/svg>\n","viewBox":"{{0, 0}, {16, 16}}"} \ No newline at end of file diff --git a/img/filetypes-tvg/x-office-spreadsheet.tvg b/img/filetypes-tvg/x-office-spreadsheet.tvg index eed0baf30..bb8d95818 100644 --- a/img/filetypes-tvg/x-office-spreadsheet.tvg +++ b/img/filetypes-tvg/x-office-spreadsheet.tvg @@ -1 +1 @@ -{"image":"\n\n \n<\/svg>\n","defaults":{"spreadsheetFileFillColor":"#9abd4e"},"viewBox":"{{0, 0}, {16, 16}}"} \ No newline at end of file +{"defaults":{},"image":"\n\n \n<\/svg>\n","viewBox":"{{0, 0}, {16, 16}}"} \ No newline at end of file diff --git a/img/filetypes.json b/img/filetypes.json index 18c05e411..1a9ffc836 100644 --- a/img/filetypes.json +++ b/img/filetypes.json @@ -13,30 +13,6 @@ "replace" : "#969696", "variable" : "fileFillColor" }, - "fill=\"#49abea\"" : { - "description" : "Fill color used in office document", - - "replace" : "#49abea", - "variable" : "documentFileFillColor" - }, - "fill=\"#f0965f\"" : { - "description" : "Fill color used in presentation document", - - "replace" : "#f0965f", - "variable" : "presentationFileFillColor" - }, - "fill=\"#9abd4e\"" : { - "description" : "Fill color used in spreadsheet document", - - "replace" : "#9abd4e", - "variable" : "spreadsheetFileFillColor" - }, - "fill=\"#dc5047\"" : { - "description" : "Fill color used in PDF document", - - "replace" : "#dc5047", - "variable" : "pdfFileFillColor" - }, "fill=\"#1D293B\"" : { "description" : "Fill color used in logo", diff --git a/ios-sdk b/ios-sdk index b66dc8431..7ca86d879 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit b66dc8431ea634337fa7f97f5021f312282f09c0 +Subproject commit 7ca86d879b42f9336ff1ba00d8ead4006eb63388 diff --git a/ownCloud Action Extension/Info.plist b/ownCloud Action Extension/Info.plist deleted file mode 100644 index 244eda26e..000000000 --- a/ownCloud Action Extension/Info.plist +++ /dev/null @@ -1,50 +0,0 @@ - - - - - OCKeychainAccessGroupIdentifier - group.com.owncloud.ios-app - CFBundleIcons - - CFBundlePrimaryIcon - - CFBundleIconFiles - - branding-action-extension-icon - - - - OCHasFileProvider - - OCAppComponentIdentifier - shareExtension - CFBundleDisplayName - Save to $(APP_PRODUCT_NAME) - OCAppIdentifierPrefix - $(AppIdentifierPrefix) - OCAppGroupIdentifier - group.com.owncloud.ios-app - NSExtension - - NSExtensionAttributes - - NSExtensionActivationRule - SUBQUERY ( - extensionItems, - $extensionItem, - SUBQUERY ( - $extensionItem.attachments, - $attachment, - ( - ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.data" - ) - ).@count == $extensionItem.attachments.@count -).@count > 0 - - NSExtensionPrincipalClass - ShareExtensionViewController - NSExtensionPointIdentifier - com.apple.ui-services - - - diff --git a/ownCloud Action Extension/de.lproj/InfoPlist.strings b/ownCloud Action Extension/de.lproj/InfoPlist.strings deleted file mode 100644 index 681bcc143..000000000 --- a/ownCloud Action Extension/de.lproj/InfoPlist.strings +++ /dev/null @@ -1,22 +0,0 @@ -/* - InfoPlist.strings - ownCloud - - Created by Matthias Hühne on 11/20/2023. - Copyright © 2020 ownCloud GmbH. All rights reserved. -*/ - -/* - * Copyright (C) 2020, ownCloud GmbH. - * - * This code is covered by the GNU Public License Version 3. - * - * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ - * You should have received a copy of this license along with this program. If not, see . - * - */ - -"CFBundleDisplayName" = "Speichern in ownCloud"; - -"The Share Extension is not available on this system." = "Die Erweiterung ist auf diesem System nicht verfügbar."; -"Share Extension unavailable" = "Erweiterung nicht verfügbar"; diff --git a/ownCloud Action Extension/en.lproj/InfoPlist.strings b/ownCloud Action Extension/en.lproj/InfoPlist.strings deleted file mode 100644 index edfd3700d..000000000 --- a/ownCloud Action Extension/en.lproj/InfoPlist.strings +++ /dev/null @@ -1,22 +0,0 @@ -/* - InfoPlist.strings - ownCloud - - Created by Matthias Hühne on 11/20/2023. - Copyright © 2020 ownCloud GmbH. All rights reserved. -*/ - -/* - * Copyright (C) 2020, ownCloud GmbH. - * - * This code is covered by the GNU Public License Version 3. - * - * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ - * You should have received a copy of this license along with this program. If not, see . - * - */ - -"CFBundleDisplayName" = "Save to ownCloud"; - -"The Share Extension is not available on this system." = "The Share Extension is not available on this system."; -"Share Extension unavailable" = "Share Extension unavailable"; diff --git a/ownCloud Action Extension/ownCloud Action Extension.entitlements b/ownCloud Action Extension/ownCloud Action Extension.entitlements deleted file mode 100644 index 988c47786..000000000 --- a/ownCloud Action Extension/ownCloud Action Extension.entitlements +++ /dev/null @@ -1,14 +0,0 @@ - - - - - com.apple.security.application-groups - - group.com.owncloud.ios-app - - keychain-access-groups - - $(AppIdentifierPrefix)group.com.owncloud.ios-app - - - diff --git a/ownCloud File Provider UI/CancelLabelViewController.swift b/ownCloud File Provider UI/CancelLabelViewController.swift index 240368673..60d5fd312 100644 --- a/ownCloud File Provider UI/CancelLabelViewController.swift +++ b/ownCloud File Provider UI/CancelLabelViewController.swift @@ -26,11 +26,9 @@ class CancelLabelViewController: UIViewController { @IBOutlet var label : UILabel! @IBOutlet var button : ThemeButton! - typealias CancelAction = (() -> Void) + var cancelAction: (() -> Void)? - var cancelAction: CancelAction? - - func updateCancelLabels(with message: String, buttonLabel: String? = nil) { + func updateCancelLabels(with message: String) { let collection = Theme.shared.activeCollection view.cssSelector = .toolbar @@ -40,7 +38,7 @@ class CancelLabelViewController: UIViewController { label.apply(css: collection.css, properties: [.stroke]) self.label.text = message - self.button.setTitle(buttonLabel ?? "Cancel".localized, for: .normal) + self.button.setTitle("Cancel".localized, for: .normal) } @IBAction func cancelScreen() { diff --git a/ownCloud File Provider UI/DocumentActionViewController.swift b/ownCloud File Provider UI/DocumentActionViewController.swift index 76a80b081..96cd62690 100644 --- a/ownCloud File Provider UI/DocumentActionViewController.swift +++ b/ownCloud File Provider UI/DocumentActionViewController.swift @@ -106,7 +106,7 @@ class DocumentActionViewController: FPUIActionExtensionViewController { prepareNavigationController() - showMessage(with: "Connecting…".localized) + showCancelLabel(with: "Connecting…".localized) var actionTypeLabel = "" var actionExtensionType : ActionExtensionType = .undefined @@ -139,7 +139,7 @@ class DocumentActionViewController: FPUIActionExtensionViewController { OnMainThread { if actionExtensionType == .sharing, core.connection.capabilities?.sharingAPIEnabled == false || item.isShareable == false { - self.showMessage(with: String(format: "%@ is not available for this item.".localized, actionTypeLabel)) + self.showCancelLabel(with: String(format: "%@ is not available for this item.".localized, actionTypeLabel)) } else if core.connectionStatus == .online { self.coreConnectionStatusObservation?.invalidate() self.coreConnectionStatusObservation = nil @@ -157,18 +157,18 @@ class DocumentActionViewController: FPUIActionExtensionViewController { } } else if core.connectionStatus == .connecting { triedConnecting = true - self.showMessage(with: "Connecting…".localized) + self.showCancelLabel(with: "Connecting…".localized) } else if core.connectionStatus == .offline || core.connectionStatus == .unavailable { // Display error if `.connecting` isn't reached within 2 seconds OnMainThread(after: 2) { if !triedConnecting { - self.showMessage(with: String(format: "%@ is not available, when this account is offline. Please open the app and log into your account before you can do this action.".localized, actionTypeLabel)) + self.showCancelLabel(with: String(format: "%@ is not available, when this account is offline. Please open the app and log into your account before you can do this action.".localized, actionTypeLabel)) } } // Display error if `.connecting` has already been reached if triedConnecting { - self.showMessage(with: String(format: "%@ is not available, when this account is offline. Please open the app and log into your account before you can do this action.".localized, actionTypeLabel)) + self.showCancelLabel(with: String(format: "%@ is not available, when this account is offline. Please open the app and log into your account before you can do this action.".localized, actionTypeLabel)) } } } @@ -180,18 +180,7 @@ class DocumentActionViewController: FPUIActionExtensionViewController { override func prepare(forError error: Error) { if !OCFileProviderSettings.browseable { prepareNavigationController() - showMessage(with: "File Provider access has been disabled by the administrator.\n\nPlease use the app to access your files.".localized) - return - } - - if OCBookmarkManager.shared.bookmarks.count == 0 { - prepareNavigationController() - showMessage(with: "No account has been set up in the {{app.name}} app yet.".localized, buttonLabel: "Open app".localized, action: { [weak self] in - if let appURLScheme = OCAppIdentity.shared.appURLSchemes?.first { - self?.extensionContext.open(URL(string: "\(appURLScheme)://fp-no-account")!) - } - self?.complete() - }) + showCancelLabel(with: "File Provider access has been disabled by the administrator.\n\nPlease use the app to access your files.".localized) return } @@ -208,29 +197,20 @@ class DocumentActionViewController: FPUIActionExtensionViewController { AppLockManager.shared.showLockscreenIfNeeded() } else { prepareNavigationController() - showMessage(with: "Passcode protection is not supported on this device.\nPlease disable passcode lock in the app settings.".localized) + showCancelLabel(with: "Passcode protection is not supported on this device.\nPlease disable passcode lock in the app settings.".localized) } } - func showMessage(with message: String, buttonLabel: String? = nil, action: CancelLabelViewController.CancelAction? = nil) { + func showCancelLabel(with message: String) { OnMainThread { - var messageController: CancelLabelViewController? - if let currentController = self.themeNavigationController?.viewControllers.first as? CancelLabelViewController { - messageController = currentController + currentController.updateCancelLabels(with: message) } else if let cancelLabelViewController = UIStoryboard.init(name: "MainInterface", bundle: nil).instantiateViewController(withIdentifier: "CancelLabelViewController") as? CancelLabelViewController { - messageController = cancelLabelViewController - } - - if let messageController { - messageController.updateCancelLabels(with: message, buttonLabel: buttonLabel) - messageController.cancelAction = action ?? { [weak self] in + cancelLabelViewController.updateCancelLabels(with: message) + cancelLabelViewController.cancelAction = { [weak self] in self?.complete(cancelWith: NSError(domain: FPUIErrorDomain, code: Int(FPUIExtensionErrorCode.userCancelled.rawValue), userInfo: nil)) } - - if self.themeNavigationController?.viewControllers.first != messageController { - self.themeNavigationController?.viewControllers = [ messageController ] - } + self.themeNavigationController?.viewControllers = [ cancelLabelViewController ] } } } diff --git a/ownCloud File Provider/FileProviderExtension.m b/ownCloud File Provider/FileProviderExtension.m index 527588bfa..985a9ed62 100644 --- a/ownCloud File Provider/FileProviderExtension.m +++ b/ownCloud File Provider/FileProviderExtension.m @@ -1071,8 +1071,6 @@ - (NSProgress *)fetchThumbnailsForItemIdentifiers:(NSArray 256) @@ -1171,7 +1169,7 @@ - (OCCore *)core - (OCCore *)coreWithError:(NSError **)outError { - OCLogVerbose(@"FileProviderExtension[%p].core[enter]: _core=%p, bookmark=%@", self, _core, self.bookmark); + OCLogDebug(@"FileProviderExtension[%p].core[enter]: _core=%p, bookmark=%@", self, _core, self.bookmark); OCBookmark *bookmark = self.bookmark; __block OCCore *retCore = nil; @@ -1255,7 +1253,7 @@ - (OCCore *)coreWithError:(NSError **)outError *outError = retError; } - OCLogVerbose(@"FileProviderExtension[%p].core[leave]: _core=%p, bookmark=%@", self, retCore, bookmark); + OCLogDebug(@"FileProviderExtension[%p].core[leave]: _core=%p, bookmark=%@", self, retCore, bookmark); return (retCore); diff --git a/ownCloud File Provider/FileProviderExtensionThumbnailRequest.m b/ownCloud File Provider/FileProviderExtensionThumbnailRequest.m index 4c9bfd82f..1ce929d8a 100644 --- a/ownCloud File Provider/FileProviderExtensionThumbnailRequest.m +++ b/ownCloud File Provider/FileProviderExtensionThumbnailRequest.m @@ -22,7 +22,7 @@ @interface FileProviderExtensionThumbnailRequest () { BOOL _isDone; - __weak OCResourceRequestItemThumbnail *_thumbnailRequest; + OCResourceRequestItemThumbnail *_thumbnailRequest; } @end @@ -102,7 +102,7 @@ - (void)requestNextThumbnail dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{ NSError *returnError = (thumbnail==nil) ? - ((error != nil) ? error.translatedError : nil) : + ((error != nil) ? error.translatedError : OCError(OCErrorInternal)) : nil; self.perThumbnailCompletionHandler(itemIdentifier, thumbnail.data, returnError); diff --git a/ownCloud.xcodeproj/project.pbxproj b/ownCloud.xcodeproj/project.pbxproj index 8bacbe3de..49c183fed 100644 --- a/ownCloud.xcodeproj/project.pbxproj +++ b/ownCloud.xcodeproj/project.pbxproj @@ -36,17 +36,13 @@ 39057AA3233BA7A60008E6C0 /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 39057AAA233BA7A60008E6C0 /* Intents.intentdefinition */; settings = {ATTRIBUTES = (no_codegen, ); }; }; 39057AA4233BA7A60008E6C0 /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 39057AAA233BA7A60008E6C0 /* Intents.intentdefinition */; settings = {ATTRIBUTES = (no_codegen, ); }; }; 39057AA7233BA7A60008E6C0 /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 39057AAA233BA7A60008E6C0 /* Intents.intentdefinition */; settings = {ATTRIBUTES = (no_codegen, ); }; }; + 391130112A20E3F200C22DD2 /* branding-sidebar-link-icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 391130102A20E3F100C22DD2 /* branding-sidebar-link-icon.png */; }; 3912208223436EB80026C290 /* SortMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3912208123436EB80026C290 /* SortMethod.swift */; }; 3912D8AD29958BF400EDCB9A /* OCThemeValues.h in Headers */ = {isa = PBXBuildFile; fileRef = 3912D8AB29958BF400EDCB9A /* OCThemeValues.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3912D8AE29958BF400EDCB9A /* OCThemeValues.m in Sources */ = {isa = PBXBuildFile; fileRef = 3912D8AC29958BF400EDCB9A /* OCThemeValues.m */; }; - 391933C22B0B81DB007DF90B /* ownCloud Action Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 391933B42B0B81DB007DF90B /* ownCloud Action Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - 391933C62B0B8E5A007DF90B /* ShareExtensionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC9B4FC42940F8D60037F8F8 /* ShareExtensionViewController.swift */; }; - 391933CD2B0B8EBD007DF90B /* ownCloudApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCC0855C2293F1FD008CC05C /* ownCloudApp.framework */; }; - 391933CE2B0B8EC0007DF90B /* ownCloudAppShared.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 394A0AF922EEFC2C00603813 /* ownCloudAppShared.framework */; }; - 391933CF2B0B8EC3007DF90B /* ownCloudSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 239369782076110900BCE21A /* ownCloudSDK.framework */; }; - 391933D02B0B8EC7007DF90B /* ownCloudUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2393697C2076110900BCE21A /* ownCloudUI.framework */; }; - 391933DA2B0B9863007DF90B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 391933DC2B0B9863007DF90B /* InfoPlist.strings */; }; 391C79A824E186DC00CB6333 /* OCBookmark+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC136581208223F000FC0F60 /* OCBookmark+Extension.swift */; }; + 392378FF24EBD1A1006E86DE /* branding-splashscreen.png in Resources */ = {isa = PBXBuildFile; fileRef = 39F48A6624D848550000E3F9 /* branding-splashscreen.png */; }; + 3923790524EBD1A5006E86DE /* branding-splashscreen-background.png in Resources */ = {isa = PBXBuildFile; fileRef = 39F48A6724D848550000E3F9 /* branding-splashscreen-background.png */; }; 392CFEB72705831700631D2B /* LAContext+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 392CFEB62705831700631D2B /* LAContext+Extension.swift */; }; 392DDAE624C8923B009E5406 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 233BDEA6204FEFE500C06732 /* Assets.xcassets */; }; 392DDB1424CF024D009E5406 /* ImportFilesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 392DDB1324CF024C009E5406 /* ImportFilesController.swift */; }; @@ -58,6 +54,7 @@ 394A0B0122EEFC2C00603813 /* ownCloudAppShared.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 394A0AF922EEFC2C00603813 /* ownCloudAppShared.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 394A0B0922EEFCE400603813 /* ownCloudAppShared.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 394A0AF922EEFC2C00603813 /* ownCloudAppShared.framework */; }; 394A0B0A22EEFCF500603813 /* ownCloudSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 239369782076110900BCE21A /* ownCloudSDK.framework */; }; + 394B0CFC29F958200005CBFE /* AccountSettingsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 394B0CFB29F958200005CBFE /* AccountSettingsProvider.swift */; }; 394E1FDA233E2D64009D2897 /* FavoriteAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 394E1FD9233E2D64009D2897 /* FavoriteAction.swift */; }; 394E1FDC233E3750009D2897 /* UnfavoriteAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 394E1FDB233E3750009D2897 /* UnfavoriteAction.swift */; }; 39534BC724EA903200AD7907 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 39534BC924EA903200AD7907 /* InfoPlist.strings */; }; @@ -68,6 +65,8 @@ 396C82FB2319AFDD00938262 /* CollaborateAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 396C82FA2319AFDD00938262 /* CollaborateAction.swift */; }; 396D7C6523224A53002380C1 /* DiscardSceneAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 396D7C5F23224A53002380C1 /* DiscardSceneAction.swift */; }; 397754F82327A33500119FCB /* OpenSceneAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 397754F22327A33500119FCB /* OpenSceneAction.swift */; }; + 398393BE246D63B0001A212B /* branding-login-background.png in Resources */ = {isa = PBXBuildFile; fileRef = 398393BC246D63B0001A212B /* branding-login-background.png */; }; + 398393BF246D63B0001A212B /* branding-login-logo.png in Resources */ = {isa = PBXBuildFile; fileRef = 398393BD246D63B0001A212B /* branding-login-logo.png */; }; 39878B7421FB1DE800DBF693 /* UINavigationController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39878B7321FB1DE800DBF693 /* UINavigationController+Extension.swift */; }; 399697F5260255B100E5AEBA /* PDFGotoPageAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 399697F1260255B100E5AEBA /* PDFGotoPageAction.swift */; }; 399698ED260A3CEE00E5AEBA /* ImportPasteboardAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 391220922344C30F0026C290 /* ImportPasteboardAction.swift */; }; @@ -99,6 +98,7 @@ 39E104CA24C585C30085FDDD /* (null) in Resources */ = {isa = PBXBuildFile; }; 39E6DE86233CDF1E008DAE04 /* OCItemTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39E6DE85233CDF1E008DAE04 /* OCItemTracker.swift */; }; 39EF06B325D6C3FC001E1E19 /* PresentationModeAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39EF06AF25D6C3FC001E1E19 /* PresentationModeAction.swift */; }; + 39F48A6A24D89D7E0000E3F9 /* branding-bookmark-icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 39F48A6524D847D70000E3F9 /* branding-bookmark-icon.png */; }; 4C05D8A5238708D40073EF50 /* MediaUploadStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C05D8A4238708D40073EF50 /* MediaUploadStorage.swift */; }; 4C11EE5B22E88D4200B84869 /* InstantMediaUploadTaskExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C11EE5A22E88D4200B84869 /* InstantMediaUploadTaskExtension.swift */; }; 4C1561E8222321E0009C4EF3 /* PhotoSelectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1561E7222321E0009C4EF3 /* PhotoSelectionViewController.swift */; }; @@ -223,11 +223,6 @@ DC20DE6B21C01B210096000B /* ownCloudUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2393697C2076110900BCE21A /* ownCloudUI.framework */; }; DC2218C62822C5B900808BCE /* OCVFSNode+FileProviderItem.m in Sources */ = {isa = PBXBuildFile; fileRef = DC2218C52822C5B900808BCE /* OCVFSNode+FileProviderItem.m */; }; DC2218CC2823329100808BCE /* FileProviderContentEnumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = DC2218CB2823329100808BCE /* FileProviderContentEnumerator.m */; }; - DC2323DC2AA7B5D600BFF393 /* BookmarkComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC2323DB2AA7B5D600BFF393 /* BookmarkComposer.swift */; }; - DC2323DE2AA7B6BB00BFF393 /* BookmarkComposerConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC2323DD2AA7B6BB00BFF393 /* BookmarkComposerConfiguration.swift */; }; - DC2323E02AA7C59400BFF393 /* BookmarkSetupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC2323DF2AA7C59400BFF393 /* BookmarkSetupViewController.swift */; }; - DC2323E32AA85D0300BFF393 /* BookmarkSetupStepViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC2323E22AA85D0300BFF393 /* BookmarkSetupStepViewController.swift */; }; - DC2323E62AA865A700BFF393 /* BookmarkSetupStepEnterURLViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC2323E52AA865A700BFF393 /* BookmarkSetupStepEnterURLViewController.swift */; }; DC23D1D9238F390A00423F62 /* OCLicenseAppStoreReceipt.m in Sources */ = {isa = PBXBuildFile; fileRef = DC23D1D7238F390200423F62 /* OCLicenseAppStoreReceipt.m */; }; DC23D1DA238F391200423F62 /* OCLicenseAppStoreReceipt.h in Headers */ = {isa = PBXBuildFile; fileRef = DC23D1D6238F390200423F62 /* OCLicenseAppStoreReceipt.h */; settings = {ATTRIBUTES = (Public, ); }; }; DC24B28725BA2A2E005783E2 /* Branding.h in Headers */ = {isa = PBXBuildFile; fileRef = DC24B27125B9DF31005783E2 /* Branding.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -249,7 +244,6 @@ DC27A1A520CBEF85008ACB6C /* OCBookmark+FileProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = DC27A1A420CBEF85008ACB6C /* OCBookmark+FileProvider.m */; }; DC27A1A820CC095C008ACB6C /* OCCore+FileProviderTools.m in Sources */ = {isa = PBXBuildFile; fileRef = DC27A1A720CC095C008ACB6C /* OCCore+FileProviderTools.m */; }; DC27A1E920CC56B0008ACB6C /* FileProviderExtensionThumbnailRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = DC27A1E820CC56B0008ACB6C /* FileProviderExtensionThumbnailRequest.m */; }; - DC28297E2AAF02A800BFF393 /* BookmarkSetupStepIntroViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC28297D2AAF02A800BFF393 /* BookmarkSetupStepIntroViewController.swift */; }; DC28F826294B733700AC4013 /* OCItemPolicy+Interactions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC28F825294B733700AC4013 /* OCItemPolicy+Interactions.swift */; }; DC28F828294BB5ED00AC4013 /* SortedItemDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC28F827294BB5ED00AC4013 /* SortedItemDataSource.swift */; }; DC298C922934CF56009FA87F /* AccountConnectionErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC298C8C2934B3E7009FA87F /* AccountConnectionErrorHandler.swift */; }; @@ -309,11 +303,6 @@ DC4C575D233958B70098BAE9 /* FixedHeightImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC4C575C233958B70098BAE9 /* FixedHeightImageView.swift */; }; DC51FD922475715F0069AB79 /* CellularSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC51FD912475715F0069AB79 /* CellularSettingsViewController.swift */; }; DC576EC022647A070087316D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DC576EC222647A070087316D /* Localizable.strings */; }; - DC5908752AA87A1700BFF393 /* BookmarkSetupStepEnterUsernameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC5908742AA87A1700BFF393 /* BookmarkSetupStepEnterUsernameViewController.swift */; }; - DC5908772AA87ABF00BFF393 /* BookmarkSetupStepAuthenticateViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC5908762AA87ABF00BFF393 /* BookmarkSetupStepAuthenticateViewController.swift */; }; - DC59087A2AA87F6B00BFF393 /* BookmarkSetupStepFinishedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC5908792AA87F6B00BFF393 /* BookmarkSetupStepFinishedViewController.swift */; }; - DC59087D2AA8B82200BFF393 /* BookmarkSetupStepPrepopulateViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC59087C2AA8B82200BFF393 /* BookmarkSetupStepPrepopulateViewController.swift */; }; - DC59087F2AA8D25400BFF393 /* CertificateSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC59087E2AA8D25400BFF393 /* CertificateSummaryView.swift */; }; DC5C48A32918FB7400EBC053 /* CollectionSidebarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC5C48A22918FB7400EBC053 /* CollectionSidebarViewController.swift */; }; DC5D58FF2A7166A300BFF393 /* ThemeCSS+SystemColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC5D58FE2A7166A300BFF393 /* ThemeCSS+SystemColors.swift */; }; DC60F2A629802ABE00905EC8 /* UINavigationItem+NavigationContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC60F2A529802ABE00905EC8 /* UINavigationItem+NavigationContent.swift */; }; @@ -408,8 +397,6 @@ DC9BFBB320A19AF4007064B5 /* doc in Resources */ = {isa = PBXBuildFile; fileRef = DC9BFBB220A19AF3007064B5 /* doc */; }; DC9BFBBD20A1C37B007064B5 /* PasswordManagerAccess.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC9BFBBC20A1C37B007064B5 /* PasswordManagerAccess.swift */; }; DC9C1AEC247C76470067895A /* MessageGroupCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC9C1AEB247C76470067895A /* MessageGroupCell.swift */; }; - DCA05A602AE6603E00BFF393 /* ClientLocationPopupButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCA05A5F2AE6603E00BFF393 /* ClientLocationPopupButton.swift */; }; - DCA05A622AE664F200BFF393 /* OCAction+UIAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCA05A612AE664F200BFF393 /* OCAction+UIAction.swift */; }; DCA2EDE2279B16F1001F04E6 /* ResourceSourceItemIcons.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCA2EDE1279B16F1001F04E6 /* ResourceSourceItemIcons.swift */; }; DCA2EDE4279B1789001F04E6 /* ResourceItemIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCA2EDE3279B1789001F04E6 /* ResourceItemIcon.swift */; }; DCA35D3F24CEDA5200DBE2B0 /* DiagnosticViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCA35D3E24CEDA5200DBE2B0 /* DiagnosticViewController.swift */; }; @@ -512,6 +499,7 @@ DCD864122811FC5700CA6631 /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCD864112811FC5700CA6631 /* GradientView.swift */; }; DCD954DF247D62FA00E184E6 /* MessageTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCD954DE247D62FA00E184E6 /* MessageTableViewController.swift */; }; DCD9B87B2379612B00691929 /* OCLicenseManager+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = DCD9B873237960E600691929 /* OCLicenseManager+Internal.h */; }; + DCDA83852A9CE6C300BFF393 /* InitialSetupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCDA83842A9CE6C300BFF393 /* InitialSetupViewController.swift */; }; DCDBB60A2525305600FAD707 /* NotificationAuthErrorForwarder.h in Headers */ = {isa = PBXBuildFile; fileRef = DCDBB60225252FDA00FAD707 /* NotificationAuthErrorForwarder.h */; settings = {ATTRIBUTES = (Public, ); }; }; DCDBB60B2525306000FAD707 /* NotificationAuthErrorForwarder.m in Sources */ = {isa = PBXBuildFile; fileRef = DCDBB60325252FDA00FAD707 /* NotificationAuthErrorForwarder.m */; }; DCDC0ACF23CD186400DFE36D /* ownCloudApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCC0855C2293F1FD008CC05C /* ownCloudApp.framework */; }; @@ -575,7 +563,6 @@ DCE684F6241BD4E800799C30 /* Branding.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3931206A2326451900E8DFBA /* Branding.plist */; }; DCEA7F41282D3B110050A3C0 /* VFSManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DCEA7F3F282D3B110050A3C0 /* VFSManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; DCEA7F42282D3B110050A3C0 /* VFSManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DCEA7F40282D3B110050A3C0 /* VFSManager.m */; }; - DCEA89822AD84D6000BFF393 /* BrandView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCEA89812AD84D6000BFF393 /* BrandView.swift */; }; DCEAF06D280767CF00980B6D /* OpenSSL in Frameworks */ = {isa = PBXBuildFile; productRef = DCEAF06C280767CF00980B6D /* OpenSSL */; }; DCEAF08A2808254800980B6D /* DriveListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCEAF0892808254800980B6D /* DriveListCell.swift */; }; DCEAF08D28084B3800980B6D /* Down in Frameworks */ = {isa = PBXBuildFile; productRef = DCEAF08C28084B3800980B6D /* Down */; }; @@ -665,34 +652,6 @@ remoteGlobalIDString = DC7E0A77203732B3006111FA; remoteInfo = Ocean; }; - 391933C02B0B81DB007DF90B /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 233BDE94204FEFE500C06732 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 391933B32B0B81DB007DF90B; - remoteInfo = "ownCloud Action Extension"; - }; - 391933C72B0B8EA2007DF90B /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 233BDE94204FEFE500C06732 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DCC0855B2293F1FD008CC05C; - remoteInfo = ownCloudApp; - }; - 391933C92B0B8EA5007DF90B /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 233BDE94204FEFE500C06732 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 394A0AF822EEFC2C00603813; - remoteInfo = ownCloudAppShared; - }; - 391933CB2B0B8EA9007DF90B /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 233BDEBF204FEFF300C06732 /* ownCloudSDK.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = DCC8F9AA202852A200EB6701; - remoteInfo = ownCloudSDK; - }; 394A0AFE22EEFC2C00603813 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 233BDE94204FEFE500C06732 /* Project object */; @@ -798,13 +757,6 @@ remoteGlobalIDString = DCC8F9AA202852A200EB6701; remoteInfo = ownCloudSDK; }; - DC2A6C752AC6BE0100BFF393 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 233BDEBF204FEFF300C06732 /* ownCloudSDK.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = DC3094832057358800189B9A; - remoteInfo = ownCloudUI; - }; DC3BE0CE2077BC52002A0AC0 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 233BDEBF204FEFF300C06732 /* ownCloudSDK.xcodeproj */; @@ -970,7 +922,6 @@ 39A7138722E79C6700089423 /* ownCloud Intents.appex in Embed Foundation Extensions */, DCE4E47224C1F5610051722F /* ownCloud Share Extension.appex in Embed Foundation Extensions */, DCC6566520C9B7E400110A97 /* ownCloud File Provider.appex in Embed Foundation Extensions */, - 391933C22B0B81DB007DF90B /* ownCloud Action Extension.appex in Embed Foundation Extensions */, 39DC7CD725C2E1570001E08C /* ownCloud File Provider UI.appex in Embed Foundation Extensions */, ); name = "Embed Foundation Extensions"; @@ -1021,17 +972,12 @@ 39057AA9233BA7A60008E6C0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; name = Base; path = Base.lproj/Intents.intentdefinition; sourceTree = ""; }; 39057AB1233BA7AE0008E6C0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Intents.strings; sourceTree = ""; }; 39104E0A223991C8002FC02F /* UIButton+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIButton+Extension.swift"; sourceTree = ""; }; + 391130102A20E3F100C22DD2 /* branding-sidebar-link-icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "branding-sidebar-link-icon.png"; sourceTree = ""; }; 3912208123436EB80026C290 /* SortMethod.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SortMethod.swift; sourceTree = ""; }; 391220922344C30F0026C290 /* ImportPasteboardAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportPasteboardAction.swift; sourceTree = ""; }; 391220932344C30F0026C290 /* CutAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CutAction.swift; sourceTree = ""; }; 3912D8AB29958BF400EDCB9A /* OCThemeValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCThemeValues.h; sourceTree = ""; }; 3912D8AC29958BF400EDCB9A /* OCThemeValues.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OCThemeValues.m; sourceTree = ""; }; - 391933B42B0B81DB007DF90B /* ownCloud Action Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "ownCloud Action Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; - 391933B52B0B81DB007DF90B /* UniformTypeIdentifiers.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UniformTypeIdentifiers.framework; path = System/Library/Frameworks/UniformTypeIdentifiers.framework; sourceTree = SDKROOT; }; - 391933BF2B0B81DB007DF90B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 391933D12B0B9577007DF90B /* ownCloud Action Extension.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = "ownCloud Action Extension.entitlements"; sourceTree = ""; }; - 391933DB2B0B9863007DF90B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 391933DD2B0B9871007DF90B /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = ""; }; 392CFEB62705831700631D2B /* LAContext+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "LAContext+Extension.swift"; sourceTree = ""; }; 392DDB1324CF024C009E5406 /* ImportFilesController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportFilesController.swift; sourceTree = ""; }; 3931206A2326451900E8DFBA /* Branding.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Branding.plist; path = ownCloud/Resources/Theming/Branding.plist; sourceTree = SOURCE_ROOT; }; @@ -1039,6 +985,7 @@ 394A0AF922EEFC2C00603813 /* ownCloudAppShared.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ownCloudAppShared.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 394A0AFB22EEFC2C00603813 /* ownCloudAppShared.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ownCloudAppShared.h; sourceTree = ""; }; 394A0AFC22EEFC2C00603813 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 394B0CFB29F958200005CBFE /* AccountSettingsProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountSettingsProvider.swift; sourceTree = ""; }; 394E1FD9233E2D64009D2897 /* FavoriteAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FavoriteAction.swift; sourceTree = ""; }; 394E1FDB233E3750009D2897 /* UnfavoriteAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnfavoriteAction.swift; sourceTree = ""; }; 39534BC824EA903200AD7907 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -1072,6 +1019,8 @@ 397754E123279EED00119FCB /* OCItem+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "OCItem+Extension.swift"; sourceTree = ""; }; 397754F22327A33500119FCB /* OpenSceneAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenSceneAction.swift; sourceTree = ""; }; 397E276B23D05A5400117B07 /* ServerListToolCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServerListToolCell.swift; sourceTree = ""; }; + 398393BC246D63B0001A212B /* branding-login-background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "branding-login-background.png"; path = "ownCloud/Resources/Theming/branding-login-background.png"; sourceTree = SOURCE_ROOT; }; + 398393BD246D63B0001A212B /* branding-login-logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "branding-login-logo.png"; path = "ownCloud/Resources/Theming/branding-login-logo.png"; sourceTree = SOURCE_ROOT; }; 3984F56B2319202200DC2639 /* DeletePathItemIntentHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeletePathItemIntentHandler.swift; sourceTree = ""; }; 39878B7321FB1DE800DBF693 /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = ""; }; 39880BAA233B5236006EA539 /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/Localizable.strings; sourceTree = ""; }; @@ -1152,6 +1101,9 @@ 39E42D1B2315288B00B82AC3 /* KeyCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyCommands.swift; sourceTree = ""; }; 39E6DE85233CDF1E008DAE04 /* OCItemTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OCItemTracker.swift; sourceTree = ""; }; 39EF06AF25D6C3FC001E1E19 /* PresentationModeAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PresentationModeAction.swift; sourceTree = ""; }; + 39F48A6524D847D70000E3F9 /* branding-bookmark-icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "branding-bookmark-icon.png"; path = "ownCloud/Resources/Theming/branding-bookmark-icon.png"; sourceTree = SOURCE_ROOT; }; + 39F48A6624D848550000E3F9 /* branding-splashscreen.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "branding-splashscreen.png"; path = "ownCloud/Resources/Theming/branding-splashscreen.png"; sourceTree = SOURCE_ROOT; }; + 39F48A6724D848550000E3F9 /* branding-splashscreen-background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "branding-splashscreen-background.png"; path = "ownCloud/Resources/Theming/branding-splashscreen-background.png"; sourceTree = SOURCE_ROOT; }; 39F689A922EF5EDC00E63429 /* ownCloud Intents.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "ownCloud Intents.entitlements"; sourceTree = ""; }; 39F689AA22F018C100E63429 /* GetDirectoryListingIntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetDirectoryListingIntentHandler.swift; sourceTree = ""; }; 42866B2892DC9EDC65D844E7 /* Pods_ownCloud_Screenshots_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ownCloud_Screenshots_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1254,6 +1206,7 @@ DC081C8A299B9B9000BFF393 /* AppStateActionGoToPersonalFolder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppStateActionGoToPersonalFolder.swift; sourceTree = ""; }; DC0A35A024C1091400FB58FC /* UserInterfaceContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserInterfaceContext.swift; sourceTree = ""; }; DC0A5C422550C70800E6674B /* class-settings-sdk */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "class-settings-sdk"; path = "ios-sdk/doc/class-settings-sdk"; sourceTree = SOURCE_ROOT; }; + DC0B379320514E4700189B9A /* ServerListBookmarkCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerListBookmarkCell.swift; sourceTree = ""; }; DC0B37952051541C00189B9A /* ownCloud.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ownCloud.entitlements; sourceTree = ""; }; DC0B37962051681600189B9A /* ThemeButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeButton.swift; sourceTree = ""; }; DC0CE19128C7DBE3009ABDFB /* OpenInWebAppAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenInWebAppAction.swift; sourceTree = ""; }; @@ -1265,11 +1218,6 @@ DC2218C52822C5B900808BCE /* OCVFSNode+FileProviderItem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "OCVFSNode+FileProviderItem.m"; sourceTree = ""; }; DC2218CA2823329100808BCE /* FileProviderContentEnumerator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FileProviderContentEnumerator.h; sourceTree = ""; }; DC2218CB2823329100808BCE /* FileProviderContentEnumerator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FileProviderContentEnumerator.m; sourceTree = ""; }; - DC2323DB2AA7B5D600BFF393 /* BookmarkComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkComposer.swift; sourceTree = ""; }; - DC2323DD2AA7B6BB00BFF393 /* BookmarkComposerConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkComposerConfiguration.swift; sourceTree = ""; }; - DC2323DF2AA7C59400BFF393 /* BookmarkSetupViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkSetupViewController.swift; sourceTree = ""; }; - DC2323E22AA85D0300BFF393 /* BookmarkSetupStepViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkSetupStepViewController.swift; sourceTree = ""; }; - DC2323E52AA865A700BFF393 /* BookmarkSetupStepEnterURLViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkSetupStepEnterURLViewController.swift; sourceTree = ""; }; DC23D1D6238F390200423F62 /* OCLicenseAppStoreReceipt.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OCLicenseAppStoreReceipt.h; sourceTree = ""; }; DC23D1D7238F390200423F62 /* OCLicenseAppStoreReceipt.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OCLicenseAppStoreReceipt.m; sourceTree = ""; }; DC243BF92317B446004FBB5C /* ThemeWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThemeWindow.swift; sourceTree = ""; }; @@ -1298,7 +1246,6 @@ DC27A1A720CC095C008ACB6C /* OCCore+FileProviderTools.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "OCCore+FileProviderTools.m"; sourceTree = ""; }; DC27A1E720CC56B0008ACB6C /* FileProviderExtensionThumbnailRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FileProviderExtensionThumbnailRequest.h; sourceTree = ""; }; DC27A1E820CC56B0008ACB6C /* FileProviderExtensionThumbnailRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FileProviderExtensionThumbnailRequest.m; sourceTree = ""; }; - DC28297D2AAF02A800BFF393 /* BookmarkSetupStepIntroViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkSetupStepIntroViewController.swift; sourceTree = ""; }; DC28F825294B733700AC4013 /* OCItemPolicy+Interactions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OCItemPolicy+Interactions.swift"; sourceTree = ""; }; DC28F827294BB5ED00AC4013 /* SortedItemDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SortedItemDataSource.swift; sourceTree = ""; }; DC298C8C2934B3E7009FA87F /* AccountConnectionErrorHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountConnectionErrorHandler.swift; sourceTree = ""; }; @@ -1360,11 +1307,6 @@ DC4FEAE9209E48E800D4476B /* DispatchQueueTools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DispatchQueueTools.swift; sourceTree = ""; }; DC51FD912475715F0069AB79 /* CellularSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellularSettingsViewController.swift; sourceTree = ""; }; DC576EC122647A070087316D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; - DC5908742AA87A1700BFF393 /* BookmarkSetupStepEnterUsernameViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkSetupStepEnterUsernameViewController.swift; sourceTree = ""; }; - DC5908762AA87ABF00BFF393 /* BookmarkSetupStepAuthenticateViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkSetupStepAuthenticateViewController.swift; sourceTree = ""; }; - DC5908792AA87F6B00BFF393 /* BookmarkSetupStepFinishedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkSetupStepFinishedViewController.swift; sourceTree = ""; }; - DC59087C2AA8B82200BFF393 /* BookmarkSetupStepPrepopulateViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkSetupStepPrepopulateViewController.swift; sourceTree = ""; }; - DC59087E2AA8D25400BFF393 /* CertificateSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CertificateSummaryView.swift; sourceTree = ""; }; DC5C48A22918FB7400EBC053 /* CollectionSidebarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionSidebarViewController.swift; sourceTree = ""; }; DC5D58FE2A7166A300BFF393 /* ThemeCSS+SystemColors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ThemeCSS+SystemColors.swift"; sourceTree = ""; }; DC5D9E742496512400BFFE8E /* MessageQueueExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageQueueExample.swift; sourceTree = ""; }; @@ -1409,7 +1351,6 @@ DC6C68352574FD0400E46BD4 /* PLCrashReporter.LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = PLCrashReporter.LICENSE; sourceTree = ""; }; DC6CC3142642C3560040ECAC /* ExternalBrowserBusyHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExternalBrowserBusyHandler.swift; sourceTree = ""; }; DC6CF7FA219446050013B9F9 /* LogSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogSettingsViewController.swift; sourceTree = ""; }; - DC6F0B962AE90C4A00BFF393 /* com.owncloud.ios-app */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "com.owncloud.ios-app"; sourceTree = ""; }; DC6FDAF62953AD50004F0C7F /* ClientSharedWithMeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientSharedWithMeViewController.swift; sourceTree = ""; }; DC70398326128B89009F2DC1 /* NSString+ByteCountParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSString+ByteCountParser.h"; sourceTree = ""; }; DC70398426128B89009F2DC1 /* NSString+ByteCountParser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSString+ByteCountParser.m"; sourceTree = ""; }; @@ -1468,8 +1409,6 @@ DC9BFBBA20A1B3CA007064B5 /* icon-password-manager.tvg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "icon-password-manager.tvg"; path = "img/filetypes-tvg/icon-password-manager.tvg"; sourceTree = SOURCE_ROOT; }; DC9BFBBC20A1C37B007064B5 /* PasswordManagerAccess.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordManagerAccess.swift; sourceTree = ""; }; DC9C1AEB247C76470067895A /* MessageGroupCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageGroupCell.swift; sourceTree = ""; }; - DCA05A5F2AE6603E00BFF393 /* ClientLocationPopupButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientLocationPopupButton.swift; sourceTree = ""; }; - DCA05A612AE664F200BFF393 /* OCAction+UIAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OCAction+UIAction.swift"; sourceTree = ""; }; DCA2EDE1279B16F1001F04E6 /* ResourceSourceItemIcons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourceSourceItemIcons.swift; sourceTree = ""; }; DCA2EDE3279B1789001F04E6 /* ResourceItemIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourceItemIcon.swift; sourceTree = ""; }; DCA35D3E24CEDA5200DBE2B0 /* DiagnosticViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiagnosticViewController.swift; sourceTree = ""; }; @@ -1585,6 +1524,7 @@ DCD864112811FC5700CA6631 /* GradientView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = ""; }; DCD954DE247D62FA00E184E6 /* MessageTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageTableViewController.swift; sourceTree = ""; }; DCD9B873237960E600691929 /* OCLicenseManager+Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "OCLicenseManager+Internal.h"; sourceTree = ""; }; + DCDA83842A9CE6C300BFF393 /* InitialSetupViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InitialSetupViewController.swift; sourceTree = ""; }; DCDBB60225252FDA00FAD707 /* NotificationAuthErrorForwarder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NotificationAuthErrorForwarder.h; sourceTree = ""; }; DCDBB60325252FDA00FAD707 /* NotificationAuthErrorForwarder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NotificationAuthErrorForwarder.m; sourceTree = ""; }; DCDC0AD023CD18D200DFE36D /* OCLicenseManager+Setup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OCLicenseManager+Setup.swift"; sourceTree = ""; }; @@ -1629,13 +1569,11 @@ DCE5E89E2080D780005F60CE /* text-vcard.tvg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "text-vcard.tvg"; path = "img/filetypes-tvg/text-vcard.tvg"; sourceTree = SOURCE_ROOT; }; DCE5E89F2080D780005F60CE /* folder-shared.tvg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "folder-shared.tvg"; path = "img/filetypes-tvg/folder-shared.tvg"; sourceTree = SOURCE_ROOT; }; DCE5E8A02080D781005F60CE /* x-office-presentation.tvg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "x-office-presentation.tvg"; path = "img/filetypes-tvg/x-office-presentation.tvg"; sourceTree = SOURCE_ROOT; }; - DCE8AB722AE8121B00BFF393 /* branding-assets */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "branding-assets"; sourceTree = ""; }; DCE93FEE21FCA434000E14F2 /* libzip.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libzip.xcodeproj; path = external/libzip/libzip.xcodeproj; sourceTree = SOURCE_ROOT; }; DCE974B1207E3AF80069FC2B /* ThemeNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeNavigationController.swift; sourceTree = ""; }; DCE974BB207EACA60069FC2B /* UIImage+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Extension.swift"; sourceTree = ""; }; DCEA7F3F282D3B110050A3C0 /* VFSManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VFSManager.h; sourceTree = ""; }; DCEA7F40282D3B110050A3C0 /* VFSManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VFSManager.m; sourceTree = ""; }; - DCEA89812AD84D6000BFF393 /* BrandView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrandView.swift; sourceTree = ""; }; DCEAF0892808254800980B6D /* DriveListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DriveListCell.swift; sourceTree = ""; }; DCEC3DE3242F665D0076B43C /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; }; DCEE1C9B23A0EADD00FE8D98 /* LicenseOfferView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LicenseOfferView.swift; sourceTree = ""; }; @@ -1722,17 +1660,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 391933B12B0B81DB007DF90B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 391933D02B0B8EC7007DF90B /* ownCloudUI.framework in Frameworks */, - 391933CF2B0B8EC3007DF90B /* ownCloudSDK.framework in Frameworks */, - 391933CE2B0B8EC0007DF90B /* ownCloudAppShared.framework in Frameworks */, - 391933CD2B0B8EBD007DF90B /* ownCloudApp.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 394A0AF622EEFC2C00603813 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -1843,7 +1770,6 @@ 394A0AFA22EEFC2C00603813 /* ownCloudAppShared */, DCE4E46924C1F5610051722F /* ownCloud Share Extension */, 39DC7CCE25C2E1570001E08C /* ownCloud File Provider UI */, - 391933B72B0B81DB007DF90B /* ownCloud Action Extension */, 233BDE9D204FEFE500C06732 /* Products */, DC85573220513CC700189B9A /* Frameworks */, ); @@ -1863,7 +1789,6 @@ 394A0AF922EEFC2C00603813 /* ownCloudAppShared.framework */, DCE4E46824C1F5610051722F /* ownCloud Share Extension.appex */, 39DC7CCD25C2E1570001E08C /* ownCloud File Provider UI.appex */, - 391933B42B0B81DB007DF90B /* ownCloud Action Extension.appex */, ); name = Products; sourceTree = ""; @@ -1882,6 +1807,7 @@ DCC832D1242BB3E900153F8C /* Messages */, DC3BE0DB2077CC13002A0AC0 /* Client */, DCA35D6724CF7B6E00DBE2B0 /* Diagnostic */, + DC7DF17C205140F400189B9A /* Server List */, DCF4F1802051A91500189B9A /* Settings */, 39E42D152315286300B82AC3 /* Key Commands */, DC422448207CAED60006A2A6 /* Theming */, @@ -1988,16 +1914,6 @@ path = Client; sourceTree = ""; }; - 391933B72B0B81DB007DF90B /* ownCloud Action Extension */ = { - isa = PBXGroup; - children = ( - 391933DC2B0B9863007DF90B /* InfoPlist.strings */, - 391933D12B0B9577007DF90B /* ownCloud Action Extension.entitlements */, - 391933BF2B0B81DB007DF90B /* Info.plist */, - ); - path = "ownCloud Action Extension"; - sourceTree = ""; - }; 392DDB1224CF024C009E5406 /* Import */ = { isa = PBXGroup; children = ( @@ -2051,7 +1967,6 @@ 397754E023279EC100119FCB /* SDK Extensions */ = { isa = PBXGroup; children = ( - DCA05A612AE664F200BFF393 /* OCAction+UIAction.swift */, 399EA72525E6565900B6FF11 /* OCCore+Extension.swift */, 399EA71A25E6561D00B6FF11 /* OCShare+Extension.swift */, DC136581208223F000FC0F60 /* OCBookmark+Extension.swift */, @@ -2149,8 +2064,12 @@ 39C31F8E22F1A4F50023923D /* Theming */ = { isa = PBXGroup; children = ( - DCE8AB722AE8121B00BFF393 /* branding-assets */, - DC6F0B962AE90C4A00BFF393 /* com.owncloud.ios-app */, + 391130102A20E3F100C22DD2 /* branding-sidebar-link-icon.png */, + 39F48A6524D847D70000E3F9 /* branding-bookmark-icon.png */, + 398393BC246D63B0001A212B /* branding-login-background.png */, + 398393BD246D63B0001A212B /* branding-login-logo.png */, + 39F48A6624D848550000E3F9 /* branding-splashscreen.png */, + 39F48A6724D848550000E3F9 /* branding-splashscreen-background.png */, 3931206A2326451900E8DFBA /* Branding.plist */, ); name = Theming; @@ -2372,39 +2291,6 @@ path = "Cursor Support"; sourceTree = ""; }; - DC2323DA2AA7B5A100BFF393 /* Composer */ = { - isa = PBXGroup; - children = ( - DC2323DB2AA7B5D600BFF393 /* BookmarkComposer.swift */, - DC2323DD2AA7B6BB00BFF393 /* BookmarkComposerConfiguration.swift */, - ); - path = Composer; - sourceTree = ""; - }; - DC2323E12AA7C59900BFF393 /* Setup */ = { - isa = PBXGroup; - children = ( - DC2323DF2AA7C59400BFF393 /* BookmarkSetupViewController.swift */, - DC2323E22AA85D0300BFF393 /* BookmarkSetupStepViewController.swift */, - DC2323E72AA865DD00BFF393 /* Steps */, - ); - path = Setup; - sourceTree = ""; - }; - DC2323E72AA865DD00BFF393 /* Steps */ = { - isa = PBXGroup; - children = ( - DC28297D2AAF02A800BFF393 /* BookmarkSetupStepIntroViewController.swift */, - DC2323E52AA865A700BFF393 /* BookmarkSetupStepEnterURLViewController.swift */, - DC5908742AA87A1700BFF393 /* BookmarkSetupStepEnterUsernameViewController.swift */, - DC5908762AA87ABF00BFF393 /* BookmarkSetupStepAuthenticateViewController.swift */, - DC59087C2AA8B82200BFF393 /* BookmarkSetupStepPrepopulateViewController.swift */, - DC5908792AA87F6B00BFF393 /* BookmarkSetupStepFinishedViewController.swift */, - DC59087E2AA8D25400BFF393 /* CertificateSummaryView.swift */, - ); - path = Steps; - sourceTree = ""; - }; DC23D1D0238F38DF00423F62 /* Receipt */ = { isa = PBXGroup; children = ( @@ -2420,7 +2306,6 @@ isa = PBXGroup; children = ( DC24B2AA25BA316D005783E2 /* Branding+App.swift */, - DCEA89812AD84D6000BFF393 /* BrandView.swift */, ); path = Branding; sourceTree = ""; @@ -2583,7 +2468,6 @@ isa = PBXGroup; children = ( DC8E99E4297EEB2800594697 /* ClientLocationBarController.swift */, - DCA05A5F2AE6603E00BFF393 /* ClientLocationPopupButton.swift */, DC3F0C2429828AE300C832DB /* OCLocation+Breadcrumbs.swift */, ); path = "Location Breadcrumbs"; @@ -2807,6 +2691,14 @@ path = tools; sourceTree = ""; }; + DC7DF17C205140F400189B9A /* Server List */ = { + isa = PBXGroup; + children = ( + DC0B379320514E4700189B9A /* ServerListBookmarkCell.swift */, + ); + path = "Server List"; + sourceTree = ""; + }; DC82664028168DAA00F91F7D /* Context */ = { isa = PBXGroup; children = ( @@ -2841,7 +2733,6 @@ A56EA84D8AD331FFA604138B /* Pods_ownCloudTests.framework */, 42866B2892DC9EDC65D844E7 /* Pods_ownCloud_Screenshots_Tests.framework */, 54199937F74A129BC74DEB0A /* Pods_ownCloudScreenshotsTests.framework */, - 391933B52B0B81DB007DF90B /* UniformTypeIdentifiers.framework */, ); name = Frameworks; sourceTree = ""; @@ -3054,6 +2945,7 @@ DCB6B1EA292B7C2400D27573 /* AppRootViewController+ItemActions.swift */, DCB6B1F4292CC46B00D27573 /* AccountController+ItemActions.swift */, DCB6B20B292E428000D27573 /* AccountController+ExtraItems.swift */, + DCDA83842A9CE6C300BFF393 /* InitialSetupViewController.swift */, ); path = "App Controllers"; sourceTree = ""; @@ -3528,10 +3420,9 @@ DCF4F1612051925A00189B9A /* Bookmarks */ = { isa = PBXGroup; children = ( - DC2323DA2AA7B5A100BFF393 /* Composer */, - DC2323E12AA7C59900BFF393 /* Setup */, DC1B270B209CF34B004715E1 /* BookmarkViewController.swift */, 4CC46D202284C677009E938F /* BookmarkInfoViewController.swift */, + 394B0CFB29F958200005CBFE /* AccountSettingsProvider.swift */, ); path = Bookmarks; sourceTree = ""; @@ -3801,13 +3692,12 @@ buildPhases = ( 23813A32205286E100DB9488 /* Run SwiftLint */, 233BDE98204FEFE500C06732 /* Sources */, - DC85573420513CCC00189B9A /* Copy Frameworks */, 233BDE99204FEFE500C06732 /* Frameworks */, 233BDE9A204FEFE500C06732 /* Resources */, + DC85573420513CCC00189B9A /* Copy Frameworks */, DC63207821FCA6A4007EC0A8 /* Copy libzip license */, - DC6F0B952AE9014B00BFF393 /* Copy branding assets */, - DCC6567020C9B7E400110A97 /* Embed Foundation Extensions */, 23DFDCF120AEEC77003BD16B /* Update LastGitCommit key in Info.plist */, + DCC6567020C9B7E400110A97 /* Embed Foundation Extensions */, ); buildRules = ( ); @@ -3823,7 +3713,6 @@ DCE4E47124C1F5610051722F /* PBXTargetDependency */, DC0491AA258CAF9800DEDC27 /* PBXTargetDependency */, 39DC7CD625C2E1570001E08C /* PBXTargetDependency */, - 391933C12B0B81DB007DF90B /* PBXTargetDependency */, ); name = ownCloud; packageProductDependencies = ( @@ -3857,27 +3746,6 @@ productReference = 233BDEB0204FEFE500C06732 /* ownCloudTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; - 391933B32B0B81DB007DF90B /* ownCloud Action Extension */ = { - isa = PBXNativeTarget; - buildConfigurationList = 391933C32B0B81DC007DF90B /* Build configuration list for PBXNativeTarget "ownCloud Action Extension" */; - buildPhases = ( - 391933B02B0B81DB007DF90B /* Sources */, - 391933B12B0B81DB007DF90B /* Frameworks */, - 391933B22B0B81DB007DF90B /* Resources */, - 39CBC5422B44633800E81D24 /* Copy branding asset action extension icon */, - ); - buildRules = ( - ); - dependencies = ( - 391933CC2B0B8EA9007DF90B /* PBXTargetDependency */, - 391933CA2B0B8EA5007DF90B /* PBXTargetDependency */, - 391933C82B0B8EA2007DF90B /* PBXTargetDependency */, - ); - name = "ownCloud Action Extension"; - productName = "ownCloud Action Extension"; - productReference = 391933B42B0B81DB007DF90B /* ownCloud Action Extension.appex */; - productType = "com.apple.product-type.app-extension"; - }; 394A0AF822EEFC2C00603813 /* ownCloudAppShared */ = { isa = PBXNativeTarget; buildConfigurationList = 394A0B0222EEFC2C00603813 /* Build configuration list for PBXNativeTarget "ownCloudAppShared" */; @@ -3895,7 +3763,6 @@ DC0491D8258CB00000DEDC27 /* PBXTargetDependency */, DCDC0ACE23CD185F00DFE36D /* PBXTargetDependency */, 394A0B0C22EEFD2800603813 /* PBXTargetDependency */, - DC2A6C762AC6BE0100BFF393 /* PBXTargetDependency */, ); name = ownCloudAppShared; packageProductDependencies = ( @@ -4055,7 +3922,7 @@ 233BDE94204FEFE500C06732 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1500; + LastSwiftUpdateCheck = 1150; LastUpgradeCheck = 1420; ORGANIZATIONNAME = "ownCloud GmbH"; TargetAttributes = { @@ -4084,9 +3951,6 @@ ProvisioningStyle = Automatic; TestTargetID = 233BDE9B204FEFE500C06732; }; - 391933B32B0B81DB007DF90B = { - CreatedOnToolsVersion = 15.0; - }; 394A0AF822EEFC2C00603813 = { CreatedOnToolsVersion = 11.0; LastSwiftMigration = 1430; @@ -4184,7 +4048,6 @@ DCC0855B2293F1FD008CC05C /* ownCloudApp */, 394A0AF822EEFC2C00603813 /* ownCloudAppShared */, DCC085632293F1FD008CC05C /* ownCloudAppTests */, - 391933B32B0B81DB007DF90B /* ownCloud Action Extension */, ); }; /* End PBXProject section */ @@ -4247,13 +4110,19 @@ buildActionMask = 2147483647; files = ( 39DF77D524EA854C0066E8F0 /* LaunchScreen.storyboard in Resources */, + 3923790524EBD1A5006E86DE /* branding-splashscreen-background.png in Resources */, + 398393BE246D63B0001A212B /* branding-login-background.png in Resources */, 3968C883239C54AD00AC28AC /* ReleaseNotes.plist in Resources */, + 398393BF246D63B0001A212B /* branding-login-logo.png in Resources */, 59D4895220C83F2E00369C2E /* InfoPlist.strings in Resources */, + 392378FF24EBD1A1006E86DE /* branding-splashscreen.png in Resources */, 593A821120C7D4C5000E2A90 /* Localizable.strings in Resources */, + 391130112A20E3F200C22DD2 /* branding-sidebar-link-icon.png in Resources */, DCE684F6241BD4E800799C30 /* Branding.plist in Resources */, DC9BFBB320A19AF4007064B5 /* doc in Resources */, 233BDEA7204FEFE500C06732 /* Assets.xcassets in Resources */, DC6C68362574FD0400E46BD4 /* PLCrashReporter.LICENSE in Resources */, + 39F48A6A24D89D7E0000E3F9 /* branding-bookmark-icon.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4265,14 +4134,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 391933B22B0B81DB007DF90B /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 391933DA2B0B9863007DF90B /* InfoPlist.strings in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 394A0AF722EEFC2C00603813 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -4390,27 +4251,6 @@ shellPath = /bin/sh; shellScript = "LASTGITCOMMIT=$(git rev-parse --short HEAD)\ndefaults write \"${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH%.*}\" \"LastGitCommit\" \"${LASTGITCOMMIT}\"\n\nGITTAGS=$(git describe --tags)\ndefaults write \"${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH%.*}\" \"GitTags\" \"${GITTAGS}\"\n\nGITBRANCH=$(git branch --show-current)\ndefaults write \"${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH%.*}\" \"GitBranch\" \"${GITBRANCH}\"\n\nBUILDDATE=$(date)\ndefaults write \"${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH%.*}\" \"BuildDate\" \"${BUILDDATE}\"\n"; }; - 39CBC5422B44633800E81D24 /* Copy branding asset action extension icon */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PROJECT_DIR}/ownCloud/Resources/Theming/branding-assets/branding-action-extension-icon.png", - "${PROJECT_DIR}/ownCloud/Resources/Theming/com.owncloud.ios-app/branding-action-extension-icon.png", - ); - name = "Copy branding asset action extension icon"; - outputFileListPaths = ( - ); - outputPaths = ( - "${TARGET_BUILD_DIR}/${WRAPPER_NAME}/branding-action-extension-icon.png", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "#!/bin/bash\n\n# Determine branding assets folder to use\nASSETS_SOURCE_FOLDER=\"${PROJECT_DIR}/ownCloud/Resources/Theming/com.owncloud.ios-app/\"\n\nASSETS_FILE_COUNT=$(ls -A \"${PROJECT_DIR}/ownCloud/Resources/Theming/branding-assets/\"branding-action-extension-icon.png | wc -l)\necho \"File count in branding-assets:\" ${ASSETS_FILE_COUNT}\n\nif [ -e \"${PROJECT_DIR}/ownCloud/Resources/Theming/branding-assets/\" ]; then\n if [ $ASSETS_FILE_COUNT -ne 0 ]; then\n # Copy branding-*.png files from branding-assets\n ASSETS_SOURCE_FOLDER=\"${PROJECT_DIR}/ownCloud/Resources/Theming/branding-assets/\"\n fi\nfi\n\n\nICON_FILE_COUNT=$(ls -A ${ASSETS_SOURCE_FOLDER}branding-action-extension-icon.png | wc -l)\n\necho \"Icon count in assets source folder:\" ${ICON_FILE_COUNT}\n\nif [ $ICON_FILE_COUNT -ne 0 ]; then\n # Copy branding-action-extension-icon.png assets\n echo \"Copying branding-action-extension-icon.png files from\" ${ASSETS_SOURCE_FOLDER}\n echo cp ${ASSETS_SOURCE_FOLDER}branding-action-extension-icon.png \"${TARGET_BUILD_DIR}/${WRAPPER_NAME}/\"\n cp ${ASSETS_SOURCE_FOLDER}branding-action-extension-icon.png \"${TARGET_BUILD_DIR}/${WRAPPER_NAME}/branding-action-extension-icon.png\"\nfi\n"; - }; DC049259258CB33600DEDC27 /* Copy PocketSVG license (inactive) */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -4436,9 +4276,9 @@ files = ( ); inputFileListPaths = ( + "${PROJECT_DIR}/external/libzip/LICENSE", ); inputPaths = ( - "${PROJECT_DIR}/external/libzip/LICENSE", ); name = "Copy libzip license"; outputFileListPaths = ( @@ -4450,26 +4290,6 @@ shellPath = /bin/sh; shellScript = "echo \"${PROJECT_DIR}/external/libzip/LICENSE\" \"${TARGET_BUILD_DIR}/${WRAPPER_NAME}/libzip.LICENSE\"\ncp \"${PROJECT_DIR}/external/libzip/LICENSE\" \"${TARGET_BUILD_DIR}/${WRAPPER_NAME}/libzip.LICENSE\"\n"; }; - DC6F0B952AE9014B00BFF393 /* Copy branding assets */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PROJECT_DIR}/ownCloud/Resources/Theming/branding-assets-input.xcfilelist", - ); - inputPaths = ( - ); - name = "Copy branding assets"; - outputFileListPaths = ( - "${PROJECT_DIR}/ownCloud/Resources/Theming/branding-assets-output.xcfilelist", - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/bash; - shellScript = "#!/bin/bash\n\n# Determine branding assets folder to use\nASSETS_SOURCE_FOLDER=\"${PROJECT_DIR}/ownCloud/Resources/Theming/com.owncloud.ios-app/\"\n\nASSETS_FILE_COUNT=$(ls -A \"${PROJECT_DIR}/ownCloud/Resources/Theming/branding-assets/\"branding-*.png | wc -l)\necho \"File count in branding-assets:\" ${ASSETS_FILE_COUNT}\n\nif [ -e \"${PROJECT_DIR}/ownCloud/Resources/Theming/branding-assets/\" ]; then\n\tif [ $ASSETS_FILE_COUNT -ne 0 ]; then\n\t\t# Copy branding-*.png files from branding-assets\n\t\tASSETS_SOURCE_FOLDER=\"${PROJECT_DIR}/ownCloud/Resources/Theming/branding-assets/\"\n\tfi\nfi\n\n# Copy branding-*.png assets\necho \"Copying branding-*.png files from\" ${ASSETS_SOURCE_FOLDER}\necho cp ${ASSETS_SOURCE_FOLDER}branding-*.png \"${TARGET_BUILD_DIR}/${WRAPPER_NAME}/\"\ncp ${ASSETS_SOURCE_FOLDER}branding-*.png \"${TARGET_BUILD_DIR}/${WRAPPER_NAME}/\"\n\n# Remove assets from the assets folder that aren't used by the app from the build product\nif [ -e \"${TARGET_BUILD_DIR}/${WRAPPER_NAME}/branding-icon.png\" ]; then\n rm \"${TARGET_BUILD_DIR}/${WRAPPER_NAME}/branding-icon.png\"\nfi\n"; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -4478,7 +4298,6 @@ buildActionMask = 2147483647; files = ( DC3DEC7B22AFA1F000F3352D /* DownloadItemsHUDViewController.swift in Sources */, - DC28297E2AAF02A800BFF393 /* BookmarkSetupStepIntroViewController.swift in Sources */, 39EF06B325D6C3FC001E1E19 /* PresentationModeAction.swift in Sources */, DC680576212DF548006C3B1F /* CertificateManagementViewController.swift in Sources */, 4CB8ADE322DF6BA700F1FEBC /* PHAsset+Upload.swift in Sources */, @@ -4489,23 +4308,18 @@ 6E4F1734217749910049A71B /* ImageDisplayViewController.swift in Sources */, DC8EB271239308E5009148F9 /* LicenseOffersViewController.swift in Sources */, 025FC742247D5004009307A7 /* MediaUploadOperation.swift in Sources */, - DC59087A2AA87F6B00BFF393 /* BookmarkSetupStepFinishedViewController.swift in Sources */, 4C11EE5B22E88D4200B84869 /* InstantMediaUploadTaskExtension.swift in Sources */, DC6CF7FB219446050013B9F9 /* LogSettingsViewController.swift in Sources */, 39878B7421FB1DE800DBF693 /* UINavigationController+Extension.swift in Sources */, - DC2323DC2AA7B5D600BFF393 /* BookmarkComposer.swift in Sources */, DC82D6FA23171339001551C5 /* ScanAction.swift in Sources */, DCC3700724D466D2008B0DEB /* DiagnosticManager.swift in Sources */, 23EC775D2137FB6B0032D4E6 /* WebViewDisplayViewController.swift in Sources */, 4C464BF12187AF1500D30602 /* PDFTocTableViewCell.swift in Sources */, DCE4E43E24C19C3E0051722F /* Action+UserInterface.swift in Sources */, - DC2323DE2AA7B6BB00BFF393 /* BookmarkComposerConfiguration.swift in Sources */, DC1B270C209CF34B004715E1 /* BookmarkViewController.swift in Sources */, 025FC745247EF0F1009307A7 /* BackgroundUploadsSettingsSection.swift in Sources */, DC63208321FCAC1E007EC0A8 /* ClientActivityViewController.swift in Sources */, DC9C1AEC247C76470067895A /* MessageGroupCell.swift in Sources */, - DC2323E32AA85D0300BFF393 /* BookmarkSetupStepViewController.swift in Sources */, - DC5908772AA87ABF00BFF393 /* BookmarkSetupStepAuthenticateViewController.swift in Sources */, 4C464BF62187AF1500D30602 /* PDFTocItem.swift in Sources */, 6E3A103E219D5BBA00F90C96 /* RenameAction.swift in Sources */, DCDC208F23994DFB003CFF5B /* LicenseTransactionsViewController.swift in Sources */, @@ -4523,11 +4337,9 @@ DC0030CB2350B75000BB8570 /* ScanViewController.swift in Sources */, 4C464BF42187AF1500D30602 /* PDFSearchTableViewCell.swift in Sources */, DCD1300A23A191C000255779 /* LicenseOfferButton.swift in Sources */, - DC2323E02AA7C59400BFF393 /* BookmarkSetupViewController.swift in Sources */, DCFEF90926EFA45A001DC7A4 /* VendorServices+App.swift in Sources */, 4C9BFA2323158C3F0059CA3E /* PreviewViewController.swift in Sources */, 399698ED260A3CEE00E5AEBA /* ImportPasteboardAction.swift in Sources */, - DC59087F2AA8D25400BFF393 /* CertificateSummaryView.swift in Sources */, 4C3E17DB234DBF9A000D7BA8 /* PendingMediaUploadTaskExtension.swift in Sources */, DCC832DE242C0C3700153F8C /* DisplaySleepPreventer.swift in Sources */, 6E586CFC2199A72600F680C4 /* OpenInAction.swift in Sources */, @@ -4536,8 +4348,8 @@ 4C1561E8222321E0009C4EF3 /* PhotoSelectionViewController.swift in Sources */, 39CC8AE6228C12100020253B /* Array+Extension.swift in Sources */, DCE28F602433683700879DEC /* ClientSessionManager.swift in Sources */, - DC5908752AA87A1700BFF393 /* BookmarkSetupStepEnterUsernameViewController.swift in Sources */, 3968C881239C54AC00AC28AC /* ReleaseNotesHostViewController.swift in Sources */, + 394B0CFC29F958200005CBFE /* AccountSettingsProvider.swift in Sources */, DC6428D02081406800493A01 /* CollapsibleProgressBar.swift in Sources */, 39CD755423D8392D00193950 /* EditDocumentViewController.swift in Sources */, 025F063A24AA18C7009D8FC5 /* ImageMetadataViewController.swift in Sources */, @@ -4604,11 +4416,10 @@ DC6C0A4929239E560045FF2A /* AppRootViewController.swift in Sources */, 02DC7C9024CB354800DCB2C6 /* ProPhotoUploadSettingsSection.swift in Sources */, DCC832F6242CC5F700153F8C /* CardIssueMessagePresenter.swift in Sources */, - DC59087D2AA8B82200BFF393 /* BookmarkSetupStepPrepopulateViewController.swift in Sources */, DCD1301123A23F4E00255779 /* OCLicenseManager+AppStore.swift in Sources */, DC62514C225D254500736874 /* UploadBaseAction.swift in Sources */, 4C6B78102226B83300C5F3DB /* PhotoAlbumTableViewController.swift in Sources */, - DC2323E62AA865A700BFF393 /* BookmarkSetupStepEnterURLViewController.swift in Sources */, + DCDA83852A9CE6C300BFF393 /* InitialSetupViewController.swift in Sources */, 23EC77592137F3DD0032D4E6 /* DisplayExtension.swift in Sources */, DCDF58B323CE82E100080BEB /* LicenseInAppPurchaseFeatureView.swift in Sources */, 02D4C82A255208E60000E299 /* PDFSearchResultsView.swift in Sources */, @@ -4632,14 +4443,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 391933B02B0B81DB007DF90B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 391933C62B0B8E5A007DF90B /* ShareExtensionViewController.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 394A0AF522EEFC2C00603813 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -4726,7 +4529,6 @@ DC46F69028DCA1B8008280CA /* SavedSearchCell.swift in Sources */, DC66A9F4279EEBF900792AC8 /* ThemeView.swift in Sources */, DCDE444D2A36F56000BFF393 /* AppStateActionOpenItem.swift in Sources */, - DCEA89822AD84D6000BFF393 /* BrandView.swift in Sources */, DC60F2AA29802D5800905EC8 /* NavigationContentItem.swift in Sources */, DC0A356F24C0E42700FB58FC /* StaticTableViewController.swift in Sources */, DC62F569292504510095BB5D /* AccountConnectionPool.swift in Sources */, @@ -4811,7 +4613,6 @@ DCB1B89F29C7378200BFF393 /* ThemeCSS.swift in Sources */, DC0A357C24C0E43C00FB58FC /* ThemeCollection.swift in Sources */, DC28F828294BB5ED00AC4013 /* SortedItemDataSource.swift in Sources */, - DCA05A602AE6603E00BFF393 /* ClientLocationPopupButton.swift in Sources */, DC298C992934D3F8009FA87F /* AlertViewController.swift in Sources */, DC8E99DC297E79E900594697 /* BrowserNavigationHistory.swift in Sources */, DCBAEAE829A568D500BFF393 /* TitleSupplementaryCell.swift in Sources */, @@ -4853,7 +4654,6 @@ 3912208223436EB80026C290 /* SortMethod.swift in Sources */, DCE4E43F24C19D370051722F /* UIAlertController+OCIssue.swift in Sources */, DC298CA929362523009FA87F /* ClientLocationPicker.swift in Sources */, - DCA05A622AE664F200BFF393 /* OCAction+UIAction.swift in Sources */, DC0A359524C0E5F900FB58FC /* UIImage+Extension.swift in Sources */, DC89EA6B29959BD200BFF393 /* AppStateActionRestoreNavigationBookmark.swift in Sources */, DC66A9F8279F467200792AC8 /* UIKeyCommand+Extension.swift in Sources */, @@ -5015,26 +4815,6 @@ target = 233BDE9B204FEFE500C06732 /* ownCloud */; targetProxy = 233BDEB1204FEFE500C06732 /* PBXContainerItemProxy */; }; - 391933C12B0B81DB007DF90B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 391933B32B0B81DB007DF90B /* ownCloud Action Extension */; - targetProxy = 391933C02B0B81DB007DF90B /* PBXContainerItemProxy */; - }; - 391933C82B0B8EA2007DF90B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DCC0855B2293F1FD008CC05C /* ownCloudApp */; - targetProxy = 391933C72B0B8EA2007DF90B /* PBXContainerItemProxy */; - }; - 391933CA2B0B8EA5007DF90B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 394A0AF822EEFC2C00603813 /* ownCloudAppShared */; - targetProxy = 391933C92B0B8EA5007DF90B /* PBXContainerItemProxy */; - }; - 391933CC2B0B8EA9007DF90B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = ownCloudSDK; - targetProxy = 391933CB2B0B8EA9007DF90B /* PBXContainerItemProxy */; - }; 394A0AFF22EEFC2C00603813 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 394A0AF822EEFC2C00603813 /* ownCloudAppShared */; @@ -5109,11 +4889,6 @@ name = ownCloudSDK; targetProxy = DC27A19220CAA0C6008ACB6C /* PBXContainerItemProxy */; }; - DC2A6C762AC6BE0100BFF393 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = ownCloudUI; - targetProxy = DC2A6C752AC6BE0100BFF393 /* PBXContainerItemProxy */; - }; DC3BE0CF2077BC52002A0AC0 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = ownCloudSDK; @@ -5235,15 +5010,6 @@ name = Intents.intentdefinition; sourceTree = ""; }; - 391933DC2B0B9863007DF90B /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 391933DB2B0B9863007DF90B /* en */, - 391933DD2B0B9871007DF90B /* de */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; 39534BC924EA903200AD7907 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( @@ -5371,8 +5137,8 @@ APP_BUILD_FLAGS = "$(inherited)"; APP_BUILD_FLAGS_SWIFT = "$(APP_BUILD_FLAGS)"; APP_PRODUCT_NAME = ownCloud; - APP_SHORT_VERSION = 12.1; - APP_VERSION = 288; + APP_SHORT_VERSION = 12.0.3; + APP_VERSION = 271; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -5441,8 +5207,8 @@ APP_BUILD_FLAGS = "$(inherited)"; APP_BUILD_FLAGS_SWIFT = "$(APP_BUILD_FLAGS)"; APP_PRODUCT_NAME = ownCloud; - APP_SHORT_VERSION = 12.1; - APP_VERSION = 288; + APP_SHORT_VERSION = 12.0.3; + APP_VERSION = 271; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -5602,86 +5368,6 @@ }; name = Release; }; - 391933C42B0B81DC007DF90B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CODE_SIGN_ENTITLEMENTS = "ownCloud Action Extension/ownCloud Action Extension.entitlements"; - CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = "$(APP_VERSION)"; - DEVELOPMENT_TEAM = 4AP2STM4H5; - ENABLE_USER_SCRIPT_SANDBOXING = YES; - GCC_C_LANGUAGE_STANDARD = gnu17; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = "ownCloud Action Extension/Info.plist"; - INFOPLIST_KEY_CFBundleDisplayName = "ownCloud Action Extension"; - INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 ownCloud GmbH. All rights reserved."; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MARKETING_VERSION = "${APP_SHORT_VERSION}"; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "com.owncloud.ios-app.ownCloud-Action-Extension"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 391933C52B0B81DC007DF90B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CODE_SIGN_ENTITLEMENTS = "ownCloud Action Extension/ownCloud Action Extension.entitlements"; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = "$(APP_VERSION)"; - DEVELOPMENT_TEAM = 4AP2STM4H5; - ENABLE_USER_SCRIPT_SANDBOXING = YES; - GCC_C_LANGUAGE_STANDARD = gnu17; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = "ownCloud Action Extension/Info.plist"; - INFOPLIST_KEY_CFBundleDisplayName = "ownCloud Action Extension"; - INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 ownCloud GmbH. All rights reserved."; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MARKETING_VERSION = "${APP_SHORT_VERSION}"; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "com.owncloud.ios-app.ownCloud-Action-Extension"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; 394A0B0322EEFC2C00603813 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -6144,15 +5830,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 391933C32B0B81DC007DF90B /* Build configuration list for PBXNativeTarget "ownCloud Action Extension" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 391933C42B0B81DC007DF90B /* Debug */, - 391933C52B0B81DC007DF90B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 394A0B0222EEFC2C00603813 /* Build configuration list for PBXNativeTarget "ownCloudAppShared" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/ownCloud.xcodeproj/xcshareddata/xcschemes/ownCloud File Provider.xcscheme b/ownCloud.xcodeproj/xcshareddata/xcschemes/ownCloud File Provider.xcscheme index c0eaa4db2..69ff7ee8c 100644 --- a/ownCloud.xcodeproj/xcshareddata/xcschemes/ownCloud File Provider.xcscheme +++ b/ownCloud.xcodeproj/xcshareddata/xcschemes/ownCloud File Provider.xcscheme @@ -109,7 +109,7 @@ + RemotePath = "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/Applications/Files.app"> @@ -142,7 +142,7 @@ isEnabled = "NO"> @@ -151,29 +151,7 @@ value = "[share-extension,open-with,file-provider]" isEnabled = "NO"> - - - - - - - - - - + isEnabled = "NO"> + + - - - - - - - - - - - - - - - - UICollectionViewDropProposal? { - if session.localDragSession == nil { - return nil - } - - return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath) - } - - public func performDropOperation(of items: [UIDragItem], with context: ClientContext?, handlingCompletion: @escaping (Bool) -> Void) { - handlingCompletion(false) - } -} diff --git a/ownCloud/App Controllers/AppRootViewController.swift b/ownCloud/App Controllers/AppRootViewController.swift index 2c37e2468..fbce0e7c1 100644 --- a/ownCloud/App Controllers/AppRootViewController.swift +++ b/ownCloud/App Controllers/AppRootViewController.swift @@ -104,7 +104,7 @@ open class AppRootViewController: EmbeddingViewController, BrowserNavigationView // Build sidebar sidebarViewController = ClientSidebarViewController(context: rootContext!, controllerConfiguration: controllerConfiguration) - sidebarViewController?.addToolbarItems(addAccount: Branding.shared.canAddAccount) + sidebarViewController?.addToolbarItems() leftNavigationController = ThemeNavigationController(rootViewController: sidebarViewController!) leftNavigationController?.cssSelectors = [ .sidebar ] @@ -121,9 +121,7 @@ open class AppRootViewController: EmbeddingViewController, BrowserNavigationView noBookmarkCondition = DataSourceCondition(.empty, with: OCBookmarkManager.shared.bookmarksDatasource, initial: true, action: { [weak self] condition in if condition.fulfilled == true { // No account available - let configuration = BookmarkComposerConfiguration.newBookmarkConfiguration - configuration.hasIntro = true - self?.contentViewController = BookmarkSetupViewController(configuration: configuration) + self?.contentViewController = InitialSetupViewController() } else { // Account already available self?.contentViewController = self?.contentBrowserController @@ -162,23 +160,6 @@ open class AppRootViewController: EmbeddingViewController, BrowserNavigationView ClientSessionManager.shared.remove(delegate: self) } - // MARK: - Interface orientations - open override var supportedInterfaceOrientations: UIInterfaceOrientationMask { - if let contentViewController { - return contentViewController.supportedInterfaceOrientations - } - - return super.supportedInterfaceOrientations - } - - open override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { - if let contentViewController { - return contentViewController.preferredInterfaceOrientationForPresentation - } - - return super.preferredInterfaceOrientationForPresentation - } - // MARK: - Status Bar style open override var childForStatusBarStyle: UIViewController? { return contentViewController @@ -187,9 +168,6 @@ open class AppRootViewController: EmbeddingViewController, BrowserNavigationView open override var contentViewController: UIViewController? { didSet { setNeedsStatusBarAppearanceUpdate() - if #available(iOS 16, *) { - setNeedsUpdateOfSupportedInterfaceOrientations() - } } } @@ -406,9 +384,7 @@ extension ClientSidebarViewController { // MARK: - Open settings @IBAction func settings() { - let navigationViewController = ThemeNavigationController(rootViewController: SettingsViewController()) - navigationViewController.modalPresentationStyle = .fullScreen - present(navigationViewController, animated: true) + self.present(ThemeNavigationController(rootViewController: SettingsViewController()), animated: true) } // MARK: - Add account diff --git a/ownCloud/App Controllers/InitialSetupViewController.swift b/ownCloud/App Controllers/InitialSetupViewController.swift new file mode 100644 index 000000000..66b6f2533 --- /dev/null +++ b/ownCloud/App Controllers/InitialSetupViewController.swift @@ -0,0 +1,65 @@ +// +// InitialSetupViewController.swift +// ownCloud +// +// Created by Felix Schwarz on 28.08.23. +// Copyright © 2023 ownCloud GmbH. All rights reserved. +// + +/* + * Copyright (C) 2023, ownCloud GmbH. + * + * This code is covered by the GNU Public License Version 3. + * + * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ + * You should have received a copy of this license along with this program. If not, see . + * + */ + +import UIKit +import ownCloudApp +import ownCloudAppShared + +class InitialSetupViewController: UIViewController { + override var preferredStatusBarStyle : UIStatusBarStyle { + return Theme.shared.activeCollection.css.getStatusBarStyle(for: self) ?? .default + } + + override func loadView() { + cssSelectors = [.modal, .welcome] + + var addAccountTitle = "Add account".localized + if !VendorServices.shared.canAddAccount { + addAccountTitle = "Login".localized + } + + let messageView = ComposedMessageView.infoBox(additionalElements: [ + .image(AccountSettingsProvider.shared.logo, size: CGSize(width: 128, height: 128), cssSelectors: [.icon]), + .title(String(format: "Welcome to %@".localized, VendorServices.shared.appName), alignment: .centered, cssSelectors: [.title], insets: NSDirectionalEdgeInsets(top: 25, leading: 0, bottom: 25, trailing: 0)), + .button(addAccountTitle, action: UIAction(handler: { [weak self] action in + if let self = self { + BookmarkViewController.showBookmarkUI(on: self, attemptLoginOnSuccess: true) + } + }), image: UIImage(systemName: "plus.circle"), cssSelectors: [.welcome]), + .button("Settings".localized ,action: UIAction(handler: { [weak self] action in + if let self = self { + self.present(ThemeNavigationController(rootViewController: SettingsViewController()), animated: true) + } + }), image: UIImage(systemName: "gearshape"), cssSelectors: [.welcome]) + ]) + messageView.elementInsets = NSDirectionalEdgeInsets(top: 25, leading: 50, bottom: 50, trailing: 50) + + let rootView = ThemeCSSView(withSelectors: []) + + if let image = Branding.shared.brandedImageNamed(.loginBackground) { + messageView.isOpaque = false + let backgroundImageView = UIImageView(image: image) + backgroundImageView.contentMode = .scaleAspectFill + rootView.embed(toFillWith: backgroundImageView) + } + + rootView.embed(centered: messageView, minimumInsets: NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20)) + + view = rootView + } +} diff --git a/ownCloud/Bookmarks/AccountSettingsProvider.swift b/ownCloud/Bookmarks/AccountSettingsProvider.swift new file mode 100644 index 000000000..03f30a99c --- /dev/null +++ b/ownCloud/Bookmarks/AccountSettingsProvider.swift @@ -0,0 +1,129 @@ +// +// AccountSettingsProvider.swift +// ownCloud +// +// Created by Matthias Hühne on 26.04.23. +// Copyright © 2023 ownCloud GmbH. All rights reserved. +// + +/* + * Copyright (C) 2018, ownCloud GmbH. + * + * This code is covered by the GNU Public License Version 3. + * + * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ + * You should have received a copy of this license along with this program. If not, see . + * + */ + +import UIKit +import ownCloudSDK +import ownCloudApp +import ownCloudAppShared + +class AccountSettingsProvider: NSObject { + + static public var shared : AccountSettingsProvider = { + return AccountSettingsProvider() + }() + + public var defaultBookmarkName: String? { + if let name = Branding.shared.profileBookmarkName { + return name + } else if let name = self.classSetting(forOCClassSettingsKey: .bookmarkDefaultName) as? String { + return name + } + + return nil + } + + public var defaultURL: URL? { + if let url = Branding.shared.profileURL { + return url + } else if let urlString = self.classSetting(forOCClassSettingsKey: .bookmarkDefaultURL) as? String { + return URL(string: urlString) + } + + return nil + } + + public var URLEditable: Bool { + if let url = Branding.shared.profileAllowUrlConfiguration { + return url + } else if let value = self.classSetting(forOCClassSettingsKey: .bookmarkURLEditable) as? Bool { + return value + } + + return true + } + + public var profileOpenHelpMessage: String? { + return Branding.shared.profileOpenHelpMessage + } + + public var profileHelpButtonLabel: String? { + return Branding.shared.profileHelpButtonLabel + } + + public var profileHelpURL: URL? { + return Branding.shared.profileHelpURL + } + + var logo: UIImage { + if Branding.shared.isBranded, let image = Branding.shared.brandedImageNamed(.loginLogo) { + return image + } + + return UIImage(named: "branding-bookmark-icon")! + } +} + +// MARK: - OCClassSettings support +extension OCClassSettingsIdentifier { + static let accountSettings = OCClassSettingsIdentifier("account-settings") +} + +extension OCClassSettingsKey { + static let bookmarkDefaultName = OCClassSettingsKey("default-name") + static let bookmarkDefaultURL = OCClassSettingsKey("default-url") + static let bookmarkURLEditable = OCClassSettingsKey("url-editable") +} + +extension AccountSettingsProvider : OCClassSettingsSupport { + public static let classSettingsIdentifier : OCClassSettingsIdentifier = .accountSettings + + public static func defaultSettings(forIdentifier identifier: OCClassSettingsIdentifier) -> [OCClassSettingsKey : Any]? { + if identifier == .bookmark { + return [ + .bookmarkURLEditable : true + ] + } + + return nil + } + + public static func classSettingsMetadata() -> [OCClassSettingsKey : [OCClassSettingsMetadataKey : Any]]? { + return [ + .bookmarkDefaultName : [ + .type : OCClassSettingsMetadataType.string, + .description : "The default name for the creation of new bookmarks.", + .category : "Bookmarks", + .status : OCClassSettingsKeyStatus.supported + ], + + .bookmarkDefaultURL : [ + .type : OCClassSettingsMetadataType.string, + .description : "The default URL for the creation of new bookmarks.", + .category : "Bookmarks", + .status : OCClassSettingsKeyStatus.supported + ], + + .bookmarkURLEditable : [ + .type : OCClassSettingsMetadataType.boolean, + .description : "Controls whether the server URL in the text field during the creation of new bookmarks can be changed.", + .category : "Bookmarks", + .status : OCClassSettingsKeyStatus.supported + ] + ] + } +} diff --git a/ownCloud/Bookmarks/BookmarkViewController.swift b/ownCloud/Bookmarks/BookmarkViewController.swift index e907dff31..216fd41be 100644 --- a/ownCloud/Bookmarks/BookmarkViewController.swift +++ b/ownCloud/Bookmarks/BookmarkViewController.swift @@ -273,7 +273,7 @@ class BookmarkViewController: StaticTableViewController { self.navigationItem.rightBarButtonItem = continueBarButtonItem // Support for bookmark default name - if let defaultNameString = Branding.shared.profileBookmarkName { + if let defaultNameString = AccountSettingsProvider.shared.defaultBookmarkName { self.bookmark?.name = defaultNameString if bookmark != nil { @@ -282,7 +282,7 @@ class BookmarkViewController: StaticTableViewController { } // Support for bookmark default URL - if let defaultURL = Branding.shared.profileURL { + if let defaultURL = AccountSettingsProvider.shared.defaultURL { self.bookmark?.url = defaultURL if bookmark != nil { @@ -290,13 +290,13 @@ class BookmarkViewController: StaticTableViewController { } } - if let url = Branding.shared.profileHelpURL, let title = Branding.shared.profileHelpButtonLabel { + if let url = AccountSettingsProvider.shared.profileHelpURL, let title = AccountSettingsProvider.shared.profileHelpButtonLabel { let imageView = UIImageView(image: UIImage(systemName: "questionmark.circle")!) helpButtonRow = StaticTableViewRow(rowWithAction: { staticRow, sender in UIApplication.shared.open(url) }, title: title, alignment: .center, accessoryView: imageView) - helpSection = StaticTableViewSection(headerTitle: "Help".localized, footerTitle: Branding.shared.profileOpenHelpMessage, identifier: "section-help", rows: [ helpButtonRow! ]) + helpSection = StaticTableViewSection(headerTitle: "Help".localized, footerTitle: AccountSettingsProvider.shared.profileOpenHelpMessage, identifier: "section-help", rows: [ helpButtonRow! ]) } case .edit: @@ -319,7 +319,7 @@ class BookmarkViewController: StaticTableViewController { } // Support for bookmark URL editable - if Branding.shared.profileAllowUrlConfiguration == false { + if AccountSettingsProvider.shared.URLEditable == false { self.urlRow?.enabled = false let vectorImageView = VectorImageView(frame: CGRect(x: 0, y: 0, width: 20, height: 20)) @@ -340,7 +340,7 @@ class BookmarkViewController: StaticTableViewController { } let logoAndAppNameView = ComposedMessageView.infoBox(additionalElements: [ - .image(Branding.shared.brandedImageNamed(.brandLogo) ?? UIImage(systemName: "globe")!, size: CGSize(width: 64, height: 64), cssSelectors: [.icon]), + .image(AccountSettingsProvider.shared.logo, size: CGSize(width: 64, height: 64), cssSelectors: [.icon]), .title(VendorServices.shared.appName, alignment: .centered, cssSelectors: [.title]) ]) @@ -348,7 +348,7 @@ class BookmarkViewController: StaticTableViewController { logoAndAppNameView.backgroundInsets = NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 0, trailing: 20) logoAndAppNameView.elementInsets = NSDirectionalEdgeInsets(top: 30, leading: 20, bottom: 10, trailing: 20) - (logoAndAppNameView.backgroundView as? RoundCornerBackgroundView)?.fillImage = Branding.shared.brandedImageNamed(.brandBackground) ?? Branding.shared.brandedImageNamed(.legacyBrandBackground) + (logoAndAppNameView.backgroundView as? RoundCornerBackgroundView)?.fillImage = Branding.shared.brandedImageNamed(.loginBackground) self.tableView.tableHeaderView = logoAndAppNameView self.tableView.layoutTableHeaderView() @@ -1108,55 +1108,39 @@ class BookmarkViewController: StaticTableViewController { // MARK: - Convenience for presentation extension BookmarkViewController { static func showBookmarkUI(on hostViewController: UIViewController, edit bookmark: OCBookmark? = nil, performContinue: Bool = false, attemptLoginOnSuccess: Bool = false, autosolveErrorOnSuccess: NSError? = nil, removeAuthDataFromCopy: Bool = true) { - if bookmark != nil { - var editBookmark = bookmark + var editBookmark = bookmark - if let bookmark { - // Retrieve latest version of bookmark from OCBookmarkManager - if let latestStoredBookmarkVersion = OCBookmarkManager.shared.bookmark(forUUIDString: bookmark.uuid.uuidString) { - editBookmark = latestStoredBookmarkVersion - } + if let bookmark { + // Retrieve latest version of bookmark from OCBookmarkManager + if let latestStoredBookmarkVersion = OCBookmarkManager.shared.bookmark(forUUIDString: bookmark.uuid.uuidString) { + editBookmark = latestStoredBookmarkVersion } + } - let bookmarkViewController : BookmarkViewController = BookmarkViewController(editBookmark, removeAuthDataFromCopy: removeAuthDataFromCopy) - bookmarkViewController.userActionCompletionHandler = { (bookmark, success) in - if success, let bookmark = bookmark { - if let error = autosolveErrorOnSuccess as Error? { - OCMessageQueue.global.resolveIssues(forError: error, forBookmarkUUID: bookmark.uuid) - } + let bookmarkViewController : BookmarkViewController = BookmarkViewController(editBookmark, removeAuthDataFromCopy: removeAuthDataFromCopy) + bookmarkViewController.userActionCompletionHandler = { (bookmark, success) in + if success, let bookmark = bookmark { + if let error = autosolveErrorOnSuccess as Error? { + OCMessageQueue.global.resolveIssues(forError: error, forBookmarkUUID: bookmark.uuid) + } - if attemptLoginOnSuccess { - AccountConnectionPool.shared.connection(for: bookmark)?.connect() - } + if attemptLoginOnSuccess { + AccountConnectionPool.shared.connection(for: bookmark)?.connect() } } + } - let navigationController : ThemeNavigationController = ThemeNavigationController(rootViewController: bookmarkViewController) - navigationController.isModalInPresentation = true + let navigationController : ThemeNavigationController = ThemeNavigationController(rootViewController: bookmarkViewController) + navigationController.isModalInPresentation = true - hostViewController.present(navigationController, animated: true, completion: { - OnMainThread { - if performContinue { - bookmarkViewController.showedOAuthInfoHeader = true // needed for HTTP+OAuth2 connections to really continue on .handleContinue() call - bookmarkViewController.handleContinue() - } - } - }) - } else { - let setupViewController = BookmarkSetupViewController(configuration: .newBookmarkConfiguration, cancelHandler: { - hostViewController.dismiss(animated: true) - }, doneHandler: { bookmark in - hostViewController.dismiss(animated: true) - if attemptLoginOnSuccess, let bookmark { - AccountConnectionPool.shared.connection(for: bookmark)?.connect() + hostViewController.present(navigationController, animated: true, completion: { + OnMainThread { + if performContinue { + bookmarkViewController.showedOAuthInfoHeader = true // needed for HTTP+OAuth2 connections to really continue on .handleContinue() call + bookmarkViewController.handleContinue() } - }) - setupViewController.navigationItem.titleLabelText = "Add account".localized - - let navigationViewController = ThemeNavigationController(rootViewController: setupViewController) - navigationViewController.modalPresentationStyle = .fullScreen - hostViewController.present(navigationViewController, animated: true, completion: nil) - } + } + }) } } diff --git a/ownCloud/Bookmarks/Composer/BookmarkComposer.swift b/ownCloud/Bookmarks/Composer/BookmarkComposer.swift deleted file mode 100644 index 2b158de53..000000000 --- a/ownCloud/Bookmarks/Composer/BookmarkComposer.swift +++ /dev/null @@ -1,533 +0,0 @@ -// -// BookmarkComposer.swift -// ownCloud -// -// Created by Felix Schwarz on 05.09.23. -// Copyright © 2023 ownCloud GmbH. All rights reserved. -// - -/* - * Copyright (C) 2023, ownCloud GmbH. - * - * This code is covered by the GNU Public License Version 3. - * - * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ - * You should have received a copy of this license along with this program. If not, see . - * - */ - -import UIKit -import ownCloudSDK -import ownCloudAppShared - -class BookmarkComposer: NSObject { - // MARK: - Steps - enum Step: Equatable, Hashable { - case intro - case enterUsername - case serverURL(urlString: String?) - case authenticate(withCredentials: Bool, username: String?, password: String?) - case chooseServer(fromInstances: [OCServerInstance]) - case infinitePropfind - case completed - } - - struct UndoAction { - var action: (_ composer: BookmarkComposer) -> Void - var byUser: Bool - } - - var configuration: BookmarkComposerConfiguration - weak var delegate: BookmarkComposerDelegate? - - init(configuration: BookmarkComposerConfiguration, removeAuthDataFromCopy: Bool = false, delegate: BookmarkComposerDelegate?) { - self.configuration = configuration - self.delegate = delegate - - self.bookmark = configuration.bookmark?.copy() as? OCBookmark ?? OCBookmark() - - bookmark.authenticationDataStorage = .memory // Disconnect bookmark from keychain - - if bookmark.isTokenBased == true, removeAuthDataFromCopy { - bookmark.authenticationData = nil - } - - if bookmark.scanForAuthenticationMethodsRequired == true { - bookmark.authenticationMethodIdentifier = nil - bookmark.authenticationData = nil - } - - if let name = configuration.name { - bookmark.name = name - } - } - - // MARK: - Internal storage - var bookmark: OCBookmark - - // MARK: - Connection instantiation - private var _cookieStorage : OCHTTPCookieStorage? - var cookieStorage : OCHTTPCookieStorage? { - if _cookieStorage == nil, let cookieSupportEnabled = OCCore.classSetting(forOCClassSettingsKey: .coreCookieSupportEnabled) as? Bool, cookieSupportEnabled == true { - _cookieStorage = OCHTTPCookieStorage() - Log.debug("Created cookie storage \(String(describing: _cookieStorage))") - } - - return _cookieStorage - } - - func instantiateConnection(for bmark: OCBookmark) -> OCConnection { - let connection = OCConnection(bookmark: bmark) - - connection.hostSimulator = OCHostSimulatorManager.shared.hostSimulator(forLocation: .accountSetup, for: self) - connection.cookieStorage = self.cookieStorage // Share cookie storage across all relevant connections - - return connection - } - - // MARK: - Setup steps - private var didShowIntro: Bool = false - private var username: String? - private var password: String? - private var instances: [OCServerInstance]? - private var supportsInfinitePropfind: Bool? - private var performedPrepopulation: Bool = false - private var isDriveBased: Bool? - private var generationOptions: [OCAuthenticationMethodKey : Any]? - - // MARK: .intro - func doneIntro() { - didShowIntro = true - - self.pushUndoAction(undoAction: UndoAction(action: { composer in - composer.didShowIntro = false - }, byUser: true)) - - self.updateState() - } - - // MARK: .enterUsername - func enterUsername(_ username: String, byUser: Bool = true, completion: @escaping Completion) { - bookmark.serverLocationUserName = username - self.username = username - - self.pushUndoAction(undoAction: UndoAction(action: { composer in - composer.bookmark.serverLocationUserName = nil - composer.username = nil - }, byUser: byUser)) - - completion(nil, nil, nil) - self.updateState() - } - - // MARK: .enterURL - typealias Completion = (_ error: Error?, _ issue: OCIssue?, _ issueCompletionHandler: IssuesCardViewController.CompletionHandler?) -> Void - - func enterURL(_ urlString: String, byUser: Bool = true, completion: @escaping Completion) { - var username : NSString?, password: NSString? - var protocolWasPrepended : ObjCBool = false - - // Normalize URL - guard let serverURL = NSURL(username: &username, password: &password, afterNormalizingURLString: urlString, protocolWasPrepended: &protocolWasPrepended) as URL? else { - return - } - - // Check for zero-length host name - if (serverURL.host == nil) || ((serverURL.host != nil) && (serverURL.host?.count==0)) { - // Missing hostname - completion(nil, OCIssue(localizedTitle: "Missing hostname".localized, localizedDescription: "The entered URL does not include a hostname.".localized, level: .error), nil) - return - } - - // Save username and password for possible later use if they were part of the URL - if username != nil { - self.username = username as? String - } - - if password != nil { - self.password = password as? String - } - - // Probe URL - bookmark.url = serverURL - - let connection = instantiateConnection(for: bookmark) - - hudMessage = "Contacting server…".localized - - connection.prepareForSetup(options: nil) { [weak self] (issue, _, _, preferredAuthenticationMethods, generationOptions) in - self?.hudMessage = nil - - let continueToNextStep : (_ allowRetry: Bool) -> Void = { [weak self] (allowRetry) in - if let preferredAuthenticationMethods, preferredAuthenticationMethods.count > 0 { - self?.bookmark.authenticationMethodIdentifier = preferredAuthenticationMethods.first - self?.pushUndoAction(undoAction: UndoAction(action: { composer in - composer.username = nil - composer.password = nil - - composer.bookmark.url = nil - composer.bookmark.authenticationMethodIdentifier = nil - composer.bookmark.certificateStore?.removeAllCertificates() - - composer.generationOptions = nil - }, byUser: byUser)) - self?.updateState() - } else if allowRetry { - self?.enterURL(urlString, completion: completion) - } - } - - self?.generationOptions = generationOptions - - if let issue { - // Parse issue for display - if issue.prepareForDisplay().isAtLeast(level: .warning) { - // Present issues if the level is >= warning - completion(nil, issue, { [weak self, weak issue] (response) in - switch response { - case .cancel: - issue?.reject() - self?.bookmark.url = nil - - case .approve: - issue?.approve() - continueToNextStep(true) - - case .dismiss: - self?.bookmark.url = nil - } - }) - } else { - // Do not present issues - issue.approve() - continueToNextStep(true) - } - } else { - continueToNextStep(false) - } - } - } - - // MARK: .authenticate - func authenticate(username: String? = nil, password: String? = nil, presentingViewController: UIViewController?, completion: @escaping Completion) { - var options : [OCAuthenticationMethodKey : Any] = generationOptions ?? [:] - - let connection = instantiateConnection(for: bookmark) - - if let authMethodIdentifier = bookmark.authenticationMethodIdentifier { - if OCAuthenticationMethod.isAuthenticationMethodPassphraseBased(authMethodIdentifier as OCAuthenticationMethodIdentifier) { - options[.usernameKey] = username ?? "" - options[.passphraseKey] = password ?? "" - } - } - - options[.presentingViewControllerKey] = presentingViewController - options[.requiredUsernameKey] = bookmark.userName - - // Pre-fill already provided username in case of a server locator being used - if options[.requiredUsernameKey] == nil, let serverLocationUserName = bookmark.serverLocationUserName { - options[.usernameKey] = serverLocationUserName - } - - guard let bookmarkAuthenticationMethodIdentifier = bookmark.authenticationMethodIdentifier else { return } - - hudMessage = "Authenticating…".localized - - connection.generateAuthenticationData(withMethod: bookmarkAuthenticationMethodIdentifier, options: options) { (error, authMethodIdentifier, authMethodData) in - if error == nil, let authMethodIdentifier, let authMethodData { - self.bookmark.authenticationMethodIdentifier = authMethodIdentifier - self.bookmark.authenticationData = authMethodData - self.bookmark.scanForAuthenticationMethodsRequired = false - - self.hudMessage = "Fetching user information…".localized - - // Retrieve available instances for this account to chose from - connection.retrieveAvailableInstances(options: options, authenticationMethodIdentifier: authMethodIdentifier, authenticationData: authMethodData, completionHandler: { error, instances in - if error == nil, let instances, instances.count > 0 { - self.instances = instances - } - - if self.bookmark.isComplete { - self.bookmark.authenticationDataStorage = .keychain // Commit auth changes to keychain - } - - let continueCompletion : Completion = { (error, issue, issueCompletionHandler) in - self.hudMessage = nil - - completion(error,issue,issueCompletionHandler) - - if error == nil, issue == nil { - self.clearUndoStack() - self.updateState() - } - } - - if self.instances == nil { - // bookmark URL final -> retrieve server configuration right away - self.retrieveServerConfiguration(completion: continueCompletion) - } else { - // server instance needs to be chosen - if self.instances?.count == 1, let onlyInstance = self.instances?.first { - // If only one instance is returned, choose it right away - self.chooseServer(instance: onlyInstance, byUser: false, completion: continueCompletion) - } else { - continueCompletion(nil, nil, nil) - } - } - - Log.debug("\(connection) returned error=\(String(describing: error)) instances=\(String(describing: instances))") // Debug message also has the task to capture connection and avoid it being prematurely dropped - }) - } else { - self.hudMessage = nil - - var issue : OCIssue? - let nsError = error as NSError? - - if let embeddedIssue = nsError?.embeddedIssue() { - issue = embeddedIssue - } else if let error = error { - issue = OCIssue(forError: error, level: .error, issueHandler: nil) - } - - if nsError?.isOCError(withCode: .authorizationFailed) == true { - // Shake - completion(error, nil, nil) - } else if nsError?.isOCError(withCode: .authorizationCancelled) == true { - // User cancelled authorization, no reaction needed - } else if let issue { - completion(nil, issue, { [weak self, weak issue] (response) in - switch response { - case .cancel: - issue?.reject() - - case .approve: - issue?.approve() - self?.updateState() - - case .dismiss: break - } - }) - } - } - } - } - - func retrieveServerConfiguration(completion: @escaping Completion) { - let connection = instantiateConnection(for: bookmark) - - self.hudMessage = "Fetching server information…".localized - - connection.connect { [weak self] (error, issue) in - guard let strongSelf = self else { return } - - // Handle errors - guard error == nil, issue == nil else { - self?.hudMessage = nil - - completion(error, issue, { [weak self, weak issue] (response) in - switch response { - case .cancel: - issue?.reject() - - case .approve: - issue?.approve() - self?.updateState() - - case .dismiss: break - } - }) - return - } - - // Inspect server configuration - strongSelf.bookmark.userDisplayName = connection.loggedInUser?.displayName - - strongSelf.isDriveBased = connection.capabilities?.spacesEnabled?.boolValue ?? false - strongSelf.supportsInfinitePropfind = connection.capabilities?.davPropfindSupportsDepthInfinity?.boolValue ?? false - - connection.disconnect(completionHandler: { - self?.hudMessage = nil - completion(nil, nil, nil) - }) - } - } - - // MARK: .chooseServer - func chooseServer(instance: OCServerInstance, byUser: Bool = true, completion: @escaping Completion) { - // Apply instance - self.bookmark.apply(instance) - - // Drop all other choices - self.instances = nil - - // Retrieve server configuration after instance changes have been applied - self.retrieveServerConfiguration(completion: completion) - } - - // MARK: .prepopulate - func prepopulate(completion: @escaping Completion) -> Progress? { - var prepopulationMethod : BookmarkPrepopulationMethod? - - // Determine prepopulation method - if prepopulationMethod == nil, let prepopulationMethodClassSetting = BookmarkViewController.classSetting(forOCClassSettingsKey: .prepopulation) as? String { - prepopulationMethod = BookmarkPrepopulationMethod(rawValue: prepopulationMethodClassSetting) - } - - if prepopulationMethod == nil, supportsInfinitePropfind == true { - prepopulationMethod = .streaming - } - - if prepopulationMethod == nil { - prepopulationMethod = .doNot - } - - if isDriveBased == true { - // Drive-based accounts do not support prepopulation yet - prepopulationMethod = .doNot - } - - performedPrepopulation = true - - // Prepopulation y/n? - if let prepopulationMethod, prepopulationMethod != .doNot { - // Perform prepopulation - var prepopulateProgress : Progress? - - // Perform prepopulation method - switch prepopulationMethod { - case .streaming: - prepopulateProgress = bookmark.prepopulate(streamCompletionHandler: { [weak self] _ in - completion(nil, nil, nil) - self?.updateState() - }) - - case .split: - prepopulateProgress = bookmark.prepopulate(completionHandler: { [weak self] _ in - completion(nil, nil, nil) - self?.updateState() - }) - - default: - completion(nil, nil, nil) - self.updateState() - } - - // Present progress - return prepopulateProgress - } - - // No prepopulation - completion(nil, nil, nil) - self.updateState() - - return nil - } - - // MARK: .finished - func setName(_ bookmarkName: String?) { - self.bookmark.name = bookmarkName - } - - // MARK: - Undo - var undoStack: [UndoAction] = [] - - var canUndoLastStep: Bool { - return !undoStack.isEmpty - } - - func clearUndoStack() { - undoStack.removeAll() - } - - func pushUndoAction(undoAction: UndoAction) { - undoStack.append(undoAction) - } - - func undoLastStep() { - if undoStack.count > 0 { - while undoStack.last != nil { - let undoAction = undoStack.removeLast() - undoAction.action(self) - - if undoAction.byUser { - break - } - } - - updateState() - } - } - - // MARK: - State - var currentStep: Step? { - didSet { - if oldValue != currentStep, let currentStep { - delegate?.present(composer: self, step: currentStep) - } - } - } - var hudMessage: String? { - didSet { - if hudMessage != oldValue { - delegate?.present(composer: self, hudMessage: hudMessage) - } - } - } - - func updateState() { - if configuration.hasIntro, !didShowIntro { - currentStep = .intro - } else if OCServerLocator.useServerLocatorIdentifier != nil, bookmark.serverLocationUserName == nil { - currentStep = .enterUsername - } else if bookmark.url == nil { - if let absoluteURL = configuration.url?.absoluteString, !configuration.urlEditable { - enterURL(absoluteURL, byUser: false, completion: { [weak self] error, issue, issueCompletionHandler in - if let self { - self.delegate?.present(composer: self, error: error, issue: issue, issueCompletionHandler: issueCompletionHandler) - } - }) - } else { - currentStep = .serverURL(urlString: configuration.url?.absoluteString) - } - } else if bookmark.authenticationData == nil { - currentStep = .authenticate(withCredentials: bookmark.isTokenBased == false, username: username, password: password) - } else if let instances, instances.count > 0 { - currentStep = .chooseServer(fromInstances: instances) - } else if supportsInfinitePropfind == true, !performedPrepopulation { - currentStep = .infinitePropfind - } else { - currentStep = .completed - } - } - - // MARK: - Add or update bookmark - func addBookmark() -> OCBookmark { - OCBookmarkManager.shared.addBookmark(bookmark) - - return bookmark - } - - func updateBookmark(_ originalBookmark: OCBookmark? = nil) { - guard let originalBookmark = originalBookmark ?? configuration.bookmark else { - return - } - - originalBookmark.setValuesFrom(bookmark) - - if !OCBookmarkManager.shared.updateBookmark(originalBookmark) { - Log.error("Changes to \(originalBookmark) not saved as it's not tracked by OCBookmarkManager!") - } - } -} - -protocol BookmarkComposerDelegate : AnyObject { - func present(composer: BookmarkComposer, step: BookmarkComposer.Step) - func present(composer: BookmarkComposer, error: Error?, issue: OCIssue?, issueCompletionHandler: IssuesCardViewController.CompletionHandler?) - func present(composer: BookmarkComposer, hudMessage: String?) -} - -extension OCBookmark { - var isComplete: Bool { - return url != nil && authenticationMethodIdentifier != nil && authenticationData != nil - } -} diff --git a/ownCloud/Bookmarks/Composer/BookmarkComposerConfiguration.swift b/ownCloud/Bookmarks/Composer/BookmarkComposerConfiguration.swift deleted file mode 100644 index f43c8971c..000000000 --- a/ownCloud/Bookmarks/Composer/BookmarkComposerConfiguration.swift +++ /dev/null @@ -1,58 +0,0 @@ -// -// BookmarkComposerConfiguration.swift -// ownCloud -// -// Created by Felix Schwarz on 05.09.23. -// Copyright © 2023 ownCloud GmbH. All rights reserved. -// - -/* - * Copyright (C) 2023, ownCloud GmbH. - * - * This code is covered by the GNU Public License Version 3. - * - * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ - * You should have received a copy of this license along with this program. If not, see . - * - */ - -import UIKit -import ownCloudSDK -import ownCloudApp -import ownCloudAppShared - -class BookmarkComposerConfiguration { - var bookmark: OCBookmark? - - var hasIntro: Bool = false - var hasSettings: Bool = false - - var url: URL? - var urlEditable: Bool = true - - var name: String? - var nameEditable: Bool = true - - var helpButtonLabel: String? - var helpButtonURL: URL? - var helpMessage: String? - - init(bookmark: OCBookmark? = nil, hasIntro: Bool = false, hasSettings: Bool = true, url: URL? = nil, urlEditable: Bool = true, name: String? = nil, nameEditable: Bool, helpButtonLabel: String? = nil, helpButtonURL: URL? = nil, helpMessage: String? = nil) { - self.bookmark = bookmark - self.hasIntro = hasIntro - self.hasSettings = hasSettings - self.url = url - self.urlEditable = urlEditable - self.name = name - self.nameEditable = nameEditable - self.helpButtonLabel = helpButtonLabel - self.helpButtonURL = helpButtonURL - self.helpMessage = helpMessage - } -} - -extension BookmarkComposerConfiguration { - static var newBookmarkConfiguration: BookmarkComposerConfiguration { - return BookmarkComposerConfiguration(url: Branding.shared.profileURL, urlEditable: Branding.shared.profileAllowUrlConfiguration ?? true, name: Branding.shared.profileBookmarkName, nameEditable: Branding.shared.canEditAccount, helpButtonLabel: Branding.shared.profileHelpButtonLabel, helpButtonURL: Branding.shared.profileHelpURL, helpMessage: Branding.shared.profileOpenHelpMessage) - } -} diff --git a/ownCloud/Bookmarks/Setup/BookmarkSetupStepViewController.swift b/ownCloud/Bookmarks/Setup/BookmarkSetupStepViewController.swift deleted file mode 100644 index fe35d5ac6..000000000 --- a/ownCloud/Bookmarks/Setup/BookmarkSetupStepViewController.swift +++ /dev/null @@ -1,293 +0,0 @@ -// -// BookmarkSetupStepViewController.swift -// ownCloud -// -// Created by Felix Schwarz on 06.09.23. -// Copyright © 2023 ownCloud GmbH. All rights reserved. -// - -/* - * Copyright (C) 2023, ownCloud GmbH. - * - * This code is covered by the GNU Public License Version 3. - * - * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ - * You should have received a copy of this license along with this program. If not, see . - * - */ - -import UIKit -import ownCloudSDK -import ownCloudAppShared - -extension BookmarkComposer.Step { - var cssSelector: ThemeCSSSelector { - switch self { - case .intro: return ThemeCSSSelector(rawValue: "intro") - case .enterUsername: return ThemeCSSSelector(rawValue: "enterUsername") - case .serverURL(urlString: _): return ThemeCSSSelector(rawValue: "serverURL") - case .authenticate(withCredentials: _, username: _, password: _): return ThemeCSSSelector(rawValue: "authenticate") - case .chooseServer(fromInstances: _): return ThemeCSSSelector(rawValue: "chooseServer") - case .infinitePropfind: return ThemeCSSSelector(rawValue: "infinitePropfind") - case .completed: return ThemeCSSSelector(rawValue: "completed") - } - } -} - -class BookmarkSetupStepViewController: UIViewController, UITextFieldDelegate { - weak var setupViewController: BookmarkSetupViewController? - var backgroundView: ThemeCSSView - var step: BookmarkComposer.Step - - var cacheViewController: Bool = true - - init(with setupViewController: BookmarkSetupViewController, step: BookmarkComposer.Step) { - self.setupViewController = setupViewController - self.step = step - self.backgroundView = ThemeCSSView(withSelectors: [.background]) - self.backgroundView.translatesAutoresizingMaskIntoConstraints = false - - composerCompletion = { [weak setupViewController] (error, issue, issueCompletionHandler) in - if let setupViewController, let composer = setupViewController.composer { - setupViewController.present(composer: composer, error: error, issue: issue, issueCompletionHandler: issueCompletionHandler) - } - } - - super.init(nibName: nil, bundle: nil) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - var stepTitle: String? - var stepMessage: String? - var continueButtonLabelText: String? = "Proceed".localized { - didSet { - var buttonConfiguration = continueButton.configuration - buttonConfiguration?.title = continueButtonLabelText - continueButton.configuration = buttonConfiguration - } - } - var backButtonLabelText: String? = "Back".localized { - didSet { - var buttonConfiguration = backButton.configuration - buttonConfiguration?.title = backButtonLabelText - backButton.configuration = buttonConfiguration - } - } - - var titleLabel: UILabel? - var messageLabel: UILabel? - var continueButton: UIButton = ThemeButton(withSelectors: [.filled]) - var backButton: UIButton = ThemeCSSButton(withSelectors: []) - - var contentContainerView: UIView? - var contentView: UIView? { - willSet { - if newValue != contentView { - contentView?.removeFromSuperview() - } - } - - didSet { - if let contentView { - contentContainerView?.embed(toFillWith: contentView) - } - } - } - - var bookmark: OCBookmark? { - return setupViewController?.composer?.bookmark - } - - var composerCompletion: BookmarkComposer.Completion - - var topViews: [UIView]? - var topViewsSpacing: CGFloat = 10 - var bottomViews: [UIView]? - var bottomViewsSpacing: CGFloat = 10 - - override func loadView() { - var views: [UIView] = topViews ?? [] - - let contentView = UIView() - contentView.cssSelectors = [.step, step.cssSelector] - - // Title & message - if let stepTitle = textOverride(for: "title") ?? stepTitle { - titleLabel = ThemeCSSLabel(withSelectors: [.title]) - titleLabel?.translatesAutoresizingMaskIntoConstraints = false - titleLabel?.text = stepTitle - titleLabel?.font = UIFont.preferredFont(forTextStyle: .headline, with: .bold) - titleLabel?.makeLabelWrapText() - - views.append(titleLabel!) - } - - if let stepMessage = textOverride(for: "message") ?? stepMessage { - messageLabel = ThemeCSSLabel(withSelectors: [.message]) - messageLabel?.translatesAutoresizingMaskIntoConstraints = false - messageLabel?.text = stepMessage - messageLabel?.font = UIFont.preferredFont(forTextStyle: .subheadline, with: .regular) - messageLabel?.makeLabelWrapText() - - views.append(messageLabel!) - } - - // Content container view - contentContainerView = UIView() - contentContainerView?.translatesAutoresizingMaskIntoConstraints = false - - if let contentContainerView { - views.append(contentContainerView) - } - - // Continue Button - var buttonConfiguration = UIButton.Configuration.borderedProminent() - buttonConfiguration.title = continueButtonLabelText - buttonConfiguration.cornerStyle = .large - - continueButton.translatesAutoresizingMaskIntoConstraints = false - continueButton.configuration = buttonConfiguration - continueButton.addAction(UIAction(handler: { [weak self] _ in - self?.handleContinue() - }), for: .primaryActionTriggered) - - views.append(continueButton) - - // Back button - if hasBackButton { - buttonConfiguration = UIButton.Configuration.plain() - buttonConfiguration.title = backButtonLabelText - buttonConfiguration.cornerStyle = .large - - backButton.translatesAutoresizingMaskIntoConstraints = false - backButton.configuration = buttonConfiguration - backButton.addAction(UIAction(handler: { [weak self] _ in - self?.handleBack() - }), for: .primaryActionTriggered) - - views.append(backButton) - } - - // Bottom views - if let bottomViews { - views.append(contentsOf: bottomViews) - } - - // Embed background view - self.backgroundView.layer.cornerRadius = 10 - self.backgroundView.layer.masksToBounds = true - contentView.embed(toFillWith: backgroundView) - - // Layout views vertically in background view - contentView.embedVertically(views: views, insets: NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20), spacingProvider: { leadingView, trailingView in - if leadingView == self.topViews?.last { - return self.topViewsSpacing - } - if trailingView == self.bottomViews?.first { - return self.bottomViewsSpacing - } - if trailingView == self.contentContainerView { - return 15 - } - if leadingView == self.contentContainerView { - return 30 - } - return 5 - }, centered: false) - - // Set view controller's view - self.view = contentView - } - - func handleContinue() { - } - - var hasBackButton: Bool { - return canGoBack - } - - var canGoBack: Bool { - return setupViewController?.canGoBack ?? false - } - - func handleBack() { - self.setupViewController?.goBack() - } - - func present(error: Error?, issue: OCIssue?, issueCompletionHandler: IssuesCardViewController.CompletionHandler?) { - if let composer = setupViewController?.composer, error != nil || issue != nil { - self.setupViewController?.present(composer: composer, error: error, issue: issue, issueCompletionHandler: issueCompletionHandler) - } - } - - func buildTextField(withAction textChangedAction: UIAction?, forEvent actionEvent: UIControl.Event = .editingChanged, placeholder placeholderString: String = "", value textValue: String = "", secureTextEntry : Bool = false, keyboardType: UIKeyboardType = .default, autocorrectionType: UITextAutocorrectionType = .default, autocapitalizationType: UITextAutocapitalizationType = UITextAutocapitalizationType.none, enablesReturnKeyAutomatically: Bool = true, returnKeyType : UIReturnKeyType = .default, inputAccessoryView : UIView? = nil, identifier : String? = nil, accessibilityLabel: String? = nil, clearButtonMode : UITextField.ViewMode = .never, borderStyle: UITextField.BorderStyle = .none) -> UITextField { - let textField : UITextField = ThemeCSSTextField() - - textField.translatesAutoresizingMaskIntoConstraints = false - - textField.placeholder = placeholderString - textField.keyboardType = keyboardType - textField.autocorrectionType = autocorrectionType - textField.isSecureTextEntry = secureTextEntry - textField.autocapitalizationType = autocapitalizationType - textField.enablesReturnKeyAutomatically = enablesReturnKeyAutomatically - textField.returnKeyType = returnKeyType - textField.inputAccessoryView = inputAccessoryView - textField.text = textValue - textField.accessibilityIdentifier = identifier - textField.clearButtonMode = clearButtonMode - textField.borderStyle = borderStyle - - if let textChangedAction { - textField.addAction(textChangedAction, for: actionEvent) - } - - textField.accessibilityLabel = accessibilityLabel - - textField.setContentHuggingPriority(.required, for: .vertical) - textField.setContentCompressionResistancePriority(.required, for: .horizontal) - - return textField - } - - var focusTextFields: [UITextField]? { - didSet { - if let focusTextFields { - for textField in focusTextFields { - textField.delegate = self - } - } - } - } - - func textFieldShouldReturn(_ textField: UITextField) -> Bool { - if let focusTextFields, let position = focusTextFields.firstIndex(of: textField) { - if position < (focusTextFields.count-1) { - let nextTextField = focusTextFields[position+1] - nextTextField.becomeFirstResponder() - - return false - } - } - - if continueButton.isEnabled { - handleContinue() - } - - return false - } - - func textOverride(for label: String) -> String? { - let key = "setup-\(step.cssSelector.rawValue)-\(label)" - let localization = key.localized - - if localization != key { - return localization - } - - return nil - } -} diff --git a/ownCloud/Bookmarks/Setup/BookmarkSetupViewController.swift b/ownCloud/Bookmarks/Setup/BookmarkSetupViewController.swift deleted file mode 100644 index 750ac0a7e..000000000 --- a/ownCloud/Bookmarks/Setup/BookmarkSetupViewController.swift +++ /dev/null @@ -1,359 +0,0 @@ -// -// BookmarkSetupViewController.swift -// ownCloud -// -// Created by Felix Schwarz on 05.09.23. -// Copyright © 2023 ownCloud GmbH. All rights reserved. -// - -/* - * Copyright (C) 2023, ownCloud GmbH. - * - * This code is covered by the GNU Public License Version 3. - * - * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ - * You should have received a copy of this license along with this program. If not, see . - * - */ - -import UIKit -import ownCloudSDK -import ownCloudApp -import ownCloudAppShared - -class BookmarkSetupViewController: EmbeddingViewController, BookmarkComposerDelegate { - var composer: BookmarkComposer? - var configuration: BookmarkComposerConfiguration - - var stepControllerByStep : [BookmarkComposer.Step : UIViewController] = [:] - - var visibleContentContainerView: UIView = UIView() - - var helpMessageView: ComposedMessageView? - - private var centerHelperView: UIView = UIView() - private var logoView: UIView? - - init(configuration: BookmarkComposerConfiguration, cancelHandler: CancelHandler? = nil, doneHandler: DoneHandler? = nil) { - self.configuration = configuration - - super.init(nibName: nil, bundle: nil) - - self.doneHandler = doneHandler - self.cancelHandler = cancelHandler - - composer = BookmarkComposer(configuration: configuration, delegate: self) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func loadView() { - let contentView = UIView() - - visibleContentContainerView.translatesAutoresizingMaskIntoConstraints = false - - let brandBackground = BrandView(showBackground: true, showLogo: false, roundedCorners: false, assetSuffix: .setup) - - contentView.embed(toFillWith: brandBackground) - contentView.embed(toFillWith: visibleContentContainerView, enclosingAnchors: contentView.safeAreaWithKeyboardAnchorSet) - - centerHelperView.translatesAutoresizingMaskIntoConstraints = false - contentView.addSubview(centerHelperView) - - self.cssSelectors = [.modal, .accountSetup] - - // Add logo - if navigationController == nil { - let deviceScreenHeight = UIScreen.main.bounds.height - let logoMaxHeight = deviceScreenHeight < 800 ? (deviceScreenHeight < 600 ? 48 : 96) : 128 - let maxLogoSize = CGSize(width: 256, height: logoMaxHeight) - logoView = BrandView(showBackground: false, showLogo: true, logoMaxSize: maxLogoSize, fitToLogo: true, roundedCorners: false, assetSuffix: .setup) - } - - if let logoView { - contentView.addSubview(logoView) - - NSLayoutConstraint.activate([ - centerHelperView.leadingAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.leadingAnchor).with(priority: .defaultLow), - centerHelperView.trailingAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.trailingAnchor).with(priority: .defaultLow), - - centerHelperView.topAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.topAnchor).with(priority: .defaultLow), - centerHelperView.heightAnchor.constraint(greaterThanOrEqualToConstant: 1), - - logoView.topAnchor.constraint(equalTo: centerHelperView.topAnchor), - logoView.centerXAnchor.constraint(equalTo: centerHelperView.centerXAnchor) - ]) - } - - // Add cancel button - if cancelHandler != nil { - if navigationController != nil { - navigationItem.rightBarButtonItem = UIBarButtonItem(systemItem: .cancel, primaryAction: UIAction(handler: { [weak self] action in - self?.cancel() - })) - } else { - let cancelButton = ThemeCSSButton(withSelectors: [.cancel]) - cancelButton.translatesAutoresizingMaskIntoConstraints = false - cancelButton.setTitle("Cancel".localized, for: .normal) - cancelButton.addAction(UIAction(handler: { [weak self] _ in - self?.cancel() - }), for: .primaryActionTriggered) - - contentView.addSubview(cancelButton) - - NSLayoutConstraint.activate([ - cancelButton.trailingAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.trailingAnchor, constant: -20), - cancelButton.topAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.topAnchor, constant: 20) - ]) - } - } - - // Add help message - if configuration.helpButtonURL != nil || configuration.helpMessage != nil { - var helpElements: [ComposedMessageElement] = [] - - if let helpButtonURL = configuration.helpButtonURL { - helpElements += [ - .button(configuration.helpButtonLabel ?? "Open help page".localized, action: UIAction(handler: { action in - UIApplication.shared.open(helpButtonURL) - }), image: UIImage(systemName: "questionmark.circle")) - ] - } - - if let helpMessage = configuration.helpMessage { - helpElements += [ - .subtitle(helpMessage, alignment: .centered) - ] - } - - let helpMessageView = ComposedMessageView(elements: helpElements) - helpMessageView.cssSelectors = [ .help ] - helpMessageView.elementInsets = NSDirectionalEdgeInsets(top: 0, leading: 15, bottom: 10, trailing: 15) - helpMessageView.setContentHuggingPriority(.required, for: .vertical) - - contentView.addSubview(helpMessageView) - - NSLayoutConstraint.activate([ - helpMessageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), - helpMessageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), - helpMessageView.bottomAnchor.constraint(equalTo: contentView.keyboardLayoutGuide.topAnchor) - ]) - } - - view = contentView - } - - override func viewDidLoad() { - super.viewDidLoad() - - composer?.updateState() - } - - override var supportedInterfaceOrientations: UIInterfaceOrientationMask { - return [.portrait, .portraitUpsideDown] - } - - override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { - return .portrait - } - - override var preferredStatusBarStyle : UIStatusBarStyle { - return Theme.shared.activeCollection.css.getStatusBarStyle(for: self) ?? .default - } - - // MARK: - Steps view controller and layout - func viewController(for step: BookmarkComposer.Step) -> UIViewController? { - if let stepViewController = stepControllerByStep[step] { - return stepViewController - } - - var stepViewController: UIViewController? - - switch step { - case .intro: - stepViewController = BookmarkSetupStepIntroViewController(with: self, step: step) - - case .serverURL(urlString: _): - stepViewController = BookmarkSetupStepEnterURLViewController(with: self, step: step) - - case .enterUsername: - stepViewController = BookmarkSetupStepEnterUsernameViewController(with: self, step: step) - - case .authenticate(withCredentials: _, username: _, password: _): - stepViewController = BookmarkSetupStepAuthenticateViewController(with: self, step: step) - - case .chooseServer(fromInstances: _): - // Do not support server choice for now (also see present(composer:step:) - break - - case .infinitePropfind: - stepViewController = BookmarkSetupStepPrepopulateViewController(with: self, step: step) - - case .completed: - if composer?.configuration.nameEditable == true { - stepViewController = BookmarkSetupStepFinishedViewController(with: self, step: step) - } else { - let bookmark = composer?.addBookmark() - done(bookmark: bookmark) - } - } - - (stepViewController as? BookmarkSetupStepViewController)?.setupViewController = self - - if (stepViewController as? BookmarkSetupStepViewController)?.cacheViewController == true { - stepControllerByStep[step] = stepViewController - } - - return stepViewController - } - - override func constraintsForEmbedding(contentViewController: UIViewController) -> [NSLayoutConstraint] { - let contentViewControllerView = contentViewController.view! - var constraints: [NSLayoutConstraint] - - if let logoView { - constraints = visibleContentContainerView.embed(centered: centerHelperView, minimumInsets: NSDirectionalEdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20), constraintsOnly: true) - - constraints += [ - contentViewControllerView.topAnchor.constraint(equalTo: logoView.safeAreaLayoutGuide.bottomAnchor, constant: 10), - contentViewControllerView.bottomAnchor.constraint(equalTo: centerHelperView.safeAreaLayoutGuide.bottomAnchor), - contentViewControllerView.leadingAnchor.constraint(equalTo: centerHelperView.safeAreaLayoutGuide.leadingAnchor), - contentViewControllerView.trailingAnchor.constraint(equalTo: centerHelperView.safeAreaLayoutGuide.trailingAnchor) - ] - } else { - constraints = visibleContentContainerView.embed(centered: contentViewControllerView, minimumInsets: NSDirectionalEdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20), constraintsOnly: true) - } - - return constraints - } - - // MARK: - HUD message - var hudMessageView: UIView? { - willSet { - hudMessageView?.removeFromSuperview() - - if newValue == nil { - contentViewController?.view.isHidden = false - logoView?.isHidden = false - } - } - - didSet { - if let hudMessageView { - visibleContentContainerView.addSubview(hudMessageView) - NSLayoutConstraint.activate([ - hudMessageView.centerYAnchor.constraint(equalTo: visibleContentContainerView.centerYAnchor), - hudMessageView.centerXAnchor.constraint(equalTo: visibleContentContainerView.safeAreaLayoutGuide.centerXAnchor), - hudMessageView.leadingAnchor.constraint(greaterThanOrEqualTo: visibleContentContainerView.safeAreaLayoutGuide.leadingAnchor, constant: 20), - hudMessageView.trailingAnchor.constraint(lessThanOrEqualTo: visibleContentContainerView.safeAreaLayoutGuide.trailingAnchor, constant: -20) - ]) - contentViewController?.view.isHidden = true - logoView?.isHidden = true - } - } - } - - // MARK: - History support - var canGoBack: Bool { - return composer?.canUndoLastStep ?? false - } - - func goBack() { - if canGoBack { - composer?.undoLastStep() - } - } - - // MARK: - Dismiss - typealias CancelHandler = () -> Void - var cancelHandler: CancelHandler? - - func cancel() { - cancelHandler?() - cancelHandler = nil - } - - typealias DoneHandler = (_ bookmark: OCBookmark?) -> Void - var doneHandler: DoneHandler? - - func done(bookmark: OCBookmark?) { - doneHandler?(bookmark) - doneHandler = nil - } - - // MARK: - Bookmark Composer Delegate - func present(composer: BookmarkComposer, step: BookmarkComposer.Step) { - if case let .chooseServer(fromInstances: instances) = step { - // Do not support server choice for now (also see viewController(for:) - // Pick first server from list - composer.chooseServer(instance: instances.first!, completion: { [weak self] error, issue, issueCompletionHandler in - guard let self, let composer = self.composer else { return } - self.present(composer: composer, error: error, issue: issue, issueCompletionHandler: issueCompletionHandler) - }) - } else { - OnMainThread { - let stepViewController = self.viewController(for: step) - stepViewController?.view.widthAnchor.constraint(greaterThanOrEqualToConstant: 400).with(priority: .defaultHigh).isActive = true - self.contentViewController = stepViewController - } - } - } - - func present(composer: BookmarkComposer, hudMessage: String?) { - OnMainThread { - if let hudMessage { - let indeterminateProgress = Progress.indeterminate() - indeterminateProgress.isCancellable = false - - let messageView = ComposedMessageView.infoBox(additionalElements: [ - .progressCircle(with: indeterminateProgress, alignment: .centered), - .spacing(10), - .text(hudMessage, style: .system(textStyle: .headline, weight: .bold), alignment: .centered) - ]) - messageView.cssSelectors = [ .step ] - - messageView.widthAnchor.constraint(greaterThanOrEqualToConstant: 400).with(priority: .defaultHigh).isActive = true - - self.hudMessageView = messageView - } else { - self.hudMessageView = nil - } - } - } - - func present(composer: BookmarkComposer, error: Error?, issue: OCIssue?, issueCompletionHandler: IssuesCardViewController.CompletionHandler?) { - OnMainThread { - var presentIssue: OCIssue? = issue - var completionHandler = issueCompletionHandler - - if presentIssue == nil, let error { - presentIssue = OCIssue(forError: error, level: .warning) - } - - if completionHandler == nil { - completionHandler = { [weak presentIssue] (response) in - switch response { - case .cancel: - presentIssue?.reject() - - case .approve: - presentIssue?.approve() - - case .dismiss: break - } - } - } - - if let presentIssue, let completionHandler { - let displayIssues = presentIssue.prepareForDisplay() - - IssuesCardViewController.present(on: self, issue: presentIssue, displayIssues: displayIssues, completion: completionHandler) - } - } - } -} - -extension ThemeCSSSelector { -} diff --git a/ownCloud/Bookmarks/Setup/Steps/BookmarkSetupStepAuthenticateViewController.swift b/ownCloud/Bookmarks/Setup/Steps/BookmarkSetupStepAuthenticateViewController.swift deleted file mode 100644 index dd5087c56..000000000 --- a/ownCloud/Bookmarks/Setup/Steps/BookmarkSetupStepAuthenticateViewController.swift +++ /dev/null @@ -1,114 +0,0 @@ -// -// BookmarkSetupStepAuthenticateViewController.swift -// ownCloud -// -// Created by Felix Schwarz on 06.09.23. -// Copyright © 2023 ownCloud GmbH. All rights reserved. -// - -/* - * Copyright (C) 2023, ownCloud GmbH. - * - * This code is covered by the GNU Public License Version 3. - * - * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ - * You should have received a copy of this license along with this program. If not, see . - * - */ - -import UIKit - -class BookmarkSetupStepAuthenticateViewController: BookmarkSetupStepViewController { - var usernameField: UITextField? - var passwordField: UITextField? - - override init(with setupViewController: BookmarkSetupViewController, step: BookmarkComposer.Step) { - super.init(with: setupViewController, step: step) - cacheViewController = false - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func loadView() { - guard case let .authenticate(withCredentials: withCredentials, username: prefillUsername, password: prefillPassword) = step else { - return - } - - if withCredentials { - continueButtonLabelText = "Login".localized - } else { - stepTitle = "Login".localized - stepMessage = "If you 'Continue', you will be prompted to allow the '{{app.name}}' app to open the login page where you can enter your credentials.".localized - continueButtonLabelText = "Open login page".localized - } - - let certificateSummaryView = CertificateSummaryView(with: bookmark?.primaryCertificate, httpHostname: bookmark?.url?.host) - certificateSummaryView.translatesAutoresizingMaskIntoConstraints = false - - if withCredentials { - self.topViews = [ certificateSummaryView ] - self.topViewsSpacing = 20 - } - - super.loadView() - - if withCredentials { - usernameField = buildTextField(withAction: UIAction(handler: { [weak self] _ in - self?.updateState() - }), placeholder: "Username", value: prefillUsername ?? "", autocorrectionType: .no, autocapitalizationType: .none, accessibilityLabel: "Server Username".localized, borderStyle: .roundedRect) - usernameField?.textContentType = .username - - passwordField = buildTextField(withAction: UIAction(handler: { [weak self] _ in - self?.updateState() - }), placeholder: "Password", value: prefillPassword ?? "", secureTextEntry: true, autocorrectionType: .no, autocapitalizationType: .none, accessibilityLabel: "Server Password".localized, borderStyle: .roundedRect) - passwordField?.textContentType = .password - - focusTextFields = [ usernameField!, passwordField! ] - - let hostView = UIView() - hostView.translatesAutoresizingMaskIntoConstraints = false - - hostView.embedVertically(views: [usernameField!, passwordField!], insets: .zero, spacingProvider: { leadingView, trailingView in - return 10 - }, centered: false) - - contentView = hostView - } else { - contentView = certificateSummaryView - } - - updateState() - } - - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - - guard case let .authenticate(withCredentials: withCredentials, username: _, password: _) = step else { - return - } - - if withCredentials { - usernameField?.becomeFirstResponder() - } - } - - func updateState() { - guard case let .authenticate(withCredentials: withCredentials, username: _, password: _) = step else { - return - } - - if withCredentials { - if let username = usernameField?.text, username.count > 0, let password = usernameField?.text, password.count > 0 { - continueButton.isEnabled = true - } else { - continueButton.isEnabled = false - } - } - } - - override func handleContinue() { - setupViewController?.composer?.authenticate(username: usernameField?.text, password: passwordField?.text, presentingViewController: self, completion: composerCompletion) - } -} diff --git a/ownCloud/Bookmarks/Setup/Steps/BookmarkSetupStepEnterURLViewController.swift b/ownCloud/Bookmarks/Setup/Steps/BookmarkSetupStepEnterURLViewController.swift deleted file mode 100644 index b06dd60a4..000000000 --- a/ownCloud/Bookmarks/Setup/Steps/BookmarkSetupStepEnterURLViewController.swift +++ /dev/null @@ -1,61 +0,0 @@ -// -// BookmarkSetupStepEnterURLViewController.swift -// ownCloud -// -// Created by Felix Schwarz on 06.09.23. -// Copyright © 2023 ownCloud GmbH. All rights reserved. -// - -/* - * Copyright (C) 2023, ownCloud GmbH. - * - * This code is covered by the GNU Public License Version 3. - * - * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ - * You should have received a copy of this license along with this program. If not, see . - * - */ - -import UIKit -import ownCloudAppShared - -class BookmarkSetupStepEnterURLViewController: BookmarkSetupStepViewController { - var urlTextField: UITextField? - - override func loadView() { - stepTitle = "Server URL".localized - - super.loadView() - - urlTextField = buildTextField(withAction: UIAction(handler: { [weak self] _ in - self?.updateState() - }), placeholder: "https://", keyboardType: .URL, autocorrectionType: .no, autocapitalizationType: .none, accessibilityLabel: "Server URL".localized, borderStyle: .roundedRect) - - urlTextField?.text = setupViewController?.composer?.configuration.url?.absoluteString - - focusTextFields = [ urlTextField! ] - - contentView = urlTextField - - updateState() - } - - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - urlTextField?.becomeFirstResponder() - } - - func updateState() { - if let urlString = urlTextField?.text, urlString.count > 0, NSURL(username: nil, password: nil, afterNormalizingURLString: urlString, protocolWasPrepended: nil) != nil { - continueButton.isEnabled = true - } else { - continueButton.isEnabled = false - } - } - - override func handleContinue() { - if let urlString = urlTextField?.text { - setupViewController?.composer?.enterURL(urlString, completion: composerCompletion) - } - } -} diff --git a/ownCloud/Bookmarks/Setup/Steps/BookmarkSetupStepEnterUsernameViewController.swift b/ownCloud/Bookmarks/Setup/Steps/BookmarkSetupStepEnterUsernameViewController.swift deleted file mode 100644 index 0b2af7d57..000000000 --- a/ownCloud/Bookmarks/Setup/Steps/BookmarkSetupStepEnterUsernameViewController.swift +++ /dev/null @@ -1,59 +0,0 @@ -// -// BookmarkSetupStepEnterUsernameViewController.swift -// ownCloud -// -// Created by Felix Schwarz on 06.09.23. -// Copyright © 2023 ownCloud GmbH. All rights reserved. -// - -/* - * Copyright (C) 2023, ownCloud GmbH. - * - * This code is covered by the GNU Public License Version 3. - * - * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ - * You should have received a copy of this license along with this program. If not, see . - * - */ - -import UIKit - -class BookmarkSetupStepEnterUsernameViewController: BookmarkSetupStepViewController { - var usernameField: UITextField? - - override func loadView() { - stepTitle = "Username".localized - - super.loadView() - - usernameField = buildTextField(withAction: UIAction(handler: { [weak self] _ in - self?.updateState() - }), autocorrectionType: .no, autocapitalizationType: .none, accessibilityLabel: "Username".localized, borderStyle: .roundedRect) - usernameField?.textContentType = .username - - focusTextFields = [ usernameField! ] - - contentView = usernameField - - updateState() - } - - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - usernameField?.becomeFirstResponder() - } - - func updateState() { - if let username = usernameField?.text, username.count > 0 { - continueButton.isEnabled = true - } else { - continueButton.isEnabled = false - } - } - - override func handleContinue() { - if let username = usernameField?.text { - setupViewController?.composer?.enterUsername(username, completion: composerCompletion) - } - } -} diff --git a/ownCloud/Bookmarks/Setup/Steps/BookmarkSetupStepFinishedViewController.swift b/ownCloud/Bookmarks/Setup/Steps/BookmarkSetupStepFinishedViewController.swift deleted file mode 100644 index a2a48b2f4..000000000 --- a/ownCloud/Bookmarks/Setup/Steps/BookmarkSetupStepFinishedViewController.swift +++ /dev/null @@ -1,58 +0,0 @@ -// -// BookmarkSetupStepFinishedViewController.swift -// ownCloud -// -// Created by Felix Schwarz on 06.09.23. -// Copyright © 2023 ownCloud GmbH. All rights reserved. -// - -/* - * Copyright (C) 2023, ownCloud GmbH. - * - * This code is covered by the GNU Public License Version 3. - * - * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ - * You should have received a copy of this license along with this program. If not, see . - * - */ - -import UIKit - -class BookmarkSetupStepFinishedViewController: BookmarkSetupStepViewController { - var bookmarkNameField: UITextField? - - override func loadView() { - stepTitle = "Account setup complete".localized - - if setupViewController?.configuration.nameEditable == true { - stepMessage = "If you'd like to give the account a custom name, please enter it below:".localized - } - - continueButtonLabelText = "Done".localized - - super.loadView() - - if setupViewController?.configuration.nameEditable == true { - bookmarkNameField = buildTextField(withAction: UIAction(handler: { [weak self] _ in - self?.updateName() - }), placeholder: setupViewController?.composer?.bookmark.shortName ?? "Name", value: setupViewController?.composer?.bookmark.name ?? "", autocorrectionType: .no, autocapitalizationType: .none, accessibilityLabel: "Name".localized, borderStyle: .roundedRect) - - contentView = bookmarkNameField - } - } - - func updateName() { - var name = bookmarkNameField?.text - - if name != nil, name?.count == 0 { - name = nil - } - - setupViewController?.composer?.setName(name) - } - - override func handleContinue() { - let bookmark = setupViewController?.composer?.addBookmark() - setupViewController?.done(bookmark: bookmark) - } -} diff --git a/ownCloud/Bookmarks/Setup/Steps/BookmarkSetupStepIntroViewController.swift b/ownCloud/Bookmarks/Setup/Steps/BookmarkSetupStepIntroViewController.swift deleted file mode 100644 index 17f2afb8e..000000000 --- a/ownCloud/Bookmarks/Setup/Steps/BookmarkSetupStepIntroViewController.swift +++ /dev/null @@ -1,59 +0,0 @@ -// -// BookmarkSetupStepIntroViewController.swift -// ownCloud -// -// Created by Felix Schwarz on 11.09.23. -// Copyright © 2023 ownCloud GmbH. All rights reserved. -// - -/* - * Copyright (C) 2023, ownCloud GmbH. - * - * This code is covered by the GNU Public License Version 3. - * - * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ - * You should have received a copy of this license along with this program. If not, see . - * - */ - -import UIKit -import ownCloudAppShared - -class BookmarkSetupStepIntroViewController: BookmarkSetupStepViewController { - var hasSettings: Bool { - return setupViewController?.configuration.hasSettings == true - } - - override func loadView() { - super.loadView() - - continueButtonLabelText = "Start setup".localized - - if hasSettings { - backButtonLabelText = "Settings".localized - } - - let messageView = ComposedMessageView(elements: [ - .title(String(format: "Welcome to %@".localized, VendorServices.shared.appName), alignment: .centered, cssSelectors: [.title], insets: NSDirectionalEdgeInsets(top: 10, leading: 0, bottom: 10, trailing: 0)), - .subtitle("The following steps will guide you through the setup process.".localized, alignment: .centered, cssSelectors: [.message]) - ]) - messageView.elementInsets = .zero - messageView.cssSelectors = [ .welcome ] - - contentView = messageView - } - - override var hasBackButton: Bool { - return hasSettings - } - - override func handleContinue() { - setupViewController?.composer?.doneIntro() - } - - override func handleBack() { - let navigationViewController = ThemeNavigationController(rootViewController: SettingsViewController()) - navigationViewController.modalPresentationStyle = .fullScreen - present(navigationViewController, animated: true) - } -} diff --git a/ownCloud/Bookmarks/Setup/Steps/BookmarkSetupStepPrepopulateViewController.swift b/ownCloud/Bookmarks/Setup/Steps/BookmarkSetupStepPrepopulateViewController.swift deleted file mode 100644 index 400d45b1f..000000000 --- a/ownCloud/Bookmarks/Setup/Steps/BookmarkSetupStepPrepopulateViewController.swift +++ /dev/null @@ -1,102 +0,0 @@ -// -// BookmarkSetupStepPrepopulateViewController.swift -// ownCloud -// -// Created by Felix Schwarz on 06.09.23. -// Copyright © 2023 ownCloud GmbH. All rights reserved. -// - -/* - * Copyright (C) 2023, ownCloud GmbH. - * - * This code is covered by the GNU Public License Version 3. - * - * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ - * You should have received a copy of this license along with this program. If not, see . - * - */ - -import UIKit -import ownCloudAppShared - -class BookmarkSetupStepProgressViewController: BookmarkSetupStepViewController { - open var cancelled : Bool = false - - open var progressView : ProgressView - - var progressMessageObservation : NSKeyValueObservation? - var progressValueObservation : NSKeyValueObservation? - open var progress : Progress? { - willSet { - progressMessageObservation?.invalidate() - progressMessageObservation = nil - - progressView.progress = nil - } - - didSet { - if progress != nil { - progressMessageObservation = progress?.observe(\Progress.localizedDescription, options: NSKeyValueObservingOptions.initial, changeHandler: { [weak self] progress, _ in - OnMainThread { - self?.messageLabel?.text = progress.localizedDescription - } - }) - - progressView.progress = progress - } - } - } - - public override init(with setupViewController: BookmarkSetupViewController, step: BookmarkComposer.Step) { - progressView = ProgressView() - progressView.translatesAutoresizingMaskIntoConstraints = false - - let indeterminateProgress = Progress.indeterminate() - indeterminateProgress.isCancellable = false - progressView.progress = indeterminateProgress - - super.init(with: setupViewController, step: step) - } - - required public init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override open func viewDidLoad() { - super.viewDidLoad() - self.contentView = progressView - } - - override func handleContinue() { - if !self.cancelled { - self.handleCancellation() - } - - self.cancelled = true - } - - func handleCancellation() { - // Subclassing point - } -} - -class BookmarkSetupStepPrepopulateViewController: BookmarkSetupStepProgressViewController { - public override init(with setupViewController: BookmarkSetupViewController, step: BookmarkComposer.Step) { - super.init(with: setupViewController, step: step) - - self.stepTitle = "Preparing account".localized - self.stepMessage = "Please wait…".localized - - self.continueButtonLabelText = "Skip".localized - - self.progress = setupViewController.composer?.prepopulate(completion: self.composerCompletion) - } - - required public init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func handleCancellation() { - self.progress?.cancel() - } -} diff --git a/ownCloud/Bookmarks/Setup/Steps/CertificateSummaryView.swift b/ownCloud/Bookmarks/Setup/Steps/CertificateSummaryView.swift deleted file mode 100644 index a09127e88..000000000 --- a/ownCloud/Bookmarks/Setup/Steps/CertificateSummaryView.swift +++ /dev/null @@ -1,128 +0,0 @@ -// -// CertificateSummaryView.swift -// ownCloud -// -// Created by Felix Schwarz on 06.09.23. -// Copyright © 2023 ownCloud GmbH. All rights reserved. -// - -/* - * Copyright (C) 2023, ownCloud GmbH. - * - * This code is covered by the GNU Public License Version 3. - * - * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ - * You should have received a copy of this license along with this program. If not, see . - * - */ - -import UIKit -import ownCloudSDK -import ownCloudApp -import ownCloudAppShared - -class CertificateSummaryView: ThemeCSSView { - init(with certificate: OCCertificate?, httpHostname: String?) { - super.init() - - cssSelector = .certificateSummary - - button.translatesAutoresizingMaskIntoConstraints = false - embed(toFillWith: button) - - button.addAction(UIAction(handler: { [weak self] _ in - self?.showCertificate() - }), for: .primaryActionTriggered) - - OnMainThread { - self.httpHostname = httpHostname - self.certificate = certificate - - self.update() - } - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - var certificate: OCCertificate? { - didSet { - if let certificate { - certificate.validationResult(completionHandler: { (validationResult, shortDescription, _, color, _) in - OnMainThread { - self.validationResult = validationResult - self.statusText = shortDescription - self.statusColor = color - - self.update() - } - }) - } else { - OnMainThread { - self.validationResult = nil - self.statusText = nil - self.statusColor = .systemRed - - self.update() - } - } - } - } - - var httpHostname: String? - - var button: UIButton = UIButton() - - var validationResult: OCCertificateValidationResult? - var statusText: String? - var statusColor: UIColor? - - var statusImage: UIImage? { - var imageName: String? - - if certificate != nil { - if let validationResult { - - switch validationResult { - case .none, .error, .reject, .promptUser: - imageName = "lock.slash.fill" - - case .passed: - imageName = "lock.fill" - - case .userAccepted: - imageName = "exclamationmark.lock.fill" - } - } - } else { - imageName = "lock.open.fill" - } - - if let imageName { - return UIImage.init(systemName: imageName) - } - - return nil - } - - func update() { - var buttonConfiguration : UIButton.Configuration = .borderless() - buttonConfiguration.baseForegroundColor = statusColor - buttonConfiguration.baseBackgroundColor = .clear - buttonConfiguration.image = self.statusImage - buttonConfiguration.title = certificate?.hostName ?? httpHostname - buttonConfiguration.buttonSize = .mini - - button.configuration = buttonConfiguration - } - - func showCertificate() { - if let certificate { - let certificateViewController : ThemeCertificateViewController = ThemeCertificateViewController(certificate: certificate, compare: nil) - let navigationController = ThemeNavigationController(rootViewController: certificateViewController) - - hostingViewController?.present(navigationController, animated: true, completion: nil) - } - } -} diff --git a/ownCloud/Client/Actions/Actions+Extensions/CreateDocumentAction.swift b/ownCloud/Client/Actions/Actions+Extensions/CreateDocumentAction.swift index 2814c1cf4..a7c832f63 100644 --- a/ownCloud/Client/Actions/Actions+Extensions/CreateDocumentAction.swift +++ b/ownCloud/Client/Actions/Actions+Extensions/CreateDocumentAction.swift @@ -270,7 +270,6 @@ class CreateDocumentAction: Action { } }) - documentNameViewController.requiredFileExtension = fileType.extension documentNameViewController.navigationItem.title = "Pick a name".localized navigationViewController.pushViewController(documentNameViewController, animated: true) diff --git a/ownCloud/Client/Actions/EditDocumentViewController.swift b/ownCloud/Client/Actions/EditDocumentViewController.swift index a0f77fa37..0553f4cba 100644 --- a/ownCloud/Client/Actions/EditDocumentViewController.swift +++ b/ownCloud/Client/Actions/EditDocumentViewController.swift @@ -154,24 +154,10 @@ class EditDocumentViewController: QLPreviewController, Themeable { } } } - - func disableEditingMode() { - if #available(iOS 17.0, *) { - if let rightBarButtonItems = self.navigationItem.rightBarButtonItems, rightBarButtonItems.count > 0 { - for markupButton in rightBarButtonItems { - if (markupButton.debugDescription as NSString).contains("pencil.tip.crop.circle") { - _ = markupButton.target?.perform(markupButton.action, with: markupButton) - } - } - } - } else { - self.setEditing(false, animated: false) - } - } @objc func dismissAnimated() { - disableEditingMode() - + self.setEditing(false, animated: false) + if savingMode == nil { requestsavingMode { (savingMode) in self.dismiss(animated: true) { diff --git a/ownCloud/Client/Actions/Scanner/ScanViewController.swift b/ownCloud/Client/Actions/Scanner/ScanViewController.swift index 24d4e4288..43853dec8 100644 --- a/ownCloud/Client/Actions/Scanner/ScanViewController.swift +++ b/ownCloud/Client/Actions/Scanner/ScanViewController.swift @@ -287,11 +287,6 @@ class ScanViewController: StaticTableViewController { didSet { if let fileName = fileNameRow?.value as? NSString { fileNameRow?.value = fileName.deletingPathExtension + "." + (exportFormat?.suffix ?? "") - fileNameRow?.requiredFileExtension = exportFormat?.suffix - - if let textField = fileNameRow?.textField, textField.isFirstResponder { - textField.selectedTextRange = textField.textRange(from: textField.beginningOfDocument, to: textField.beginningOfDocument) - } } guard let oneFilePerPageRow = oneFilePerPageRow else { return } @@ -320,9 +315,7 @@ class ScanViewController: StaticTableViewController { self.isModalInPresentation = true self.navigationItem.title = "Scan".localized self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(ScanViewController.cancel)) - - let saveBarButtonItem = UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(ScanViewController.save)) - self.navigationItem.rightBarButtonItem = saveBarButtonItem + self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(ScanViewController.save)) self.core = core self.targetFolderItem = item @@ -360,7 +353,7 @@ class ScanViewController: StaticTableViewController { // Save section // - Name - fileNameRow = StaticTableViewRow(textFieldWithAction: { [weak self, weak saveBarButtonItem] (row, textField, type) in + fileNameRow = StaticTableViewRow(textFieldWithAction: { [weak self] (row, textField, type) in self?.navigationItem.rightBarButtonItem?.isEnabled = ((row.value as? String)?.count ?? 0) > 0 if type == .didBegin, let nameTextField = textField as? UITextField { @@ -376,10 +369,6 @@ class ScanViewController: StaticTableViewController { nameTextField.selectedTextRange = nameTextField.textRange(from: nameTextField.beginningOfDocument, to: nameTextField.endOfDocument) } } - - if let fileName = (textField as? UITextField)?.text, let requiredFileExtension = row.requiredFileExtension { - saveBarButtonItem?.isEnabled = (fileName.count > (requiredFileExtension.count + 1)) - } }, placeholder: "Name".localized, value: fileName ?? "", keyboardType: .default, autocorrectionType: .no, enablesReturnKeyAutomatically: true, returnKeyType: .default, identifier: "name", accessibilityLabel: "Name".localized) saveSection.add(row: fileNameRow!) self.addSection(saveSection) diff --git a/ownCloud/Client/Viewer/DisplayHostViewController.swift b/ownCloud/Client/Viewer/DisplayHostViewController.swift index 165f250ce..f13a59aef 100644 --- a/ownCloud/Client/Viewer/DisplayHostViewController.swift +++ b/ownCloud/Client/Viewer/DisplayHostViewController.swift @@ -176,13 +176,13 @@ class DisplayHostViewController: UIPageViewController { } // MARK: - Active Viewer - private var _navigationItemObservation : NSKeyValueObservation? + private var _navigationTitleObservation : NSKeyValueObservation? private var _navigationBarButtonItemsObservation : NSKeyValueObservation? weak var activeDisplayViewController : DisplayViewController? { willSet { - _navigationItemObservation?.invalidate() - _navigationItemObservation = nil + _navigationTitleObservation?.invalidate() + _navigationTitleObservation = nil _navigationBarButtonItemsObservation?.invalidate() _navigationBarButtonItemsObservation = nil @@ -191,12 +191,8 @@ class DisplayHostViewController: UIPageViewController { didSet { Log.debug("New activeDisplayViewController: \(activeDisplayViewController?.item?.name ?? "-")") - _navigationItemObservation = activeDisplayViewController?.observe(\DisplayViewController.item, options: .initial, changeHandler: { [weak self] (displayViewController, _) in - if let itemLocation = displayViewController.item?.location, let clientContext = displayViewController.clientContext { - OnMainThread(inline: true) { - self?.navigationItem.titleView = ClientLocationPopupButton(clientContext: clientContext, location: itemLocation) - } - } + _navigationTitleObservation = activeDisplayViewController?.observe(\DisplayViewController.displayTitle, options: .initial, changeHandler: { [weak self] (displayViewController, _) in + self?.navigationItem.title = displayViewController.displayTitle }) _navigationBarButtonItemsObservation = activeDisplayViewController?.observe(\DisplayViewController.displayBarButtonItems, options: .initial, changeHandler: { [weak self] (displayViewController, _) in diff --git a/ownCloud/Client/Viewer/DisplayViewController.swift b/ownCloud/Client/Viewer/DisplayViewController.swift index 55a333bd5..86008909f 100644 --- a/ownCloud/Client/Viewer/DisplayViewController.swift +++ b/ownCloud/Client/Viewer/DisplayViewController.swift @@ -120,7 +120,7 @@ class DisplayViewController: UIViewController, Themeable, OCQueryDelegate { return nil } - @objc dynamic var item: OCItem? { + var item: OCItem? { didSet { if itemClaimIdentifier == nil, // No claim registered by the DisplayViewController for the item yet let item = item, let core = core, @@ -477,8 +477,8 @@ class DisplayViewController: UIViewController, Themeable, OCQueryDelegate { } // MARK: - UI management - @objc dynamic var displayTitle : String? - @objc dynamic var displayBarButtonItems : [UIBarButtonItem]? + @objc var displayTitle : String? + @objc var displayBarButtonItems : [UIBarButtonItem]? private func updateDisplayTitleAndButtons() { if let itemName = item?.name { diff --git a/ownCloud/Client/Viewer/Image/ImageDisplayViewController.swift b/ownCloud/Client/Viewer/Image/ImageDisplayViewController.swift index 9e6bf5a56..debb8ada9 100644 --- a/ownCloud/Client/Viewer/Image/ImageDisplayViewController.swift +++ b/ownCloud/Client/Viewer/Image/ImageDisplayViewController.swift @@ -220,13 +220,6 @@ extension ImageDisplayViewController: DisplayExtension { extension ImageDisplayViewController: UIGestureRecognizerDelegate { func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool { - if gestureRecognizer == tapToZoomGestureRecognizer, - scrollView?.hasActiveImageAnalysisSelection == true, // allow selection when VisionKit image analysis is active - let otherGestureRecognizer = otherGestureRecognizer as? UITapGestureRecognizer, - otherGestureRecognizer.numberOfTapsRequired == 2 { - return true - } - if gestureRecognizer === tapToZoomGestureRecognizer && otherGestureRecognizer === showHideBarsTapGestureRecognizer { return true } diff --git a/ownCloud/Licensing/Offers/LicenseOfferView.swift b/ownCloud/Licensing/Offers/LicenseOfferView.swift index b8e8e1808..4e43924ee 100644 --- a/ownCloud/Licensing/Offers/LicenseOfferView.swift +++ b/ownCloud/Licensing/Offers/LicenseOfferView.swift @@ -204,7 +204,7 @@ class LicenseOfferView: UIView, Themeable { if let purchaseButton = purchaseButton { let progress = Progress.indeterminate() - progress.isCancellable = false + progress?.isCancellable = false purchaseBusyView = ProgressView() purchaseBusyView?.translatesAutoresizingMaskIntoConstraints = false diff --git a/ownCloud/Release Notes/ReleaseNotes.plist b/ownCloud/Release Notes/ReleaseNotes.plist index a1dd56af1..717842625 100644 --- a/ownCloud/Release Notes/ReleaseNotes.plist +++ b/ownCloud/Release Notes/ReleaseNotes.plist @@ -1788,123 +1788,6 @@ Added an optional "Wait for completion" option to the "Save File& - - Version - 12.1 - ReleaseNotes - - - Title - New account wizard - Subtitle - Introducing a new, intuitive account wizard user interface for a fast onboarding experience. - Type - New - ImageName - sparkles.rectangle.stack - - - Title - Reordering accounts - Subtitle - Now you can easily reorder accounts in the sidebar by simply dragging and dropping them. - Type - New - ImageName - line.3.horizontal.circle - - - Title - Location breadcrumb - Subtitle - We have added a location breadcrumb dropdown in the file viewer, making it easier to navigate through your files. - Type - New - ImageName - chevron.down - - - Title - Text recognition - Subtitle - You can now perform text recognition actions on images. - Type - New - ImageName - text.viewfinder - - - Title - File extension / suffix protection - Subtitle - To prevent accidental removal or modification of the suffix for new documents and document scanner files, we have implemented file extension protection. - Type - New - ImageName - lock.shield - - - Title - Share Action "Save to ownCloud" - Subtitle - We have added a new action called "Save to ownCloud" to the share sheet, allowing you to easily save files to your ownCloud account. - Type - New - ImageName - square.and.arrow.up - - - Title - Link naming - Subtitle - You can now enter and edit the name of link shares. - Type - New - ImageName - character.textbox - - - Title - Sort by Last Used - Subtitle - Introducing a new sorting method - “Last Used” - which allows you to sort items based on the most recently accessed ones. - Type - New - ImageName - arrow.up.arrow.down - - - Title - Markup Edit Mode on iOS 17 - Subtitle - We have fixed the issue that was disabling the edit mode in the markup document view on iOS 17. - Type - Fix - ImageName - wrench - - - Title - Open ownCloud Links in App - Subtitle - We have resolved the issue with opening private links from third-party apps. - Type - Fix - ImageName - wrench - - - Title - Bug Fixes - Subtitle - We have addressed various issues with the File Provider and the app itself. - Type - Fix - ImageName - wrench - - - diff --git a/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-1024x1024.png b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-1024x1024.png new file mode 100644 index 000000000..2bddda788 Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-1024x1024.png differ diff --git a/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-120x120.png b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-120x120.png new file mode 100644 index 000000000..15322073b Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-120x120.png differ diff --git a/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-152x152.png b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-152x152.png new file mode 100644 index 000000000..dbc6b8aab Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-152x152.png differ diff --git a/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-167x167.png b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-167x167.png new file mode 100644 index 000000000..a026e7e48 Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-167x167.png differ diff --git a/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-180x180.png b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-180x180.png new file mode 100644 index 000000000..bb66bbb03 Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-180x180.png differ diff --git a/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-20x20.png b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-20x20.png new file mode 100644 index 000000000..6bdb42926 Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-20x20.png differ diff --git a/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-29x29.png b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-29x29.png new file mode 100644 index 000000000..edabadab0 Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-29x29.png differ diff --git a/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-40x40.png b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-40x40.png new file mode 100644 index 000000000..4f1613797 Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-40x40.png differ diff --git a/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-58x58.png b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-58x58.png new file mode 100644 index 000000000..8e2e27749 Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-58x58.png differ diff --git a/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-60x60.png b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-60x60.png new file mode 100644 index 000000000..475cc6d88 Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-60x60.png differ diff --git a/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-76x76.png b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-76x76.png new file mode 100644 index 000000000..0b8a3ec7a Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-76x76.png differ diff --git a/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-80x80.png b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-80x80.png new file mode 100644 index 000000000..0c29dcc18 Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-80x80.png differ diff --git a/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-87x87.png b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-87x87.png new file mode 100644 index 000000000..eca51a9c0 Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/AppIcon.appiconset/icon-1024-87x87.png differ diff --git a/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/Contents.json b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..b75f2d40f --- /dev/null +++ b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/Contents.json @@ -0,0 +1,116 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom": "iphone", + "filename" : "icon-20@2x.png", + "scale": "2x" + }, + { + "size" : "20x20", + "idiom": "iphone", + "filename" : "icon-20@3x.png", + "scale": "3x" + }, + { + "size" : "20x20", + "idiom": "ipad", + "filename" : "icon-20.png", + "scale": "1x" + }, + { + "size" : "20x20", + "idiom": "ipad", + "filename" : "icon-20@2x.png", + "scale": "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "icon-29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "icon-29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "icon-40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "icon-40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon-60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon-60@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "icon-29.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "icon-29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "icon-40.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "icon-40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon-76.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon-76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "icon-83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "icon-1024.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-1024.png b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-1024.png new file mode 100644 index 000000000..095f8d70b Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-1024.png differ diff --git a/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-20.png b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-20.png new file mode 100644 index 000000000..6507f8f4f Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-20.png differ diff --git a/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-20@2x.png b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-20@2x.png new file mode 100644 index 000000000..aac4be424 Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-20@2x.png differ diff --git a/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-20@3x.png b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-20@3x.png new file mode 100644 index 000000000..baad7533b Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-20@3x.png differ diff --git a/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-29.png b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-29.png new file mode 100644 index 000000000..0d0fd6686 Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-29.png differ diff --git a/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-29@2x.png b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-29@2x.png new file mode 100644 index 000000000..88932ee8a Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-29@2x.png differ diff --git a/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-29@3x.png b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-29@3x.png new file mode 100644 index 000000000..6f3a6966b Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-29@3x.png differ diff --git a/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-40.png b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-40.png new file mode 100644 index 000000000..aac4be424 Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-40.png differ diff --git a/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-40@2x.png b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-40@2x.png new file mode 100644 index 000000000..110363ec8 Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-40@2x.png differ diff --git a/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-40@3x.png b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-40@3x.png new file mode 100644 index 000000000..0b5cc5a7b Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-40@3x.png differ diff --git a/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-60@2x.png b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-60@2x.png new file mode 100644 index 000000000..0b5cc5a7b Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-60@2x.png differ diff --git a/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-60@3x.png b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-60@3x.png new file mode 100644 index 000000000..d6cabc294 Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-60@3x.png differ diff --git a/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-76.png b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-76.png new file mode 100644 index 000000000..36756000c Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-76.png differ diff --git a/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-76@2x.png b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-76@2x.png new file mode 100644 index 000000000..47b5f048e Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-76@2x.png differ diff --git a/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-83.5@2x.png b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-83.5@2x.png new file mode 100644 index 000000000..5ddd010df Binary files /dev/null and b/ownCloud/Resources/Assets.xcassets/iOS/AppIcon.appiconset/icon-83.5@2x.png differ diff --git a/ownCloud/Resources/LaunchScreen.storyboard b/ownCloud/Resources/LaunchScreen.storyboard index 8e974e8bb..3b88ec199 100644 --- a/ownCloud/Resources/LaunchScreen.storyboard +++ b/ownCloud/Resources/LaunchScreen.storyboard @@ -1,9 +1,9 @@ - + - + @@ -19,11 +19,10 @@ - - + + - @@ -42,6 +41,7 @@ + @@ -51,6 +51,6 @@ - + diff --git a/ownCloud/Resources/Theming/branding-assets-input.xcfilelist b/ownCloud/Resources/Theming/branding-assets-input.xcfilelist deleted file mode 100644 index 3cfca7dc3..000000000 --- a/ownCloud/Resources/Theming/branding-assets-input.xcfilelist +++ /dev/null @@ -1,7 +0,0 @@ -# List of all possible source locations - -# Default theme -${PROJECT_DIR}/ownCloud/Resources/Theming/com.owncloud.ios-app - -# branding-assets -${PROJECT_DIR}/ownCloud/Resources/Theming/branding-assets \ No newline at end of file diff --git a/ownCloud/Resources/Theming/branding-assets-output.xcfilelist b/ownCloud/Resources/Theming/branding-assets-output.xcfilelist deleted file mode 100644 index 00dd41eab..000000000 --- a/ownCloud/Resources/Theming/branding-assets-output.xcfilelist +++ /dev/null @@ -1,24 +0,0 @@ -# List of all possible files in branding-assets (target locations) - -# BrandView assets -${TARGET_BUILD_DIR}/${WRAPPER_NAME}/branding-logo.png -${TARGET_BUILD_DIR}/${WRAPPER_NAME}/branding-background.png - -# - setup variants -${TARGET_BUILD_DIR}/${WRAPPER_NAME}/branding-logo-setup.png -${TARGET_BUILD_DIR}/${WRAPPER_NAME}/branding-background-setup.png - -# - sidebar variants -${TARGET_BUILD_DIR}/${WRAPPER_NAME}/branding-logo-sidebar.png -${TARGET_BUILD_DIR}/${WRAPPER_NAME}/branding-background-sidebar.png - -# - legacy paths -${TARGET_BUILD_DIR}/${WRAPPER_NAME}/branding-login-logo.png -${TARGET_BUILD_DIR}/${WRAPPER_NAME}/branding-login-background.png - -# Splashscreen assets -${TARGET_BUILD_DIR}/${WRAPPER_NAME}/branding-splashscreen-logo.png -${TARGET_BUILD_DIR}/${WRAPPER_NAME}/branding-splashscreen-background.png - -# Sidebar link icon -${TARGET_BUILD_DIR}/${WRAPPER_NAME}/branding-sidebar-link-icon.png diff --git a/ownCloud/Resources/Theming/branding-assets/.do-not-remove b/ownCloud/Resources/Theming/branding-assets/.do-not-remove deleted file mode 100644 index e69de29bb..000000000 diff --git a/ownCloud/Resources/Theming/branding-bookmark-icon.png b/ownCloud/Resources/Theming/branding-bookmark-icon.png new file mode 100644 index 000000000..24d08707e Binary files /dev/null and b/ownCloud/Resources/Theming/branding-bookmark-icon.png differ diff --git a/ownCloud/Resources/Theming/branding-icon.png b/ownCloud/Resources/Theming/branding-icon.png new file mode 100644 index 000000000..66294a740 Binary files /dev/null and b/ownCloud/Resources/Theming/branding-icon.png differ diff --git a/ownCloud/Resources/Theming/branding-login-background.png b/ownCloud/Resources/Theming/branding-login-background.png new file mode 100644 index 000000000..52bd98b44 Binary files /dev/null and b/ownCloud/Resources/Theming/branding-login-background.png differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/branding-logo.png b/ownCloud/Resources/Theming/branding-login-logo.png similarity index 100% rename from ownCloud/Resources/Theming/com.owncloud.ios-app.emm/branding-logo.png rename to ownCloud/Resources/Theming/branding-login-logo.png diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/branding-sidebar-link-icon.png b/ownCloud/Resources/Theming/branding-sidebar-link-icon.png similarity index 100% rename from ownCloud/Resources/Theming/com.owncloud.ios-app.emm/branding-sidebar-link-icon.png rename to ownCloud/Resources/Theming/branding-sidebar-link-icon.png diff --git a/ownCloud/Resources/Theming/branding-splashscreen-background.png b/ownCloud/Resources/Theming/branding-splashscreen-background.png new file mode 100644 index 000000000..ca2b68fcf Binary files /dev/null and b/ownCloud/Resources/Theming/branding-splashscreen-background.png differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/branding-splashscreen-logo.png b/ownCloud/Resources/Theming/branding-splashscreen.png similarity index 100% rename from ownCloud/Resources/Theming/com.owncloud.ios-app.emm/branding-splashscreen-logo.png rename to ownCloud/Resources/Theming/branding-splashscreen.png diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/Contents.json b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..770379d94 --- /dev/null +++ b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,116 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "icon-20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "icon-20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "icon-29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "icon-29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "icon-40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "icon-40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon-60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon-60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "icon-20.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "icon-20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "icon-29.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "icon-29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "icon-40.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "icon-40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon-76.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon-76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "icon-83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "icon-1024.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/branding-icon.png b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-1024.png similarity index 100% rename from ownCloud/Resources/Theming/com.owncloud.ios-app.emm/branding-icon.png rename to ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-1024.png diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-20.png b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-20.png new file mode 100644 index 000000000..00f48a8db Binary files /dev/null and b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-20.png differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png new file mode 100644 index 000000000..415be8917 Binary files /dev/null and b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png new file mode 100644 index 000000000..e06a34160 Binary files /dev/null and b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-29.png b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-29.png new file mode 100644 index 000000000..10d288c08 Binary files /dev/null and b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-29.png differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png new file mode 100644 index 000000000..c7009e370 Binary files /dev/null and b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png new file mode 100644 index 000000000..d1d090968 Binary files /dev/null and b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-40.png b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-40.png new file mode 100644 index 000000000..415be8917 Binary files /dev/null and b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-40.png differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png new file mode 100644 index 000000000..46621e254 Binary files /dev/null and b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png new file mode 100644 index 000000000..90f20f466 Binary files /dev/null and b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png new file mode 100644 index 000000000..90f20f466 Binary files /dev/null and b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png new file mode 100644 index 000000000..060f21f82 Binary files /dev/null and b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-76.png b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-76.png new file mode 100644 index 000000000..e50667f14 Binary files /dev/null and b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-76.png differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png new file mode 100644 index 000000000..104d696f2 Binary files /dev/null and b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png new file mode 100644 index 000000000..fed0a2898 Binary files /dev/null and b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/branding-background.png b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/branding-background.png deleted file mode 100644 index db7653966..000000000 Binary files a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/branding-background.png and /dev/null differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/branding-splashscreen-background.png b/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/branding-splashscreen-background.png deleted file mode 100644 index d07c4dbf6..000000000 Binary files a/ownCloud/Resources/Theming/com.owncloud.ios-app.emm/branding-splashscreen-background.png and /dev/null differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app/branding-background.png b/ownCloud/Resources/Theming/com.owncloud.ios-app/branding-background.png deleted file mode 100644 index db7653966..000000000 Binary files a/ownCloud/Resources/Theming/com.owncloud.ios-app/branding-background.png and /dev/null differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app/branding-icon.png b/ownCloud/Resources/Theming/com.owncloud.ios-app/branding-icon.png deleted file mode 100644 index 33d9e8b6d..000000000 Binary files a/ownCloud/Resources/Theming/com.owncloud.ios-app/branding-icon.png and /dev/null differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app/branding-logo.png b/ownCloud/Resources/Theming/com.owncloud.ios-app/branding-logo.png deleted file mode 100644 index 791a812af..000000000 Binary files a/ownCloud/Resources/Theming/com.owncloud.ios-app/branding-logo.png and /dev/null differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app/branding-sidebar-link-icon.png b/ownCloud/Resources/Theming/com.owncloud.ios-app/branding-sidebar-link-icon.png deleted file mode 100644 index 791a812af..000000000 Binary files a/ownCloud/Resources/Theming/com.owncloud.ios-app/branding-sidebar-link-icon.png and /dev/null differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app/branding-splashscreen-background.png b/ownCloud/Resources/Theming/com.owncloud.ios-app/branding-splashscreen-background.png deleted file mode 100644 index d07c4dbf6..000000000 Binary files a/ownCloud/Resources/Theming/com.owncloud.ios-app/branding-splashscreen-background.png and /dev/null differ diff --git a/ownCloud/Resources/Theming/com.owncloud.ios-app/branding-splashscreen-logo.png b/ownCloud/Resources/Theming/com.owncloud.ios-app/branding-splashscreen-logo.png deleted file mode 100644 index 791a812af..000000000 Binary files a/ownCloud/Resources/Theming/com.owncloud.ios-app/branding-splashscreen-logo.png and /dev/null differ diff --git a/ownCloud/Resources/Theming/generate.sh b/ownCloud/Resources/Theming/generate.sh deleted file mode 100755 index 9059cf5ae..000000000 --- a/ownCloud/Resources/Theming/generate.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -# PREREQUISITE -# Create symlink -# ln -s SYNCDIR\ Config\ Data/5500Z000003poZfQAI/ios/current ~/Developer/github.com/owncloud/ios-app/ownCloud/Resources/Theming/theme.damken - -current_dir=$(pwd) -theming_dir="/ownCloud/Resources/Theming" -theme=$1 - -if [ -d "$theming_dir" ]; then - git submodule init - git submodule update - - rename 's/current./theme./' $current_dir$theming_dir/*.* - mv $current_dir$theming_dir/theme.$theme $current_dir$theming_dir/current.$theme - - cp $current_dir$theming_dir/current*/*.png $current_dir$theming_dir/ - cp $current_dir$theming_dir/current*/*.json $current_dir$theming_dir/Branding.json - - fastlane generate_appicon - - gomplate --file ./tools/gomplate/Branding.plist.tmpl \ - --context config=$current_dir$theming_dir/Branding.json \ - --out $current_dir$theming_dir/Branding.plist -else - echo "Directory $theming_dir does not exist. Please execute this script in the root path of the ios-app repository." -fi \ No newline at end of file diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/Contents.json b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..770379d94 --- /dev/null +++ b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,116 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "icon-20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "icon-20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "icon-29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "icon-29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "icon-40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "icon-40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon-60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon-60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "icon-20.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "icon-20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "icon-29.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "icon-29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "icon-40.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "icon-40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon-76.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon-76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "icon-83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "icon-1024.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/branding-icon.png b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-1024.png similarity index 100% rename from ownCloud/Resources/Theming/online.owncloud.ios-app/branding-icon.png rename to ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-1024.png diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-20.png b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-20.png new file mode 100644 index 000000000..8efbb519b Binary files /dev/null and b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-20.png differ diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png new file mode 100644 index 000000000..dad04e3d9 Binary files /dev/null and b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png differ diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png new file mode 100644 index 000000000..5d70c3675 Binary files /dev/null and b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png differ diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-29.png b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-29.png new file mode 100644 index 000000000..bac72d87b Binary files /dev/null and b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-29.png differ diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png new file mode 100644 index 000000000..f9a9652e5 Binary files /dev/null and b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png differ diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png new file mode 100644 index 000000000..c78bfbeb0 Binary files /dev/null and b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png differ diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-40.png b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-40.png new file mode 100644 index 000000000..dad04e3d9 Binary files /dev/null and b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-40.png differ diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png new file mode 100644 index 000000000..3d269139d Binary files /dev/null and b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png differ diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png new file mode 100644 index 000000000..3afa83291 Binary files /dev/null and b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png differ diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png new file mode 100644 index 000000000..3afa83291 Binary files /dev/null and b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png differ diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png new file mode 100644 index 000000000..b3ca62124 Binary files /dev/null and b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png differ diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-76.png b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-76.png new file mode 100644 index 000000000..15b54ed2d Binary files /dev/null and b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-76.png differ diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png new file mode 100644 index 000000000..6b7f351df Binary files /dev/null and b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png differ diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png new file mode 100644 index 000000000..41fa57b3d Binary files /dev/null and b/ownCloud/Resources/Theming/online.owncloud.ios-app/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png differ diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/Branding.plist b/ownCloud/Resources/Theming/online.owncloud.ios-app/Branding.plist index 5c3d47477..a75004c80 100644 --- a/ownCloud/Resources/Theming/online.owncloud.ios-app/Branding.plist +++ b/ownCloud/Resources/Theming/online.owncloud.ios-app/Branding.plist @@ -10,53 +10,598 @@ branding.organization-name ownCloud Online + branding.send-feedback-address + branding.profile-definitions - allowedHosts - - owncloud.online - owncloud.com - owncloud.team - owncloud.works - owncloud.org - - bookmarkName - ownCloud Online - canConfigureURL - - helpURL - https://owncloud.online/try/ - helpURLButtonString - TRY IT FOR FREE identifier ownCloud-online name ownCloud Online - promptForHelpURL - If you do not have an ownCloud Online account yet, you can request a free test account. promptForURL Please enter your ownCloud Online URL + promptForHelpURL + If you do not have an ownCloud Online account yet, you can request a free test account. + helpURLButtonString + TRY IT FOR FREE + bookmarkName + ownCloud Online url + canConfigureURL + + helpURL + https://owncloud.online/try/ + allowedHosts + + owncloud.online + owncloud.com + owncloud.team + + allowedAuthenticationMethods + + com.owncloud.basicauth + com.owncloud.oauth2 + - branding.send-feedback-address - - branding.theme-colors - - branding-background-color - #628a99 - setup-status-bar-style - black - folder-icon-color - #52DDA9 - file-icon-color - #52DDA9 - branding.url-help https://owncloud.online/faq/ branding.url-privacy https://owncloud.online/privacy-policy/ + branding.theme-generic-colors + + Corporate + + Color + #52DDA9 + + Action + + Primary + #1279C5 + Inverse + #FFFFFF + Secondary + #777777 + + Text + + Primary + #333333 + Inverse + #000000 + Secondary + #666666 + Inverse-Light + #000000 + Disabled + #BFC9D9 + + Login + + Primary + #333333 + Inverse + #FFFFFF + Secondary + #666666 + Inverse-Light + #F2F4F7 + Disabled + #BFC9D9 + + Background + + Standard + #FFFFFF + Light + #EEEEEE + Input-Form + #FFFFFF + Selected + #E5EFFF + Tooltip + #1F2939 + + System + + success + #4CD964 + success-background + #DBF7E0 + warning + #FF8800 + warning-background + #FFE7CC + danger + #E00000 + danger-background + #F9CCCC + + Status + + Progress-Indicator + #7357C7 + Progress-Background + #D5D3DC + + Icon + + System + #667FA3 + System-Light + #CCD4E0 + Filetype-Normal + #00af90 + Disabled + #C4C4C4 + + Tab + + Active + #00af90 + Inactive + #777777 + + + branding.theme-definitions + + + Name + ownCloud-online + Identifier + com.owncloud.branding + ThemeStyle + contrast + darkBrandColor + #52DDA9 + lightBrandColor + #628a99 + Colors + + tintColor + #000000 + Label + + informativeColor + + successColor + System.Success + warningColor + System.Warning + errorColor + System.Danger + + Fill + + approvalColors + + normal + + background + #52DDA9 + foreground + + + highlighted + + background + #52DDA9 + foreground + + + disabled + + background + #37C390 + foreground + + + + neutralColors + + normal + + background + + foreground + + + highlighted + + background + + foreground + + + disabled + + background + + foreground + + + + destructiveColors + + normal + + background + + foreground + + + highlighted + + background + + foreground + + + disabled + + background + + foreground + + + + + Favorite + + enabledColor + + disabledColor + + + Table + + tableBackgroundColor + Background.Standard + tableGroupBackgroundColor + + tableSeparatorColor + + tableRowBorderColor + + tableRowColors + + backgroundColor + Background.Standard + labelColor + Text.Primary + secondaryLabelColor + Text.Secondary + symbolColor + Action.Primary + tintColor + + filledColorPairCollection + + normal + + background + + foreground + + + highlighted + + background + + foreground + + + disabled + + background + + foreground + + + + + tableRowHighlightColors + + backgroundColor + #DCEBF6 + labelColor + + secondaryLabelColor + + symbolColor + + tintColor + + filledColorPairCollection + + normal + + background + + foreground + + + highlighted + + background + + foreground + + + disabled + + background + + foreground + + + + + + Icon + + folderFillColor + Icon.Filetype-Normal + fileFillColor + Icon.Filetype-Normal + logoFillColor + Icon.Filetype-Normal + iconFillColor + Icon.Filetype-Normal + symbolFillColor + Icon.Filetype-Normal + + Progress + + foreground + Progress.Indicator + background + Progress.Background + + Toolbar + + backgroundColor + Background.Standard + labelColor + Text.Inverse + secondaryLabelColor + Tab.Inactive + symbolColor + + tintColor + Tab.Active + filledColorPairCollection + + normal + + background + + foreground + Tab.Inactive + + highlighted + + background + + foreground + + + disabled + + background + + foreground + + + + + Searchbar + + backgroundColor + Background.Input-Form + labelColor + Text.Inverse + secondaryLabelColor + Text.Secondary + symbolColor + + tintColor + Text.Inverse + filledColorPairCollection + + normal + + background + + foreground + + + highlighted + + background + + foreground + + + disabled + + background + + foreground + + + + + Login + + backgroundColor + Background.Standard + labelColor + Login.Primary + secondaryLabelColor + Login.Secondary + symbolColor + + tintColor + Login.Inverse + filledColorPairCollection + + normal + + background + + foreground + #000000 + + highlighted + + background + + foreground + + + disabled + + background + + foreground + + + + + NavigationBar + + backgroundColor + #FFFFFF + labelColor + Text.Inverse + secondaryLabelColor + + symbolColor + + tintColor + Text.Inverse-Light + filledColorPairCollection + + normal + + background + + foreground + + + highlighted + + background + + foreground + + + disabled + + background + + foreground + + + + + darkBrandColors + + backgroundColor + + labelColor + + secondaryLabelColor + + symbolColor + + tintColor + + filledColorPairCollection + + normal + + background + + foreground + + + highlighted + + background + + foreground + + + disabled + + background + + foreground + + + + + lightBrandColors + + backgroundColor + + labelColor + + secondaryLabelColor + + symbolColor + + tintColor + + filledColorPairCollection + + normal + + background + + foreground + + + highlighted + + background + + foreground + + + disabled + + background + + foreground + + + + + + Styles + + statusBarStyle + darkContent + barStyle + black + activityIndicatorViewStyle + gray + searchBarActivityIndicatorViewStyle + white + interfaceStyle + light + keyboardAppearance + light + backgroundBlurEffectStyle + light + + + diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/branding-background.png b/ownCloud/Resources/Theming/online.owncloud.ios-app/branding-login-background.png similarity index 100% rename from ownCloud/Resources/Theming/online.owncloud.ios-app/branding-background.png rename to ownCloud/Resources/Theming/online.owncloud.ios-app/branding-login-background.png diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/branding-logo.png b/ownCloud/Resources/Theming/online.owncloud.ios-app/branding-login-logo.png similarity index 100% rename from ownCloud/Resources/Theming/online.owncloud.ios-app/branding-logo.png rename to ownCloud/Resources/Theming/online.owncloud.ios-app/branding-login-logo.png diff --git a/ownCloud/Resources/Theming/online.owncloud.ios-app/branding-splashscreen-logo.png b/ownCloud/Resources/Theming/online.owncloud.ios-app/branding-splashscreen.png similarity index 100% rename from ownCloud/Resources/Theming/online.owncloud.ios-app/branding-splashscreen-logo.png rename to ownCloud/Resources/Theming/online.owncloud.ios-app/branding-splashscreen.png diff --git a/ownCloud/Resources/ar.lproj/InfoPlist.strings b/ownCloud/Resources/ar.lproj/InfoPlist.strings index 2dda65d31..afbc56cdc 100644 Binary files a/ownCloud/Resources/ar.lproj/InfoPlist.strings and b/ownCloud/Resources/ar.lproj/InfoPlist.strings differ diff --git a/ownCloud/Resources/ar.lproj/Localizable.strings b/ownCloud/Resources/ar.lproj/Localizable.strings index 63be839a8..ec56f0246 100644 Binary files a/ownCloud/Resources/ar.lproj/Localizable.strings and b/ownCloud/Resources/ar.lproj/Localizable.strings differ diff --git a/ownCloud/Resources/bg_BG.lproj/InfoPlist.strings b/ownCloud/Resources/bg_BG.lproj/InfoPlist.strings index 76efdf907..5ee67e4b6 100644 Binary files a/ownCloud/Resources/bg_BG.lproj/InfoPlist.strings and b/ownCloud/Resources/bg_BG.lproj/InfoPlist.strings differ diff --git a/ownCloud/Resources/bg_BG.lproj/Localizable.strings b/ownCloud/Resources/bg_BG.lproj/Localizable.strings index e48364fce..f6286b178 100644 Binary files a/ownCloud/Resources/bg_BG.lproj/Localizable.strings and b/ownCloud/Resources/bg_BG.lproj/Localizable.strings differ diff --git a/ownCloud/Resources/de-DE.lproj/InfoPlist.strings b/ownCloud/Resources/de-DE.lproj/InfoPlist.strings index 1b78abc6d..ca2233854 100644 Binary files a/ownCloud/Resources/de-DE.lproj/InfoPlist.strings and b/ownCloud/Resources/de-DE.lproj/InfoPlist.strings differ diff --git a/ownCloud/Resources/de-DE.lproj/Localizable.strings b/ownCloud/Resources/de-DE.lproj/Localizable.strings index 903237734..2930d8c17 100644 Binary files a/ownCloud/Resources/de-DE.lproj/Localizable.strings and b/ownCloud/Resources/de-DE.lproj/Localizable.strings differ diff --git a/ownCloud/Resources/de.lproj/InfoPlist.strings b/ownCloud/Resources/de.lproj/InfoPlist.strings index 1b78abc6d..ca2233854 100644 Binary files a/ownCloud/Resources/de.lproj/InfoPlist.strings and b/ownCloud/Resources/de.lproj/InfoPlist.strings differ diff --git a/ownCloud/Resources/de.lproj/Localizable.strings b/ownCloud/Resources/de.lproj/Localizable.strings index 7b8e9542b..df7c44913 100644 Binary files a/ownCloud/Resources/de.lproj/Localizable.strings and b/ownCloud/Resources/de.lproj/Localizable.strings differ diff --git a/ownCloud/Resources/de_CH.lproj/InfoPlist.strings b/ownCloud/Resources/de_CH.lproj/InfoPlist.strings index 31069d00f..69d989e7c 100644 Binary files a/ownCloud/Resources/de_CH.lproj/InfoPlist.strings and b/ownCloud/Resources/de_CH.lproj/InfoPlist.strings differ diff --git a/ownCloud/Resources/el.lproj/InfoPlist.strings b/ownCloud/Resources/el.lproj/InfoPlist.strings index 453295626..91a17eac5 100644 Binary files a/ownCloud/Resources/el.lproj/InfoPlist.strings and b/ownCloud/Resources/el.lproj/InfoPlist.strings differ diff --git a/ownCloud/Resources/en-GB.lproj/InfoPlist.strings b/ownCloud/Resources/en-GB.lproj/InfoPlist.strings index 4e2788526..e97ffac19 100644 Binary files a/ownCloud/Resources/en-GB.lproj/InfoPlist.strings and b/ownCloud/Resources/en-GB.lproj/InfoPlist.strings differ diff --git a/ownCloud/Resources/en-GB.lproj/Localizable.strings b/ownCloud/Resources/en-GB.lproj/Localizable.strings index a5657cadc..f0789809d 100644 Binary files a/ownCloud/Resources/en-GB.lproj/Localizable.strings and b/ownCloud/Resources/en-GB.lproj/Localizable.strings differ diff --git a/ownCloud/Resources/en.lproj/Localizable.strings b/ownCloud/Resources/en.lproj/Localizable.strings index a8e5cbba8..fdbe1486b 100644 --- a/ownCloud/Resources/en.lproj/Localizable.strings +++ b/ownCloud/Resources/en.lproj/Localizable.strings @@ -129,8 +129,6 @@ "{{itemCount}} items with {{totalSize}} total ({{fileCount}} files, {{folderCount}} folders)" = "{{itemCount}} items with {{totalSize}} total ({{fileCount}} files, {{folderCount}} folders)"; "{{remaining}} available" = "{{remaining}} available"; -"Loading…" = "Loading…"; - "Show more results" = "Show more results"; "An error occurred" = "An error occurred"; @@ -168,12 +166,6 @@ "Welcome to %@" = "Welcome to %@"; "Please enter a server URL" = "Please enter a server URL"; "Please pick a profile to begin setup" = "Please pick a profile to begin setup"; -"The following steps will guide you through the setup process." = "The following steps will guide you through the setup process."; -"Start setup" = "Start setup"; -"Open login page" = "Open login page"; -"If you 'Continue', you will be prompted to allow the '{{app.name}}' app to open the login page where you can enter your credentials." = "If you 'Continue', you will be prompted to allow the '{{app.name}}' app to open the login page where you can enter your credentials."; -"Account setup complete" = "Account setup complete"; -"If you'd like to give the account a custom name, please enter it below:" = "If you'd like to give the account a custom name, please enter it below:"; /* Single Account */ "You are connected as\n%@" = "You are connected as\n%@"; @@ -631,8 +623,6 @@ "Add" = "Add"; "Save changes" = "Save changes"; -"Enter password" = "Enter password"; - /* Quick Access view */ "Quick Access" = "Quick Access"; "Collection" = "Collection"; @@ -870,10 +860,6 @@ "File Provider access has been disabled by the administrator. Please use the app to create new folders." = "File Provider access has been disabled by the administrator. Please use the app to create new folders."; "File Provider access has been disabled by the administrator. Please use the share extension to import files." = "File Provider access has been disabled by the administrator. Please use the share extension to import files."; -/* - No account */ -"No account has been set up in the {{app.name}} app yet." = "No account has been set up in the {{app.name}} app yet."; -"Open app" = "Open app"; - /* Disallowed Import Methods */ /* - Share Extension */ "Share Extension disabled" = "Share Extension disabled"; diff --git a/ownCloud/Resources/es.lproj/InfoPlist.strings b/ownCloud/Resources/es.lproj/InfoPlist.strings index 7644890d6..117bed35b 100644 Binary files a/ownCloud/Resources/es.lproj/InfoPlist.strings and b/ownCloud/Resources/es.lproj/InfoPlist.strings differ diff --git a/ownCloud/Resources/es.lproj/Localizable.strings b/ownCloud/Resources/es.lproj/Localizable.strings index e7ca61894..bb225df4c 100644 Binary files a/ownCloud/Resources/es.lproj/Localizable.strings and b/ownCloud/Resources/es.lproj/Localizable.strings differ diff --git a/ownCloud/Resources/et_EE.lproj/Localizable.strings b/ownCloud/Resources/et_EE.lproj/Localizable.strings index b9411f488..59572d788 100644 Binary files a/ownCloud/Resources/et_EE.lproj/Localizable.strings and b/ownCloud/Resources/et_EE.lproj/Localizable.strings differ diff --git a/ownCloud/Resources/fr.lproj/InfoPlist.strings b/ownCloud/Resources/fr.lproj/InfoPlist.strings index 871fc4f8a..f43ade8c6 100644 Binary files a/ownCloud/Resources/fr.lproj/InfoPlist.strings and b/ownCloud/Resources/fr.lproj/InfoPlist.strings differ diff --git a/ownCloud/Resources/fr.lproj/Localizable.strings b/ownCloud/Resources/fr.lproj/Localizable.strings index bd1b3d7ba..7900e732d 100644 Binary files a/ownCloud/Resources/fr.lproj/Localizable.strings and b/ownCloud/Resources/fr.lproj/Localizable.strings differ diff --git a/ownCloud/Resources/gl.lproj/InfoPlist.strings b/ownCloud/Resources/gl.lproj/InfoPlist.strings index d6b12ca14..f6682892d 100644 Binary files a/ownCloud/Resources/gl.lproj/InfoPlist.strings and b/ownCloud/Resources/gl.lproj/InfoPlist.strings differ diff --git a/ownCloud/Resources/gl.lproj/Localizable.strings b/ownCloud/Resources/gl.lproj/Localizable.strings index 72ffa0027..3bc439d2b 100644 Binary files a/ownCloud/Resources/gl.lproj/Localizable.strings and b/ownCloud/Resources/gl.lproj/Localizable.strings differ diff --git a/ownCloud/Resources/he.lproj/InfoPlist.strings b/ownCloud/Resources/he.lproj/InfoPlist.strings index 0257cff0e..8a9541062 100644 Binary files a/ownCloud/Resources/he.lproj/InfoPlist.strings and b/ownCloud/Resources/he.lproj/InfoPlist.strings differ diff --git a/ownCloud/Resources/ko.lproj/InfoPlist.strings b/ownCloud/Resources/ko.lproj/InfoPlist.strings index 9a547b65e..257dc025a 100644 Binary files a/ownCloud/Resources/ko.lproj/InfoPlist.strings and b/ownCloud/Resources/ko.lproj/InfoPlist.strings differ diff --git a/ownCloud/Resources/ko.lproj/Localizable.strings b/ownCloud/Resources/ko.lproj/Localizable.strings index df8c21207..32d205481 100644 Binary files a/ownCloud/Resources/ko.lproj/Localizable.strings and b/ownCloud/Resources/ko.lproj/Localizable.strings differ diff --git a/ownCloud/Resources/pt-BR.lproj/InfoPlist.strings b/ownCloud/Resources/pt-BR.lproj/InfoPlist.strings index 9d54dfa13..47b708027 100644 Binary files a/ownCloud/Resources/pt-BR.lproj/InfoPlist.strings and b/ownCloud/Resources/pt-BR.lproj/InfoPlist.strings differ diff --git a/ownCloud/Resources/pt-BR.lproj/Localizable.strings b/ownCloud/Resources/pt-BR.lproj/Localizable.strings index 2358a1f95..858b96e46 100644 Binary files a/ownCloud/Resources/pt-BR.lproj/Localizable.strings and b/ownCloud/Resources/pt-BR.lproj/Localizable.strings differ diff --git a/ownCloud/Resources/ru.lproj/InfoPlist.strings b/ownCloud/Resources/ru.lproj/InfoPlist.strings index a021513a8..04d32c0d6 100644 Binary files a/ownCloud/Resources/ru.lproj/InfoPlist.strings and b/ownCloud/Resources/ru.lproj/InfoPlist.strings differ diff --git a/ownCloud/Resources/ru.lproj/Localizable.strings b/ownCloud/Resources/ru.lproj/Localizable.strings index 7771f1eae..ed95dde9a 100644 Binary files a/ownCloud/Resources/ru.lproj/Localizable.strings and b/ownCloud/Resources/ru.lproj/Localizable.strings differ diff --git a/ownCloud/Resources/sq.lproj/InfoPlist.strings b/ownCloud/Resources/sq.lproj/InfoPlist.strings index f7508c4e3..13c3d54d3 100644 Binary files a/ownCloud/Resources/sq.lproj/InfoPlist.strings and b/ownCloud/Resources/sq.lproj/InfoPlist.strings differ diff --git a/ownCloud/Resources/sq.lproj/Localizable.strings b/ownCloud/Resources/sq.lproj/Localizable.strings index dfacce0e9..cb3fcc68a 100644 Binary files a/ownCloud/Resources/sq.lproj/Localizable.strings and b/ownCloud/Resources/sq.lproj/Localizable.strings differ diff --git a/ownCloud/Resources/th-TH.lproj/InfoPlist.strings b/ownCloud/Resources/th-TH.lproj/InfoPlist.strings index 9f50e3a4a..bf930021f 100644 Binary files a/ownCloud/Resources/th-TH.lproj/InfoPlist.strings and b/ownCloud/Resources/th-TH.lproj/InfoPlist.strings differ diff --git a/ownCloud/Resources/th-TH.lproj/Localizable.strings b/ownCloud/Resources/th-TH.lproj/Localizable.strings index 24450ee70..e8fafc7f4 100644 Binary files a/ownCloud/Resources/th-TH.lproj/Localizable.strings and b/ownCloud/Resources/th-TH.lproj/Localizable.strings differ diff --git a/ownCloud/Resources/tr.lproj/InfoPlist.strings b/ownCloud/Resources/tr.lproj/InfoPlist.strings index bc8b585ab..00de75866 100644 Binary files a/ownCloud/Resources/tr.lproj/InfoPlist.strings and b/ownCloud/Resources/tr.lproj/InfoPlist.strings differ diff --git a/ownCloud/Resources/tr.lproj/Localizable.strings b/ownCloud/Resources/tr.lproj/Localizable.strings index 9b8223e8b..825884800 100644 Binary files a/ownCloud/Resources/tr.lproj/Localizable.strings and b/ownCloud/Resources/tr.lproj/Localizable.strings differ diff --git a/ownCloud/Resources/zh-Hans.lproj/InfoPlist.strings b/ownCloud/Resources/zh-Hans.lproj/InfoPlist.strings index 76e7fe67b..0efdfb133 100644 Binary files a/ownCloud/Resources/zh-Hans.lproj/InfoPlist.strings and b/ownCloud/Resources/zh-Hans.lproj/InfoPlist.strings differ diff --git a/ownCloud/Resources/zh_TW.lproj/InfoPlist.strings b/ownCloud/Resources/zh_TW.lproj/InfoPlist.strings index c919b9641..f10856a05 100644 Binary files a/ownCloud/Resources/zh_TW.lproj/InfoPlist.strings and b/ownCloud/Resources/zh_TW.lproj/InfoPlist.strings differ diff --git a/ownCloud/Resources/zh_TW.lproj/Localizable.strings b/ownCloud/Resources/zh_TW.lproj/Localizable.strings index 49a347ef8..0294e7653 100644 Binary files a/ownCloud/Resources/zh_TW.lproj/Localizable.strings and b/ownCloud/Resources/zh_TW.lproj/Localizable.strings differ diff --git a/ownCloud/SceneDelegate.swift b/ownCloud/SceneDelegate.swift index 408875bc0..51487ec75 100644 --- a/ownCloud/SceneDelegate.swift +++ b/ownCloud/SceneDelegate.swift @@ -51,11 +51,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { window = ThemeWindow(windowScene: windowScene) window?.rootViewController = appRootViewController - if #available(iOS 16, *) { - // From the console: "Manually adding the rootViewController's view to the view hierarchy is no longer supported. Please allow UIWindow to add the rootViewController's view to the view hierarchy itself." - } else { - window?.addSubview(appRootViewController.view) - } + window?.addSubview(appRootViewController.view) window?.makeKeyAndVisible() } diff --git a/ownCloud/Server List/ServerListBookmarkCell.swift b/ownCloud/Server List/ServerListBookmarkCell.swift new file mode 100644 index 000000000..89dbefed1 --- /dev/null +++ b/ownCloud/Server List/ServerListBookmarkCell.swift @@ -0,0 +1,190 @@ +// +// ServerListBookmarkCell.swift +// ownCloud +// +// Created by Felix Schwarz on 08.03.18. +// Copyright © 2018 ownCloud GmbH. All rights reserved. +// + +/* + * Copyright (C) 2018, ownCloud GmbH. + * + * This code is covered by the GNU Public License Version 3. + * + * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ + * You should have received a copy of this license along with this program. If not, see . + * + */ + +import UIKit +import ownCloudSDK +import ownCloudApp +import ownCloudAppShared + +class ServerListBookmarkCell : ThemeTableViewCell { + static private let iconSideLength : CGFloat = 40 + + public var titleLabel : UILabel = UILabel() + public var detailLabel : UILabel = UILabel() + public var logoFallbackView : UIImageView = UIImageView() + public var iconView : ResourceViewHost = ResourceViewHost(fallbackSize: CGSize(width: ServerListBookmarkCell.iconSideLength, height: ServerListBookmarkCell.iconSideLength)) + public var infoView : UIView = UIView() + + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + prepareViewAndConstraints() + } + + public required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + func prepareViewAndConstraints() { + self.selectionStyle = .default + + PointerEffect.install(on: self.contentView, effectStyle: .hover) + + titleLabel.translatesAutoresizingMaskIntoConstraints = false + detailLabel.translatesAutoresizingMaskIntoConstraints = false + iconView.translatesAutoresizingMaskIntoConstraints = false + logoFallbackView.translatesAutoresizingMaskIntoConstraints = false + infoView.translatesAutoresizingMaskIntoConstraints = false + + logoFallbackView.contentMode = .scaleAspectFit + logoFallbackView.image = Branding.shared.brandedImageNamed(.bookmarkIcon) + + iconView.fallbackView = logoFallbackView + + titleLabel.font = UIFont.preferredFont(forTextStyle: .headline) + titleLabel.adjustsFontForContentSizeCategory = true + + detailLabel.font = UIFont.preferredFont(forTextStyle: .subheadline) + detailLabel.adjustsFontForContentSizeCategory = true + + detailLabel.textColor = UIColor.gray + + contentView.addSubview(titleLabel) + contentView.addSubview(detailLabel) + contentView.addSubview(iconView) + contentView.addSubview(infoView) + + NSLayoutConstraint.activate([ + iconView.widthAnchor.constraint(equalToConstant: ServerListBookmarkCell.iconSideLength), + iconView.heightAnchor.constraint(equalToConstant: ServerListBookmarkCell.iconSideLength), + iconView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), + + iconView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), + iconView.trailingAnchor.constraint(equalTo: titleLabel.leadingAnchor, constant: -25), + iconView.trailingAnchor.constraint(equalTo: detailLabel.leadingAnchor, constant: -25), + + titleLabel.trailingAnchor.constraint(equalTo: infoView.leadingAnchor), + titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 20), + titleLabel.bottomAnchor.constraint(equalTo: detailLabel.topAnchor, constant: -5), + + detailLabel.trailingAnchor.constraint(equalTo: infoView.leadingAnchor), + detailLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -20), + + infoView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 20), + infoView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -20), + infoView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20) + ]) + + infoView.setContentHuggingPriority(.required, for: .horizontal) + logoFallbackView.setContentHuggingPriority(.required, for: .vertical) + titleLabel.setContentCompressionResistancePriority(.defaultHigh, for: .vertical) + detailLabel.setContentCompressionResistancePriority(.defaultHigh, for: .vertical) + + Theme.shared.add(tvgResourceFor: "owncloud-logo") + + NotificationCenter.default.addObserver(self, selector: #selector(ServerListBookmarkCell.updateMessageBadgeFrom(notification:)), name: .BookmarkMessageCountChanged, object: nil) + } + + deinit { + NotificationCenter.default.removeObserver(self, name: .BookmarkMessageCountChanged, object: nil) + } + + // MARK: - Content updates + var messageSelector : MessageSelector? + var directMessageCountTrackingEnabled : Bool = false + var bookmark : OCBookmark? { + didSet { + if let bookmark = bookmark { + titleLabel.text = bookmark.shortName + detailLabel.text = bookmark.url?.absoluteString + accessibilityIdentifier = "server-bookmark-cell" + + iconView.activeViewProvider = bookmark.avatar + + if directMessageCountTrackingEnabled { + messageSelector = MessageSelector(from: .global, filter: { (message) -> Bool in + return (message.bookmarkUUID == bookmark.uuid) && !message.resolved + }, handler: { [weak self] (messages, _, _) in + OnMainThread { + self?.updateMessageBadge(count: (messages != nil) ? messages!.count : 0) + } + }) + } + } else { + if directMessageCountTrackingEnabled { + messageSelector = nil + } + } + } + } + + // MARK: - Message Badge + private var badgeLabel : RoundedLabel? + + func updateMessageBadge(count: Int) { + if count > 0 { + if badgeLabel == nil { + badgeLabel = RoundedLabel(text: "", style: .token) + badgeLabel?.translatesAutoresizingMaskIntoConstraints = false + + if let badgeLabel = badgeLabel { + infoView.addSubview(badgeLabel) + + NSLayoutConstraint.activate([ + badgeLabel.leadingAnchor.constraint(equalTo: infoView.leadingAnchor, constant: 20), + badgeLabel.trailingAnchor.constraint(equalTo: infoView.trailingAnchor), + badgeLabel.centerYAnchor.constraint(equalTo: infoView.centerYAnchor) + ]) + } + } + + badgeLabel?.labelText = "\(count)" + } else { + badgeLabel?.removeFromSuperview() + badgeLabel = nil + } + } + + @objc func updateMessageBadgeFrom(notification: Notification) { + if let countByBookmarkUUID = notification.object as? ServerListTableViewController.ServerListTableMessageCountByUUID, let bookmarkUUID = bookmark?.uuid { + self.updateMessageBadge(count: countByBookmarkUUID[bookmarkUUID] ?? 0) + } + } + + // MARK: - Themeing + override func applyThemeCollectionToCellContents(theme: Theme, collection: ThemeCollection) { + let itemState = ThemeItemState(selected: self.isSelected) + + self.titleLabel.applyThemeCollection(collection, itemStyle: .title, itemState: itemState) + self.detailLabel.applyThemeCollection(collection, itemStyle: .message, itemState: itemState) + if !VendorServices.shared.isBranded { + self.logoFallbackView.image = self.logoFallbackView.image?.tinted(with: collection.tableRowColors.labelColor) + } + } + + override func applyThemeCollection(theme: Theme, collection: ThemeCollection, event: ThemeEvent) { + let itemState = ThemeItemState(selected: self.isSelected) + + super.applyThemeCollection(theme: theme, collection: collection, event: event) + + self.titleLabel.applyThemeCollection(collection, itemStyle: .title, itemState: itemState) + self.detailLabel.applyThemeCollection(collection, itemStyle: .message, itemState: itemState) + if !VendorServices.shared.isBranded { + self.logoFallbackView.image = self.logoFallbackView.image?.tinted(with: collection.tableRowColors.labelColor) + } + } +} diff --git a/ownCloud/Settings/UserInterfaceSettingsSection.swift b/ownCloud/Settings/UserInterfaceSettingsSection.swift index a45696611..06dd04ab4 100644 --- a/ownCloud/Settings/UserInterfaceSettingsSection.swift +++ b/ownCloud/Settings/UserInterfaceSettingsSection.swift @@ -18,7 +18,6 @@ import UIKit import ownCloudSDK -import ownCloudApp import ownCloudAppShared class UserInterfaceSettingsSection: SettingsSection { @@ -36,7 +35,7 @@ class UserInterfaceSettingsSection: SettingsSection { self?.pushThemeStyleSelector() }, title: "Theme".localized, value: ThemeStyle.displayName, accessoryType: .disclosureIndicator, identifier: "theme") - if Branding.shared.allowThemeSelection { + if !VendorServices.shared.isBranded { self.add(row: themeRow!) } @@ -84,9 +83,9 @@ class UserInterfaceSettingsSection: SettingsSection { ThemeStyle.followSystemAppearance = true themeRow?.cell?.detailTextLabel?.text = "System".localized } else if let styleIdentifier = row.value as? String, - let style = ThemeStyle.forIdentifier(styleIdentifier) { - ThemeStyle.preferredStyle = style + let style = ThemeStyle.forIdentifier(styleIdentifier), ThemeStyle.preferredStyle != style { ThemeStyle.followSystemAppearance = false + ThemeStyle.preferredStyle = style themeRow?.cell?.detailTextLabel?.text = ThemeStyle.displayName } diff --git a/ownCloud/UI Elements/ImageScrollView.swift b/ownCloud/UI Elements/ImageScrollView.swift index 999a6cbef..88b9707fa 100644 --- a/ownCloud/UI Elements/ImageScrollView.swift +++ b/ownCloud/UI Elements/ImageScrollView.swift @@ -17,17 +17,14 @@ */ import UIKit -import VisionKit -import ownCloudSDK -import ownCloudAppShared class ImageScrollView: UIScrollView { + // MARK: - Constants private let MAXIMUM_ZOOM_SCALE: CGFloat = 6.0 // MARK: - Instance Variables - private var imageView: UIImageView? - private var imageAnalysisInteraction: Any? + private var imageView: UIImageView! // MARK: - Init override init(frame: CGRect) { @@ -52,12 +49,12 @@ class ImageScrollView: UIScrollView { // MARK: - Manage Scale private func centerImage() { - guard let imageView else { + guard imageView != nil else { return } let boundsSize: CGSize = bounds.size - var frameToCenter: CGRect = imageView.frame + var frameToCenter: CGRect = imageView?.frame ?? .zero // center horizontally if frameToCenter.size.width < boundsSize.width { @@ -97,6 +94,7 @@ class ImageScrollView: UIScrollView { // MARK: - Public API extension ImageScrollView { + func updateScaleForRotation(size: CGSize) { contentSize = size setMinZoomScaleForCurrentBounds(size) @@ -108,58 +106,11 @@ extension ImageScrollView { func display(image: UIImage, inSize: CGSize) { imageView?.removeFromSuperview() - imageView = UIImageView(image: image) - guard let imageView else { return } - imageView.accessibilityIdentifier = "loaded-image-gallery" imageView.contentMode = .scaleAspectFit - addSubview(imageView) updateScaleForRotation(size: inSize) - - if imageInteractionsAllowed { - analyzeImage(image: image) - } - } - - var hasActiveImageAnalysisSelection: Bool { - if #available(iOS 16, *) { - if let interaction = imageAnalysisInteraction as? ImageAnalysisInteraction { - return interaction.selectableItemsHighlighted - } - } - - return false - } - - func analyzeImage(image: UIImage) { - if #available(iOS 16, *) { - guard ImageAnalyzer.isSupported else { - return - } - - let interaction = ImageAnalysisInteraction() - imageView?.addInteraction(interaction) - - imageAnalysisInteraction = interaction - - Task.detached(priority: .userInitiated, operation: { - do { - let configuration = ImageAnalyzer.Configuration([.machineReadableCode, .text, .visualLookUp]) - let analyzer = ImageAnalyzer() - let analysis = try await analyzer.analyze(image, configuration: configuration) - await MainActor.run { - interaction.analysis = analysis - interaction.preferredInteractionTypes = [.automatic] - } - } catch { - await MainActor.run(body: { - interaction.preferredInteractionTypes = [] - }) - } - }) - } } } @@ -174,28 +125,3 @@ extension ImageScrollView: UIScrollViewDelegate { } } - -// MARK: - Class Settings -public extension OCClassSettingsKey { - static let allowImageInteractions = OCClassSettingsKey("allow-image-interactions") -} - -extension ImageScrollView { - static func registerImageInteractionsSettings() { - Action.registerOCClassSettingsDefaults([ - .allowImageInteractions : true - ], metadata: [ - .allowImageInteractions : [ - .type : OCClassSettingsMetadataType.boolean, - .label : "Allow Image Interactions", - .description : "Allow (true) or disallow (false) text/selection/OCR interactions with images.", - .status : OCClassSettingsKeyStatus.advanced, - .category : "Actions" - ] - ]) - } - - var imageInteractionsAllowed: Bool { - return Action.classSetting(forOCClassSettingsKey: .allowImageInteractions) as? Bool ?? true - } -} diff --git a/ownCloudAppFramework/Branding/Branding.h b/ownCloudAppFramework/Branding/Branding.h index a13114906..8c7a00faa 100644 --- a/ownCloudAppFramework/Branding/Branding.h +++ b/ownCloudAppFramework/Branding/Branding.h @@ -26,7 +26,6 @@ typedef NSString* BrandingLegacyKey; typedef OCClassSettingsKey BrandingKey NS_TYPED_EXTENSIBLE_ENUM; typedef NSString* BrandingFileImportMethod NS_TYPED_EXTENSIBLE_ENUM; typedef NSString* BrandingImageName NS_TYPED_EXTENSIBLE_ENUM; -typedef NSString* BrandingAssetSuffix NS_TYPED_EXTENSIBLE_ENUM; @protocol BrandingInitialization + (void)initializeBranding; @@ -42,7 +41,6 @@ typedef NSString* BrandingAssetSuffix NS_TYPED_EXTENSIBLE_ENUM; @property(strong,nonatomic,readonly,class) Branding *sharedBranding; @property(assign,nonatomic) BOOL allowBranding; //!< YES if branding is allowed. If NO, computedValueForClassSettingsKey returns only default values. -@property(assign,nonatomic) BOOL allowThemeSelection; //!< YES if theme selection is allowed @property(strong,nullable,nonatomic,readonly) NSBundle *appBundle; //!< Bundle of the main app @@ -62,7 +60,6 @@ typedef NSString* BrandingAssetSuffix NS_TYPED_EXTENSIBLE_ENUM; - (BOOL)isImportMethodAllowed:(BrandingFileImportMethod)importMethod; - (nullable UIImage *)brandedImageNamed:(BrandingImageName)imageName; //!< Returns the respective image from the appBundle -- (nullable UIImage *)brandedImageNamed:(BrandingImageName)imageName assetSuffix:(nullable BrandingAssetSuffix)assetSuffix; //!< Returns the respective image from the appBundle, trying to retrieve a more specific asset with the provided suffix (if provided) - (nullable id)computedValueForClassSettingsKey:(OCClassSettingsKey)classSettingsKey; - (nullable NSURL *)urlForClassSettingsKey:(OCClassSettingsKey)settingsKey; diff --git a/ownCloudAppFramework/Branding/Branding.m b/ownCloudAppFramework/Branding/Branding.m index aa9c60f01..58f0bd5b7 100644 --- a/ownCloudAppFramework/Branding/Branding.m +++ b/ownCloudAppFramework/Branding/Branding.m @@ -75,7 +75,6 @@ - (instancetype)init _brandingPlistURL = [appBundle URLForResource:@"Branding" withExtension:@"plist"]; _allowBranding = YES; - _allowThemeSelection = YES; NSData *brandingPlistData; @@ -213,21 +212,6 @@ - (nullable UIImage *)brandedImageNamed:(BrandingImageName)imageName return ([UIImage imageNamed:imageName inBundle:self.appBundle compatibleWithTraitCollection:nil]); } -- (nullable UIImage *)brandedImageNamed:(BrandingImageName)imageName assetSuffix:(BrandingAssetSuffix)assetSuffix -{ - UIImage *image = nil; - - if (assetSuffix != nil) { - image = [UIImage imageNamed:[imageName stringByAppendingFormat:@"-%@", assetSuffix] inBundle:self.appBundle compatibleWithTraitCollection:nil]; - } - - if (image == nil) { - image = [UIImage imageNamed:imageName inBundle:self.appBundle compatibleWithTraitCollection:nil]; - } - - return (image); -} - - (nullable id)computedValueForClassSettingsKey:(OCClassSettingsKey)classSettingsKey { id value = nil; diff --git a/ownCloudAppFramework/Building/BuildOptions.m b/ownCloudAppFramework/Building/BuildOptions.m index edc5fa5a6..36219f607 100644 --- a/ownCloudAppFramework/Building/BuildOptions.m +++ b/ownCloudAppFramework/Building/BuildOptions.m @@ -21,7 +21,6 @@ OCClassSettingsIdentifier OCClassSettingsIdentifierBuildOptions = @"build"; OCClassSettingsKey OCClassSettingsKeyBuildFlags = @"flags"; -OCClassSettingsKey OCClassSettingsKeyVersionNumber = @"version-number"; OCClassSettingsKey OCClassSettingsKeyCustomAppScheme = @"custom-app-scheme"; OCClassSettingsKey OCClassSettingsKeyCustomAuthScheme = @"custom-auth-scheme"; OCClassSettingsKey OCClassSettingsKeyAppGroupIdentifier = @"app-group-identifier"; @@ -59,14 +58,6 @@ + (OCClassSettingsMetadataCollection)classSettingsMetadata OCClassSettingsMetadataKeyCategory : @"Build", }, - // build.version-number - OCClassSettingsKeyVersionNumber : @{ - OCClassSettingsMetadataKeyType : OCClassSettingsMetadataTypeString, - OCClassSettingsMetadataKeyDescription : @"Sets a custom version number for the app.", - OCClassSettingsMetadataKeyStatus : OCClassSettingsKeyStatusSupported, - OCClassSettingsMetadataKeyCategory : @"Build", - }, - // build.custom-app-scheme OCClassSettingsKeyCustomAppScheme : @{ OCClassSettingsMetadataKeyType : OCClassSettingsMetadataTypeString, diff --git a/ownCloudAppShared/Branding/BrandView.swift b/ownCloudAppShared/Branding/BrandView.swift deleted file mode 100644 index 7699b71d9..000000000 --- a/ownCloudAppShared/Branding/BrandView.swift +++ /dev/null @@ -1,166 +0,0 @@ -// -// BrandView.swift -// ownCloudAppShared -// -// Created by Felix Schwarz on 12.10.23. -// Copyright © 2023 ownCloud GmbH. All rights reserved. -// - -/* - * Copyright (C) 2023, ownCloud GmbH. - * - * This code is covered by the GNU Public License Version 3. - * - * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ - * You should have received a copy of this license along with this program. If not, see . - * - */ - -import UIKit -import ownCloudApp - -open class BrandView: UIView { - open var showBackground: Bool = true { - didSet { - render() - } - } - - open var showLogo: Bool = true { - didSet { - render() - } - } - open var logoMaxSize: CGSize? { - didSet { - render() - } - } - open var fitToLogo: Bool = false { - didSet { - render() - } - } - - open var roundedCorners: Bool = true { - didSet { - render() - } - } - open var assetSuffix: BrandingAssetSuffix? { - didSet { - render() - } - } - - public init(showBackground: Bool, showLogo: Bool, logoMaxSize: CGSize? = nil, fitToLogo: Bool = false, roundedCorners: Bool, assetSuffix: BrandingAssetSuffix? = nil) { - super.init(frame: CGRect(x: 0, y: 0, width: 128, height: 128)) - - translatesAutoresizingMaskIntoConstraints = false - - self.showBackground = showBackground - - self.showLogo = showLogo - self.logoMaxSize = logoMaxSize - self.fitToLogo = fitToLogo - - self.roundedCorners = roundedCorners - self.assetSuffix = assetSuffix - - self.cssSelector = .brand - - render() - } - - required public init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: - Views - private var backgroundColorView: ThemeCSSView? - private var backgroundImageView: UIImageView? - private var logoImageView: UIImageView? - - func render() { - // Create and add background views - backgroundColorView?.removeFromSuperview() - backgroundColorView = nil - - backgroundImageView?.removeFromSuperview() - backgroundImageView = nil - - if showBackground { - // Add background color - backgroundColorView = ThemeCSSView(withSelectors: [.background]) - backgroundColorView?.translatesAutoresizingMaskIntoConstraints = false - embed(toFillWith: backgroundColorView!) - - // Add background image - if let backgroundImage = Branding.shared.brandedImageNamed(.brandBackground, assetSuffix: assetSuffix) ?? Branding.shared.brandedImageNamed(.legacyBrandBackground, assetSuffix: assetSuffix) { - backgroundImageView = UIImageView(image: backgroundImage) - backgroundImageView?.translatesAutoresizingMaskIntoConstraints = false - backgroundImageView?.contentMode = .scaleAspectFill - backgroundImageView?.cssSelector = .background - backgroundImageView?.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 700), for: .horizontal) // make background image view have a smaller compression resistance than the parent view (defaults to 750), in order not to establish that the background image width does not determine the superview's width - - embed(toFillWith: backgroundImageView!) - } - - // Apply rounded corners - if roundedCorners { - let cornerRadius: CGFloat = 10 - - backgroundColorView?.layer.cornerRadius = cornerRadius - backgroundColorView?.clipsToBounds = true - - backgroundImageView?.layer.cornerRadius = cornerRadius - backgroundImageView?.clipsToBounds = true - - layer.cornerRadius = cornerRadius - clipsToBounds = true - } - } - - // Logo image view - logoImageView?.removeFromSuperview() - logoImageView = nil - - if showLogo { - if let logoImage = Branding.shared.brandedImageNamed(.brandLogo, assetSuffix: assetSuffix) ?? Branding.shared.brandedImageNamed(.legacyBrandLogo, assetSuffix: assetSuffix) { - logoImageView = UIImageView(image: logoImage) - logoImageView?.translatesAutoresizingMaskIntoConstraints = false - logoImageView?.contentMode = .scaleAspectFit - logoImageView?.accessibilityLabel = VendorServices.shared.appName - logoImageView?.cssSelector = .icon - - if let logoImageView { - // Apply aspect ratio maximum size - if let logoMaxSize { - let logoImageSize = UIImage.sizeThatFits(logoImage.size, into: logoMaxSize) - - NSLayoutConstraint.activate([ - logoImageView.widthAnchor.constraint(equalToConstant: logoImageSize.width), - logoImageView.heightAnchor.constraint(equalToConstant: logoImageSize.height) - ]) - } - - if fitToLogo { - embed(toFillWith: logoImageView) - } else { - addSubview(logoImageView) - NSLayoutConstraint.activate([ - logoImageView.centerXAnchor.constraint(equalTo: centerXAnchor), - logoImageView.centerYAnchor.constraint(equalTo: centerYAnchor) - ]) - } - } - } - } - } -} - -extension BrandView: DataItemSelectionInteraction { - public func allowSelection(in viewController: UIViewController?, section: CollectionViewSection?, with context: ClientContext?) -> Bool { - return false - } -} diff --git a/ownCloudAppShared/Branding/Branding+App.swift b/ownCloudAppShared/Branding/Branding+App.swift index ebf46832b..4f3668a6d 100644 --- a/ownCloudAppShared/Branding/Branding+App.swift +++ b/ownCloudAppShared/Branding/Branding+App.swift @@ -51,18 +51,8 @@ extension OCClassSettingsKey { public static let profileDefinitions : OCClassSettingsKey = OCClassSettingsKey("profile-definitions") // Themes - public static let themeDefinitions: OCClassSettingsKey = OCClassSettingsKey("theme-definitions") - - public static let themeColors: OCClassSettingsKey = OCClassSettingsKey("theme-colors") - public static let themeCSSRecords: OCClassSettingsKey = OCClassSettingsKey("theme-css-records") -} - -enum BrandingColorAlias: String, CaseIterable { - case tintColor = "tint-color" - case brandingBackgroundColor = "branding-background-color" - case setupStatusBarStyle = "setup-status-bar-style" - case folderIconColor = "folder-icon-color" - case fileIconColor = "file-icon-color" + public static let themeGenericColors : OCClassSettingsKey = OCClassSettingsKey("theme-generic-colors") + public static let themeDefinitions : OCClassSettingsKey = OCClassSettingsKey("theme-definitions") } extension Branding : BrandingInitialization { @@ -75,8 +65,7 @@ extension Branding : BrandingInitialization { .sendFeedbackAddress : "ios-app@owncloud.com", .canAddAccount : true, .canEditAccount : true, - .enableReviewPrompt : false, - .profileAllowUrlConfiguration : true + .enableReviewPrompt : false ], metadata: [ .documentationURL : [ .type : OCClassSettingsMetadataType.urlString, @@ -165,113 +154,82 @@ extension Branding : BrandingInitialization { .status : OCClassSettingsKeyStatus.advanced ], - .themeDefinitions : [ - .type : OCClassSettingsMetadataType.dictionaryArray, - .description : "Array of dictionaries, each specifying a theme.", + .themeGenericColors : [ + .type : OCClassSettingsMetadataType.dictionary, + .description : "Dictionary defining generic colors that can be used in the definitions.", .category : "Branding", .status : OCClassSettingsKeyStatus.advanced ], - .themeCSSRecords: [ - .type : OCClassSettingsMetadataType.stringArray, - .label : "Theme CSS Records", - .description : "CSS records to add to the CSS space of system-color-based themes for branded clients. Mutually exclusive with theme-definitions.", - .category : "Branding", - .status : OCClassSettingsKeyStatus.advanced - ], - - .themeColors : [ - .type : OCClassSettingsMetadataType.dictionary, - .label : "Theme Colors", - .description : "Values to use in system-color-based themes for branded clients. Mutually exclusive with theme-definitions.", + .themeDefinitions : [ + .type : OCClassSettingsMetadataType.dictionaryArray, + .description : "Array of dictionaries, each specifying a theme.", .category : "Branding", - .possibleKeys : [ - [ - OCClassSettingsMetadataKey.value : BrandingColorAlias.tintColor.rawValue, - OCClassSettingsMetadataKey.description : "Color to use as tint/accent color for controls (in hex notation)." - ], - [ - OCClassSettingsMetadataKey.value : BrandingColorAlias.brandingBackgroundColor.rawValue, - OCClassSettingsMetadataKey.description : "Color to use as background color for brand views (in hex notation)." - ], - [ - OCClassSettingsMetadataKey.value : BrandingColorAlias.setupStatusBarStyle.rawValue, - OCClassSettingsMetadataKey.description : "The status bar style in the setup wizard, affecting the status bar text color. Can be either `default`, `black` or `white`." - ], - [ - OCClassSettingsMetadataKey.value : BrandingColorAlias.fileIconColor.rawValue, - OCClassSettingsMetadataKey.description : "Color to fill file icons with (in hex notation)." - ], - [ - OCClassSettingsMetadataKey.value : BrandingColorAlias.folderIconColor.rawValue, - OCClassSettingsMetadataKey.description : "Color to fill folder icons with (in hex notation)." - ] - ], .status : OCClassSettingsKeyStatus.advanced ], .profileBookmarkName : [ - .type : OCClassSettingsMetadataType.string, - .label : "Bookmark Name", - .description : "The name that should be used for the bookmark that's generated from this profile and appears in the account list.", - .status : OCClassSettingsKeyStatus.advanced, - .category : "Branding" + .type : OCClassSettingsMetadataType.string, + .label : "Bookmark Name", + .description : "The name that should be used for the bookmark that's generated from this profile and appears in the account list.", + .status : OCClassSettingsKeyStatus.advanced, + .category : "Branding" ], .profileURL : [ - .type : OCClassSettingsMetadataType.urlString, - .label : "URL", - .description : "The URL of the server targeted by this profile.", - .status : OCClassSettingsKeyStatus.advanced, - .category : "Branding" + .type : OCClassSettingsMetadataType.urlString, + .label : "URL", + .description : "The URL of the server targeted by this profile.", + .status : OCClassSettingsKeyStatus.advanced, + .category : "Branding" ], .profileHelpURL : [ - .type : OCClassSettingsMetadataType.urlString, - .label : "Onboarding URL", - .description : "Optional URL to onboarding resources.", - .status : OCClassSettingsKeyStatus.advanced, - .category : "Branding" + .type : OCClassSettingsMetadataType.urlString, + .label : "Onboarding URL", + .description : "Optional URL to onboarding resources.", + .status : OCClassSettingsKeyStatus.advanced, + .category : "Branding" ], .profileOpenHelpMessage: [ - .type : OCClassSettingsMetadataType.string, - .label : "Open onboarding URL message", - .description : "Message shown in an alert before opening the onboarding URL.", - .status : OCClassSettingsKeyStatus.advanced, - .category : "Branding" + .type : OCClassSettingsMetadataType.string, + .label : "Open onboarding URL message", + .description : "Message shown in an alert before opening the onboarding URL.", + .status : OCClassSettingsKeyStatus.advanced, + .category : "Branding" ], .profileHelpButtonLabel : [ - .type : OCClassSettingsMetadataType.string, - .label : "Onboarding button title", - .description : "Text used for the onboarding button title", - .status : OCClassSettingsKeyStatus.advanced, - .category : "Branding" + .type : OCClassSettingsMetadataType.string, + .label : "Onboarding button title", + .description : "Text used for the onboarding button title", + .status : OCClassSettingsKeyStatus.advanced, + .category : "Branding" ], .profileAllowUrlConfiguration : [ - .type : OCClassSettingsMetadataType.boolean, - .label : "Allow URL configuration", - .description : "Indicates if the user can change the server URL for the account.", - .status : OCClassSettingsKeyStatus.advanced, - .category : "Branding" + .type : OCClassSettingsMetadataType.boolean, + .label : "Allow URL configuration", + .description : "Indicates if the user can change the server URL for the account.", + .status : OCClassSettingsKeyStatus.advanced, + .category : "Branding" ], .sidebarLinks : [ - .type : OCClassSettingsMetadataType.array, - .label : "Sidebar Link Items", - .description : "Array of Dictionary, which should appear in the sidebar. Keys url and title are mandatory and an optional image can be added as either an SF-Symbol name (key: symbol) or the name of an image bundled with the app (key: image)", - .status : OCClassSettingsKeyStatus.advanced, - .category : "Branding" + .type : OCClassSettingsMetadataType.array, + .label : "Sidebar Link Items", + .description : "Array of Dictionary, which should appear in the sidebar. Keys url and title are mandatory and an optional image can be added as either an SF-Symbol name (key: symbol) or the name of an image bundled with the app (key: image)", + .status : OCClassSettingsKeyStatus.advanced, + .category : "Branding" ], .sidebarLinksTitle : [ - .type : OCClassSettingsMetadataType.string, - .label : "Sidebar Links Title", - .description : "Title for the sidebar links section.", - .status : OCClassSettingsKeyStatus.advanced, - .category : "Branding" + .type : OCClassSettingsMetadataType.string, + .label : "Sidebar Links Title", + .description : "Title for the sidebar links section.", + .status : OCClassSettingsKeyStatus.advanced, + .category : "Branding" ] ]) } @@ -291,25 +249,20 @@ extension Branding : BrandingInitialization { registerLegacyKeyPath("Profiles", forClassSettingsKey: .profileDefinitions) + registerLegacyKeyPath("Generic", forClassSettingsKey: .themeGenericColors) registerLegacyKeyPath("Themes", forClassSettingsKey: .themeDefinitions) // swiftlint:enable comma } } extension BrandingImageName { - public static let brandLogo : BrandingImageName = BrandingImageName("branding-logo") - public static let brandBackground : BrandingImageName = BrandingImageName("branding-background") + public static let loginLogo : BrandingImageName = BrandingImageName("branding-login-logo") + public static let loginBackground : BrandingImageName = BrandingImageName("branding-login-background") - public static let legacyBrandLogo : BrandingImageName = BrandingImageName("branding-login-logo") // can be removed as of version 12.2 - public static let legacyBrandBackground : BrandingImageName = BrandingImageName("branding-login-background") // can be removed as of version 12.2 - - public static let splashscreenLogo : BrandingImageName = BrandingImageName("branding-splashscreen-logo") + public static let splashscreenLogo : BrandingImageName = BrandingImageName("branding-splashscreen") public static let splashscreenBackground : BrandingImageName = BrandingImageName("branding-splashscreen-background") -} -extension BrandingAssetSuffix { - public static let setup: BrandingAssetSuffix = BrandingAssetSuffix("setup") - public static let sidebar: BrandingAssetSuffix = BrandingAssetSuffix("sidebar") + public static let bookmarkIcon : BrandingImageName = BrandingImageName("branding-bookmark-icon") } extension Branding { @@ -446,7 +399,7 @@ public struct SidebarLink { } extension Branding { - func generateThemeStyle(from theme: [String : Any]) -> ThemeStyle? { + func generateThemeStyle(from theme: [String : Any], generic: [String : Any]) -> ThemeStyle? { let style = theme["ThemeStyle"] as? String ?? ThemeCollectionStyle.light.rawValue let identifier = theme["Identifier"] as? String ?? "com.owncloud.branding" let name = theme["Name"] as? String ?? "ownCloud-branding-theme" @@ -455,78 +408,29 @@ extension Branding { if let themeStyle = ThemeCollectionStyle(rawValue: style), let darkBrandColor = theme["darkBrandColor"] as? String, let lightBrandColor = theme["lightBrandColor"] as? String { + let colors = theme["Colors"] as? NSDictionary let styles = theme["Styles"] as? NSDictionary - return ThemeStyle(styleIdentifier: identifier, localizedName: name.localized, lightColor: lightBrandColor.colorFromHex ?? UIColor.red, darkColor: darkBrandColor.colorFromHex ?? UIColor.blue, themeStyle: themeStyle, interfaceStyles: styles, cssRecordStrings: cssRecordStrings) + return ThemeStyle(styleIdentifier: identifier, localizedName: name.localized, lightColor: lightBrandColor.colorFromHex ?? UIColor.red, darkColor: darkBrandColor.colorFromHex ?? UIColor.blue, themeStyle: themeStyle, customColors: colors, genericColors: generic as NSDictionary?, interfaceStyles: styles, cssRecordStrings: cssRecordStrings) } return nil } public func setupThemeStyles() -> Bool { - var brandingThemeStyles : [ThemeStyle] = [] - - allowThemeSelection = true + var extractedThemeStyles : [ThemeStyle] = [] if let themeStyleDefinitions = self.computedValue(forClassSettingsKey: .themeDefinitions) as? [[String : Any]] { + let generic = self.computedValue(forClassSettingsKey: .themeGenericColors) as? [String : Any] ?? [:] for themeStyleDefinition in themeStyleDefinitions { - if let themeStyle = self.generateThemeStyle(from: themeStyleDefinition) { - brandingThemeStyles.append(themeStyle) + if let themeStyle = self.generateThemeStyle(from: themeStyleDefinition, generic: generic) { + extractedThemeStyles.append(themeStyle) } } - } else if isBranded { - var tintColor: UIColor? - var mappedCSSRecordStrings : [String]? - - if let colors = self.computedValue(forClassSettingsKey: .themeColors) as? [String:String] { - func addCSSRecord(_ selectors: [ThemeCSSSelector], property: ThemeCSSProperty, value: String) { - if mappedCSSRecordStrings == nil { - mappedCSSRecordStrings = [] - } - - mappedCSSRecordStrings?.append("\(selectors.address(with: property)): \(value)") - } - - for (aliasString, value) in colors { - if let alias = BrandingColorAlias(rawValue: aliasString) { - switch alias { - case .tintColor: - // Use as tint color - tintColor = value.colorFromHex - - case .brandingBackgroundColor: - addCSSRecord([.brand, .background], property: .fill, value: value) - - case .setupStatusBarStyle: - addCSSRecord([.accountSetup], property: .statusBarStyle, value: value) - - case .folderIconColor: - addCSSRecord([.vectorImage, .folderColor], property: .fill, value: value) - - case .fileIconColor: - addCSSRecord([.vectorImage, .fileColor], property: .fill, value: value) - addCSSRecord([.vectorImage, .documentFileColor], property: .fill, value: value) - addCSSRecord([.vectorImage, .presentationFileColor], property: .fill, value: value) - addCSSRecord([.vectorImage, .spreadsheetFileColor], property: .fill, value: value) - addCSSRecord([.vectorImage, .pdfFileColor], property: .fill, value: value) - } - } - } - } - - var effectiveCSSRecordStrings: [String] = mappedCSSRecordStrings ?? [] - - if let themeCSSRecordStrings = self.computedValue(forClassSettingsKey: .themeCSSRecords) as? [String] { - effectiveCSSRecordStrings.append(contentsOf: themeCSSRecordStrings) - } - - brandingThemeStyles.append(ThemeStyle.systemLight(with: tintColor, cssRecordStrings: effectiveCSSRecordStrings)) - brandingThemeStyles.append(ThemeStyle.systemDark(with: tintColor, cssRecordStrings: effectiveCSSRecordStrings)) - allowThemeSelection = true } var isDefault = true - for themeStyle in brandingThemeStyles { + for themeStyle in extractedThemeStyles { let themeStyleExtension = themeStyle.themeStyleExtension(isDefault: isDefault) OCExtensionManager.shared.addExtension(themeStyleExtension) isDefault = false @@ -538,9 +442,4 @@ extension Branding { public extension ThemeCSSSelector { static let welcome = ThemeCSSSelector(rawValue: "welcome") - static let accountSetup = ThemeCSSSelector(rawValue: "accountSetup") - static let step = ThemeCSSSelector(rawValue: "step") - static let help = ThemeCSSSelector(rawValue: "help") - static let certificateSummary = ThemeCSSSelector(rawValue: "certificateSummary") - static let brand = ThemeCSSSelector(rawValue: "brand") } diff --git a/ownCloudAppShared/Client/Collection Views/Cells/AccountControllerCell.swift b/ownCloudAppShared/Client/Collection Views/Cells/AccountControllerCell.swift index 25a061f22..9e2e6a92e 100644 --- a/ownCloudAppShared/Client/Collection Views/Cells/AccountControllerCell.swift +++ b/ownCloudAppShared/Client/Collection Views/Cells/AccountControllerCell.swift @@ -44,7 +44,10 @@ class AccountControllerCell: ThemeableCollectionViewListCell { iconView.cssSelectors = [.icon] disconnectButton.cssSelectors = [.disconnect] - iconView.fallbackView = BrandView(showBackground: true, showLogo: true, logoMaxSize: CGSize(width: 36, height: 36), roundedCorners: true) + logoFallbackView.contentMode = .scaleAspectFit + logoFallbackView.image = Branding.shared.brandedImageNamed(.bookmarkIcon) + + iconView.fallbackView = logoFallbackView titleLabel.font = UIFont.preferredFont(forTextStyle: .title3, with: .bold) titleLabel.adjustsFontForContentSizeCategory = true @@ -107,15 +110,13 @@ class AccountControllerCell: ThemeableCollectionViewListCell { disconnectButton.trailingAnchor.constraint(lessThanOrEqualTo: infoView.trailingAnchor), disconnectButton.centerYAnchor.constraint(equalTo: infoView.centerYAnchor), - contentView.heightAnchor.constraint(equalToConstant: AccountControllerCell.avatarSideLength + 20).with(priority: .defaultHigh) + contentView.heightAnchor.constraint(equalToConstant: AccountControllerCell.avatarSideLength + 20) ]) infoView.setContentHuggingPriority(.required, for: .horizontal) logoFallbackView.setContentHuggingPriority(.required, for: .vertical) titleLabel.setContentCompressionResistancePriority(.defaultHigh, for: .vertical) detailLabel.setContentCompressionResistancePriority(.defaultHigh, for: .vertical) - - disconnectButton.setContentCompressionResistancePriority(.required, for: .horizontal) } override init(frame: CGRect) { diff --git a/ownCloudAppShared/Client/Collection Views/Cells/UniversalItemListCell Content Providers/OCShare+UniversalItemListCellContentProvider.swift b/ownCloudAppShared/Client/Collection Views/Cells/UniversalItemListCell Content Providers/OCShare+UniversalItemListCellContentProvider.swift index 5f7b7d246..9d0d0fc43 100644 --- a/ownCloudAppShared/Client/Collection Views/Cells/UniversalItemListCell Content Providers/OCShare+UniversalItemListCellContentProvider.swift +++ b/ownCloudAppShared/Client/Collection Views/Cells/UniversalItemListCell Content Providers/OCShare+UniversalItemListCellContentProvider.swift @@ -88,7 +88,7 @@ extension OCShare: UniversalItemListCellContentProvider { } } else { // Link shares - content.title = .text(name ?? token ?? "Link".localized) + content.title = .text(name ?? "Link".localized) if let urlString = url?.absoluteString, urlString.count > 0 { if let roleName = matchingRole?.localizedName { @@ -242,7 +242,7 @@ extension OCShare: UniversalItemListCellContentProvider { } } - if category == .withMe, let effectiveState { + if category == .withMe, let effectiveState, effectiveState != .accepted { var accessories: [UICellAccessory] = [] let omitLongActions = (effectiveState == .pending) && (UITraitCollection.current.horizontalSizeClass == .compact) @@ -257,7 +257,7 @@ extension OCShare: UniversalItemListCellContentProvider { accessories.append(accessory) } - if (effectiveState == .pending || effectiveState == .accepted) && !omitLongActions { + if effectiveState == .pending, !omitLongActions { let (_, accessory) = cell.makeAccessoryButton(image: OCSymbol.icon(forSymbolName: "minus.circle"), title: "Decline".localized, accessibilityLabel: "Decline share".localized, cssSelectors: [.accessory, .decline], action: UIAction(handler: { [weak self, weak context] action in if let self, let context, let core = context.core { core.makeDecision(on: self, accept: false, completionHandler: { error in @@ -274,13 +274,13 @@ extension OCShare: UniversalItemListCellContentProvider { accessories.append(accessory) } - if effectiveState == .accepted { - accessories.append(cell.revealButtonAccessory) - } - content.accessories = accessories } + if category == .withMe, let effectiveState, effectiveState == .accepted { + content.accessories = [ cell.revealButtonAccessory ] + } + _ = updateContent(content) } } diff --git a/ownCloudAppShared/Client/Collection Views/Cells/UniversalItemListCell Content Providers/OCShareRole+UniversalItemListCellContentProvider.swift b/ownCloudAppShared/Client/Collection Views/Cells/UniversalItemListCell Content Providers/OCShareRole+UniversalItemListCellContentProvider.swift index 74dc4c16b..433879709 100644 --- a/ownCloudAppShared/Client/Collection Views/Cells/UniversalItemListCell Content Providers/OCShareRole+UniversalItemListCellContentProvider.swift +++ b/ownCloudAppShared/Client/Collection Views/Cells/UniversalItemListCell Content Providers/OCShareRole+UniversalItemListCellContentProvider.swift @@ -25,7 +25,6 @@ extension OCShareRole: UniversalItemListCellContentProvider { if let icon = OCSymbol.icon(forSymbolName: symbolName) { content.icon = .icon(image: icon) - content.iconWidth = UniversalItemListCell.defaultIconSize.width / 2 } content.title = .text(localizedName) diff --git a/ownCloudAppShared/Client/Collection Views/Cells/UniversalItemListCell.swift b/ownCloudAppShared/Client/Collection Views/Cells/UniversalItemListCell.swift index 92b36e21e..1ae92129f 100644 --- a/ownCloudAppShared/Client/Collection Views/Cells/UniversalItemListCell.swift +++ b/ownCloudAppShared/Client/Collection Views/Cells/UniversalItemListCell.swift @@ -49,7 +49,6 @@ open class UniversalItemListCell: ThemeableCollectionViewListCell { icon = content.icon iconDisabled = content.iconDisabled - iconWidth = content.iconWidth details = content.details @@ -103,7 +102,6 @@ open class UniversalItemListCell: ThemeableCollectionViewListCell { var title: Title? var icon: Icon? var iconDisabled: Bool = false - var iconWidth: CGFloat? var details: [SegmentViewItem]? @@ -129,7 +127,7 @@ open class UniversalItemListCell: ThemeableCollectionViewListCell { return view }() - static public let defaultIconSize : CGSize = CGSize(width: 40, height: 40) + private let iconSize : CGSize = CGSize(width: 40, height: 40) public let thumbnailSize : CGSize = CGSize(width: 60, height: 60) // when changing size, also update .iconView.fallbackSize open var iconView: ResourceViewHost = ResourceViewHost(fallbackSize: CGSize(width: 60, height: 60)) // when changing size, also update .thumbnailSize @@ -308,12 +306,10 @@ open class UniversalItemListCell: ThemeableCollectionViewListCell { hasSecondaryDetailView = false } - let iconWidthConstraint = updateIconWidth(content?.iconWidth, defaultWidth: (iconViewHeight / 0.75)) // 4:3 - constraints = [ iconView.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: horizontalMargin), iconView.trailingAnchor.constraint(equalTo: titleLabel.leadingAnchor, constant: -spacing), - iconWidthConstraint, + iconView.widthAnchor.constraint(equalToConstant: floor(iconViewHeight / 0.75)), // 4:3 iconView.heightAnchor.constraint(equalToConstant: iconViewHeight), iconView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: verticalIconMargin), iconView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -verticalIconMargin), @@ -332,7 +328,7 @@ open class UniversalItemListCell: ThemeableCollectionViewListCell { let verticalLabelMargin : CGFloat = 10 let verticalIconMargin : CGFloat = 10 let spacing : CGFloat = 15 - let iconViewWidth : CGFloat = floor(type(of: self).defaultIconSize.width / 2) + let iconViewWidth : CGFloat = floor(iconSize.width / 2) let titleDetailSpacing: CGFloat = 15 titleLabel.numberOfLines = 1 @@ -345,12 +341,10 @@ open class UniversalItemListCell: ThemeableCollectionViewListCell { hasSecondaryDetailView = false } - let iconWidthConstraint = updateIconWidth(content?.iconWidth, defaultWidth: iconViewWidth) - constraints = [ iconView.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: horizontalMargin), iconView.trailingAnchor.constraint(equalTo: titleLabel.leadingAnchor, constant: -spacing), - iconWidthConstraint, + iconView.widthAnchor.constraint(equalToConstant: iconViewWidth), iconView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: verticalIconMargin), iconView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -verticalIconMargin), @@ -368,7 +362,7 @@ open class UniversalItemListCell: ThemeableCollectionViewListCell { let verticalLabelMargin : CGFloat = 10 let verticalIconMargin : CGFloat = 10 let spacing : CGFloat = 15 - let iconViewWidth : CGFloat = type(of: self).defaultIconSize.width + let iconViewWidth : CGFloat = iconSize.width let verticalLabelMarginFromCenter : CGFloat = 1 titleLabel.numberOfLines = 1 @@ -383,12 +377,10 @@ open class UniversalItemListCell: ThemeableCollectionViewListCell { truncationMode = .truncateTail - let iconWidthConstraint = updateIconWidth(content?.iconWidth, defaultWidth: iconViewWidth) - constraints = [ iconView.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: horizontalMargin), iconView.trailingAnchor.constraint(equalTo: titleLabel.leadingAnchor, constant: -spacing), - iconWidthConstraint, + iconView.widthAnchor.constraint(equalToConstant: iconViewWidth), iconView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: verticalIconMargin), iconView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -verticalIconMargin), @@ -414,28 +406,6 @@ open class UniversalItemListCell: ThemeableCollectionViewListCell { } } - private var iconWidthConstraint: NSLayoutConstraint? - private var lastIconWidth: CGFloat? - private var defaultIconWidthForCellLayout: CGFloat? // default width for current cell layout - private func updateIconWidth(_ newWidth: CGFloat?, defaultWidth: CGFloat? = nil) -> NSLayoutConstraint { - if let iconWidthConstraint { - iconWidthConstraint.isActive = false - } - - if let defaultWidth { - // Store default width for this cell type if one is provided - defaultIconWidthForCellLayout = defaultWidth - } - - // Fall back to default icon size if necessary - let effectiveWidth = newWidth ?? defaultIconWidthForCellLayout ?? type(of: self).defaultIconSize.width - - let widthConstraint = iconView.widthAnchor.constraint(equalToConstant: effectiveWidth) - iconWidthConstraint = widthConstraint - - return widthConstraint - } - // MARK: - Content var title: NSAttributedString? { didSet { @@ -532,11 +502,6 @@ open class UniversalItemListCell: ThemeableCollectionViewListCell { } } - if content?.iconWidth != lastIconWidth { - updateIconWidth(content?.iconWidth).isActive = true - lastIconWidth = content?.iconWidth - } - iconView.request = iconRequest if let iconViewProvider { iconView.activeViewProvider = iconViewProvider diff --git a/ownCloudAppShared/Client/Data Item Interactions/OCDataItem+InteractionProtocols.swift b/ownCloudAppShared/Client/Data Item Interactions/OCDataItem+InteractionProtocols.swift index f6bbff309..3d9fa0168 100644 --- a/ownCloudAppShared/Client/Data Item Interactions/OCDataItem+InteractionProtocols.swift +++ b/ownCloudAppShared/Client/Data Item Interactions/OCDataItem+InteractionProtocols.swift @@ -47,8 +47,8 @@ import ownCloudSDK // MARK: - Drag & drop public struct LocalDataItem { - public var bookmarkUUID : UUID - public var dataItem: OCDataItem + var bookmarkUUID : UUID + var dataItem: OCDataItem } @objc public protocol DataItemDragInteraction: OCDataItem { diff --git a/ownCloudAppShared/Client/Data Source Conditions/DataSourceCondition.swift b/ownCloudAppShared/Client/Data Source Conditions/DataSourceCondition.swift index 3322f2e9a..d89bcfc02 100644 --- a/ownCloudAppShared/Client/Data Source Conditions/DataSourceCondition.swift +++ b/ownCloudAppShared/Client/Data Source Conditions/DataSourceCondition.swift @@ -94,8 +94,7 @@ open class DataSourceCondition: NSObject { setParentOf(condition: condition, to: self) action = inAction - if initial, let action, - fulfilled != nil { // only make initial call if a fulfilled state could already be computed - for condition types where this is not possible right away the subscription's `performInitialUpdate: true` parameter will make sure the initial call is performed as soon as fulfilled could be determined + if initial, let action { action(self) } } diff --git a/ownCloudAppShared/Client/Sharing/ShareViewController.swift b/ownCloudAppShared/Client/Sharing/ShareViewController.swift index 0eba7c02d..08cae769e 100644 --- a/ownCloudAppShared/Client/Sharing/ShareViewController.swift +++ b/ownCloudAppShared/Client/Sharing/ShareViewController.swift @@ -54,7 +54,6 @@ open class ShareViewController: CollectionViewController, SearchViewControllerDe public var share: OCShare? public var item: OCItem? public var location: OCLocation? - public var name: String? public var type: ShareType public var mode: Mode @@ -100,8 +99,6 @@ open class ShareViewController: CollectionViewController, SearchViewControllerDe var linksSectionDatasource: OCDataSourceArray? var linksSection: CollectionViewSection? - var nameTextField : UITextField? - var customPermissionsSectionOptionGroup: OptionGroup? var customPermissionsDatasource: OCDataSourceArray? var customPermissionsSection: CollectionViewSection? @@ -178,31 +175,6 @@ open class ShareViewController: CollectionViewController, SearchViewControllerDe sections.append(linksSection) } - // - Name - if self.type == .link { - let textField : UITextField = ThemeCSSTextField() - textField.translatesAutoresizingMaskIntoConstraints = false - textField.setContentHuggingPriority(.required, for: .vertical) - textField.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) - textField.placeholder = share?.token ?? "Link".localized - textField.text = share?.name - textField.accessibilityLabel = "Name".localized - - nameTextField = textField - - let spacerView = UIView() - spacerView.translatesAutoresizingMaskIntoConstraints = false - spacerView.embed(toFillWith: textField, insets: NSDirectionalEdgeInsets(top: 10, leading: 18, bottom: 10, trailing: 18)) - - let nameSectionDatasource = OCDataSourceArray(items: [spacerView]) - let nameSection = CollectionViewSection(identifier: "name", dataSource: nameSectionDatasource, cellStyle: managementCellStyle, cellLayout: .list(appearance: .insetGrouped, contentInsets: .insetGroupedSectionInsets), clientContext: shareControllerContext) - nameSection.boundarySupplementaryItems = [ - .mediumTitle("Name".localized) - ] - - sections.append(nameSection) - } - // - Roles & permissions rolesSectionDatasource = OCDataSourceArray() @@ -292,14 +264,6 @@ open class ShareViewController: CollectionViewController, SearchViewControllerDe self.addStacked(child: bottomButtonBarViewController, position: .bottom) - // Wire up name textfield - self.name = share?.name - nameTextField?.addAction(UIAction(handler: { [weak self, weak nameTextField] _ in - if let nameTextField { - self?.name = nameTextField.text - } - }), for: .allEditingEvents) - // Set up view if let share, let core = clientContext?.core { role = core.matchingShareRole(for: share) @@ -700,7 +664,7 @@ open class ShareViewController: CollectionViewController, SearchViewControllerDe case .link: if let location, let permissions { - newShare = OCShare(publicLinkTo: location, linkName: name, permissions: permissions, password: nil, expiration: nil) + newShare = OCShare(publicLinkTo: location, linkName: nil, permissions: permissions, password: nil, expiration: nil) } } @@ -754,10 +718,6 @@ open class ShareViewController: CollectionViewController, SearchViewControllerDe share.protectedByPassword = true } - if self?.type == .link { - share.name = self?.name - } - share.expirationDate = self?.expirationDate }, completionHandler: { error, share in OnMainThread { diff --git a/ownCloudAppShared/Client/User Interface/MessageView.swift b/ownCloudAppShared/Client/User Interface/MessageView.swift index 2b01d6930..4982cc3b7 100644 --- a/ownCloudAppShared/Client/User Interface/MessageView.swift +++ b/ownCloudAppShared/Client/User Interface/MessageView.swift @@ -88,7 +88,6 @@ open class MessageView: UIView { messageLabel.translatesAutoresizingMaskIntoConstraints = false messageLabel.numberOfLines = 0 messageLabel.textAlignment = .center - messageLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) containerView.addSubview(imageView) containerView.addSubview(titleLabel) diff --git a/ownCloudAppShared/Client/User Interface/NamingViewController.swift b/ownCloudAppShared/Client/User Interface/NamingViewController.swift index 0f457a0e5..7aff8f858 100644 --- a/ownCloudAppShared/Client/User Interface/NamingViewController.swift +++ b/ownCloudAppShared/Client/User Interface/NamingViewController.swift @@ -19,8 +19,8 @@ import UIKit import ownCloudSDK -public typealias StringValidatorResult = (Bool, String?, String?) // (validationPassed, validationErrorTitle, validationErrorMessage) -public typealias StringValidatorHandler = (_ stringToCheck: String) -> StringValidatorResult +public typealias StringValidatorResult = (Bool, String?, String?) +public typealias StringValidatorHandler = (String) -> StringValidatorResult open class NamingViewController: UIViewController { weak open var item: OCItem? @@ -28,7 +28,6 @@ open class NamingViewController: UIViewController { open var completion: (String?, NamingViewController) -> Void open var stringValidator: StringValidatorHandler? open var defaultName: String? - open var requiredFileExtension: String? private var blurView: UIVisualEffectView @@ -38,7 +37,7 @@ open class NamingViewController: UIViewController { private var thumbnailImageView: ResourceViewHost private var nameContainer: UIView - private var nameTextField: ThemeCSSTextField + private var nameTextField: UITextField private var textfieldTopAnchorConstraint: NSLayoutConstraint private var textfieldCenterYAnchorConstraint: NSLayoutConstraint @@ -153,7 +152,6 @@ open class NamingViewController: UIViewController { // Name textfield nameTextField.translatesAutoresizingMaskIntoConstraints = false - nameTextField.requiredFileExtension = requiredFileExtension nameContainer.addSubview(nameTextField) NSLayoutConstraint.activate([ nameTextField.heightAnchor.constraint(equalToConstant: 40), @@ -269,9 +267,7 @@ open class NamingViewController: UIViewController { } @objc open func textfieldDidChange(_ sender: UITextField) { - let filename = sender.text - - if filename != "", requiredFileExtension == nil || ((requiredFileExtension != nil) && filename != ".\(requiredFileExtension!)") { + if sender.text != "" { doneButton?.isEnabled = true } else { doneButton?.isEnabled = false @@ -355,15 +351,7 @@ extension NamingViewController: UITextFieldDelegate { } else { textField.selectedTextRange = nameTextField.textRange(from: nameTextField.beginningOfDocument, to: nameTextField.endOfDocument) } - } - public func textFieldShouldClear(_ textField: UITextField) -> Bool { - if let requiredFileExtension { - textField.text = "." + requiredFileExtension - textField.selectedTextRange = textField.textRange(from: textField.beginningOfDocument, to: textField.beginningOfDocument) - return false - } - return true } open func textFieldShouldReturn(_ textField: UITextField) -> Bool { diff --git a/ownCloudAppShared/Client/View Controllers/ClientItemViewController.swift b/ownCloudAppShared/Client/View Controllers/ClientItemViewController.swift index 990cd564b..a255c3b47 100644 --- a/ownCloudAppShared/Client/View Controllers/ClientItemViewController.swift +++ b/ownCloudAppShared/Client/View Controllers/ClientItemViewController.swift @@ -673,64 +673,33 @@ open class ClientItemViewController: CollectionViewController, SortBarDelegate, } set { - if navigationItem.titleView is ClientLocationPopupButton { - navigationItem.titleView = nil - } - navigationItem.titleLabelText = newValue navigationItem.title = newValue } } - var useNavigationLocationBreadcrumbDropdown: Bool { - return UIDevice.current.userInterfaceIdiom == .pad - } - - var navigationLocation: OCLocation? { - didSet { - if let clientContext, let navigationLocation, !navigationLocation.isRoot { - navigationItem.titleView = ClientLocationPopupButton(clientContext: clientContext, location: navigationLocation) - } else { - if navigationItem.titleView is ClientLocationPopupButton { - navigationItem.titleView = nil - } - } - } - } - func updateNavigationTitleFromContext() { var navigationTitle: String? - var navigationLocation: OCLocation? // Set navigation title from location (if provided) if let location { navigationTitle = location.displayName(in: clientContext) - navigationLocation = location } // Set navigation title from queryLocation if navigationTitle == nil, let queryLocation = query?.queryLocation { navigationTitle = queryLocation.displayName(in: clientContext) - navigationLocation = queryLocation } // Set navigation title from rootItem.name - if navigationTitle == nil, let queryRootItem = self.clientContext?.rootItem as? OCItem { - navigationTitle = queryRootItem.name - navigationLocation = queryRootItem.location - } - - // Compose navigation title - if useNavigationLocationBreadcrumbDropdown { - self.navigationLocation = navigationLocation + if navigationTitle == nil { + navigationTitle = (self.clientContext?.rootItem as? OCItem)?.name } - if navigationLocation == nil || !useNavigationLocationBreadcrumbDropdown { - if let navigationTitle { - self.navigationTitle = navigationTitle - } else { - self.navigationTitle = navigationItem.title - } + if let navigationTitle { + self.navigationTitle = navigationTitle + } else { + self.navigationTitle = navigationItem.title } } diff --git a/ownCloudAppShared/Client/View Controllers/ClientSidebarViewController.swift b/ownCloudAppShared/Client/View Controllers/ClientSidebarViewController.swift index fd67f1c73..ce0730e25 100644 --- a/ownCloudAppShared/Client/View Controllers/ClientSidebarViewController.swift +++ b/ownCloudAppShared/Client/View Controllers/ClientSidebarViewController.swift @@ -71,26 +71,14 @@ public class ClientSidebarViewController: CollectionSidebarViewController, Navig accountsControllerSectionSource?.source = OCBookmarkManager.shared.bookmarksDatasource // Combined data source - if let accountsControllerSectionSource { - var sources: [OCDataSource] = [ accountsControllerSectionSource ] - - if let brandingElementDataSource { - sources.insert(brandingElementDataSource, at: 0) - } - - if let sidebarLinksDataSource { - sources.append(sidebarLinksDataSource) - } - - if sources.count > 1 { - combinedSectionsDatasource = OCDataSourceComposition(sources: sources) - } + if let accountsControllerSectionSource, let sidebarLinksDataSource = sidebarLinksDataSource { + combinedSectionsDatasource = OCDataSourceComposition(sources: [ accountsControllerSectionSource, sidebarLinksDataSource ]) } // Set up Collection View sectionsDataSource = combinedSectionsDatasource ?? accountsControllerSectionSource navigationItem.largeTitleDisplayMode = .never - navigationItem.titleView = ClientSidebarViewController.buildNavigationLogoView() + navigationItem.titleView = self.buildNavigationLogoView() // Add 10pt space at the top so that the first section's account doesn't "stick" to the top collectionView.contentInset.top += 10 @@ -182,24 +170,6 @@ public class ClientSidebarViewController: CollectionSidebarViewController, Navig focusedBookmark = newFocusedBookmark } - public var brandingElementDataSource: OCDataSourceArray? { - if Branding.shared.isBranded { - let logoSize = CGSize(width: 128, height: 64) - let brandView = BrandView(showBackground: true, showLogo: true, logoMaxSize: logoSize, roundedCorners: true, assetSuffix: .sidebar) - - NSLayoutConstraint.activate([ - brandView.heightAnchor.constraint(equalToConstant: logoSize.height) - ]) - - let elementDataSource = OCDataSourceArray(items: [ brandView ]) - let section = CollectionViewSection(identifier: "branding-elements", dataSource: elementDataSource, cellStyle: CollectionViewCellStyle(with: .sideBar), cellLayout: .list(appearance: .sidebar), clientContext: clientContext) - - return OCDataSourceArray(items: [ section ]) - } - - return nil - } - public var sidebarLinksDataSource: OCDataSourceArray? { if let sidebarLinks = Branding.shared.sidebarLinks { let actions = sidebarLinks.compactMap { link in @@ -236,54 +206,11 @@ public class ClientSidebarViewController: CollectionSidebarViewController, Navig return nil } - - // MARK: - Reordering bookmarks - func dataItem(for itemRef: CollectionViewController.ItemRef) -> OCDataItem? { - let (dataItemRef, sectionID) = unwrap(itemRef) - - if let sectionID, let section = sectionsByID[sectionID] { - if let record = try? section.dataSource?.record(forItemRef: dataItemRef) { - return record.item - } - } - - return nil - } - - public override func configureDataSource() { - super.configureDataSource() - - collectionViewDataSource.reorderingHandlers.canReorderItem = { (itemRef) in - // Log.debug("Can reorder \(itemRef)") - return true - } - - collectionViewDataSource.reorderingHandlers.didReorder = { [weak self] transaction in - Log.debug("Did reorder \(transaction)") - - guard let self else { return } - - var reorderedBookmarks: [OCBookmark] = [] - - for collectionItemRef in transaction.finalSnapshot.itemIdentifiers { - if let accountController = self.dataItem(for: collectionItemRef) as? AccountController, - let bookmark = accountController.bookmark, - let managedBookmark = OCBookmarkManager.shared.bookmark(for: bookmark.uuid) { - reorderedBookmarks.append(managedBookmark) - Log.debug("Bookmark: \(bookmark.shortName)") - } - } - - if OCBookmarkManager.shared.bookmarks.count == reorderedBookmarks.count { - OCBookmarkManager.shared.replaceBookmarks(reorderedBookmarks) - } - } - } } // MARK: - Branding extension ClientSidebarViewController { - static public func buildNavigationLogoView() -> ThemeCSSView { + func buildNavigationLogoView() -> ThemeCSSView { let logoImage = UIImage(named: "branding-login-logo") let logoImageView = UIImageView(image: logoImage) logoImageView.cssSelector = .icon @@ -304,6 +231,7 @@ extension ClientSidebarViewController { let logoContainer = ThemeCSSView(withSelectors: [.logo]) logoContainer.translatesAutoresizingMaskIntoConstraints = false + logoContainer.addSubview(logoImageView) logoContainer.setContentHuggingPriority(.required, for: .horizontal) logoContainer.setContentHuggingPriority(.required, for: .vertical) @@ -311,18 +239,16 @@ extension ClientSidebarViewController { logoWrapperView.addSubview(logoContainer) if VendorServices.shared.isBranded { - logoContainer.addSubview(logoLabel) NSLayoutConstraint.activate([ - logoLabel.topAnchor.constraint(greaterThanOrEqualTo: logoContainer.topAnchor), - logoLabel.bottomAnchor.constraint(lessThanOrEqualTo: logoContainer.bottomAnchor), - logoLabel.centerYAnchor.constraint(equalTo: logoContainer.centerYAnchor), - logoLabel.centerXAnchor.constraint(equalTo: logoContainer.centerXAnchor), + logoImageView.topAnchor.constraint(greaterThanOrEqualTo: logoContainer.topAnchor), + logoImageView.bottomAnchor.constraint(lessThanOrEqualTo: logoContainer.bottomAnchor), + logoImageView.centerYAnchor.constraint(equalTo: logoContainer.centerYAnchor), + logoImageView.centerXAnchor.constraint(equalTo: logoContainer.centerXAnchor), logoContainer.topAnchor.constraint(equalTo: logoWrapperView.topAnchor), logoContainer.bottomAnchor.constraint(equalTo: logoWrapperView.bottomAnchor), logoContainer.centerXAnchor.constraint(equalTo: logoWrapperView.centerXAnchor) ]) } else { - logoContainer.addSubview(logoImageView) logoContainer.addSubview(logoLabel) NSLayoutConstraint.activate([ logoImageView.topAnchor.constraint(greaterThanOrEqualTo: logoContainer.topAnchor), diff --git a/ownCloudAppShared/Client/View Controllers/Location Breadcrumbs/ClientLocationPopupButton.swift b/ownCloudAppShared/Client/View Controllers/Location Breadcrumbs/ClientLocationPopupButton.swift deleted file mode 100644 index 03ffaa528..000000000 --- a/ownCloudAppShared/Client/View Controllers/Location Breadcrumbs/ClientLocationPopupButton.swift +++ /dev/null @@ -1,90 +0,0 @@ -// -// ClientLocationPopupButton.swift -// ownCloudAppShared -// -// Created by Felix Schwarz on 23.10.23. -// Copyright © 2023 ownCloud GmbH. All rights reserved. -// - -/* - * Copyright (C) 2023, ownCloud GmbH. - * - * This code is covered by the GNU Public License Version 3. - * - * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ - * You should have received a copy of this license along with this program. If not, see . - * - */ - -import UIKit -import ownCloudSDK - -open class ClientLocationPopupButton: ThemeCSSButton { - weak var clientContext: ClientContext? - open var location: OCLocation? { - didSet { - updateButton() - } - } - - public init(clientContext: ClientContext? = nil, location: OCLocation? = nil, excludeLastPathComponent: Bool = true) { - super.init(frame: .zero) - cssSelectors = [.title] - - self.clientContext = clientContext - self.location = location - - titleLabel?.adjustsFontForContentSizeCategory = true - semanticContentAttribute = (effectiveUserInterfaceLayoutDirection == .leftToRight) ? .forceRightToLeft : .forceLeftToRight - setContentHuggingPriority(.defaultHigh, for: .horizontal) - setContentCompressionResistancePriority(.defaultHigh, for: .horizontal) - showsMenuAsPrimaryAction = true - translatesAutoresizingMaskIntoConstraints = false - - menu = UIMenu(title: "", children: [ - UIDeferredMenuElement.uncached({ [weak self] completion in - var menuItems : [UIMenuElement] = [] - let breadcrumbLocation = excludeLastPathComponent ? self?.location?.parent : self?.location - - if let clientContext = self?.clientContext, let breadcrumbs = breadcrumbLocation?.breadcrumbs(in: clientContext, includeServerName: false, action: .reveal).reversed() { - for crumbAction in breadcrumbs { - menuItems.append(crumbAction.uiAction()) - } - } - - completion(menuItems) - }) - ]) - - updateButton() - } - - open override func didMoveToWindow() { - super.didMoveToWindow() - - self.updateButton() - } - - func updateButton() { - let title = location?.displayName(in: clientContext) ?? "-" - let attributedTitle = AttributedString(NSAttributedString(string: title, attributes: [.font : UIFont.systemFont(ofSize: UIFont.buttonFontSize, weight: .semibold)])) - let symbolConfiguration = UIImage.SymbolConfiguration(pointSize: 0.7 * UIFont.buttonFontSize) - let chevronBackgroundColor = Theme.shared.activeThemeCSS.getColor(.fill, selectors: [.popupButton, .icon], for: self) ?? .lightGray - let chevronForegroundColor = Theme.shared.activeThemeCSS.getColor(.stroke, selectors: [.popupButton, .icon], for: self) ?? .tintColor - let chevronImage = UIImage(systemName: "chevron.down.circle.fill", withConfiguration: symbolConfiguration)?.applyingSymbolConfiguration(UIImage.SymbolConfiguration(paletteColors: [chevronForegroundColor, chevronBackgroundColor])) - - var buttonConfig = configuration ?? .plain() - buttonConfig.imagePadding = 5 - buttonConfig.attributedTitle = attributedTitle - #if swift(>=5.9) // workaround build issue on Xcode 14.2 (GitHub actions) - buttonConfig.titleLineBreakMode = .byTruncatingMiddle - #endif - buttonConfig.image = chevronImage - - self.configuration = buttonConfig - } - - required public init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} diff --git a/ownCloudAppShared/Client/View Controllers/Location Breadcrumbs/OCLocation+Breadcrumbs.swift b/ownCloudAppShared/Client/View Controllers/Location Breadcrumbs/OCLocation+Breadcrumbs.swift index 25752a674..99313a4e8 100644 --- a/ownCloudAppShared/Client/View Controllers/Location Breadcrumbs/OCLocation+Breadcrumbs.swift +++ b/ownCloudAppShared/Client/View Controllers/Location Breadcrumbs/OCLocation+Breadcrumbs.swift @@ -24,12 +24,6 @@ public extension OCActionPropertyKey { } public extension OCLocation { - enum BreadcrumbAction { - case open - case reveal - case auto - } - func displayName(in context: ClientContext?) -> String { switch type { case .drive: @@ -88,68 +82,21 @@ public extension OCLocation { return nil } - func breadcrumbs(in clientContext: ClientContext, includeServerName: Bool = true, includeDriveName: Bool = true, skipFiles: Bool = false, action breadcrumbAction: BreadcrumbAction = .open) -> [OCAction] { + func breadcrumbs(in clientContext: ClientContext, includeServerName: Bool = true, includeDriveName: Bool = true) -> [OCAction] { var breadcrumbs: [OCAction] = [] var currentLocation = self - var previousLocation: OCLocation? - var effectiveIncludeServername = includeServerName func addCrumb(title: String?, icon: UIImage?, location: OCLocation? = nil) { var actionBlock: OCActionBlock? if let location { - if location.type == .file, skipFiles { - previousLocation = location - return - } - - actionBlock = { [weak clientContext, previousLocation] (action, options, completion) in + actionBlock = { [weak clientContext] (action, options, completion) in if let context = (options?[.clientContext] as? ClientContext) ?? clientContext { - var effectiveBreadcrumbAction: BreadcrumbAction = breadcrumbAction - - switch breadcrumbAction { - case .open: break - - case .reveal: - if let previousLocation { - if previousLocation.type != .folder, previousLocation.type != .file { - // Can only reveal files and folders - effectiveBreadcrumbAction = .open - } - } else { - if location.type != .file { - // Only reveal top file, but not folder - effectiveBreadcrumbAction = .open - } - } - - case .auto: - if location.type == .file { - effectiveBreadcrumbAction = .reveal - } else { - effectiveBreadcrumbAction = .open - } - } - - switch effectiveBreadcrumbAction { - case .open: - _ = (location as DataItemSelectionInteraction).openItem?(from: nil, with: context, animated: true, pushViewController: true, completion: { (success) in - completion(success ? nil : NSError(ocError: .internal)) - }) - - case .reveal: - let revealLocation = previousLocation ?? location - - _ = (revealLocation as DataItemSelectionInteraction).revealItem?(from: nil, with: context, animated: true, pushViewController: true, completion: { success in - completion(success ? nil : NSError(ocError: .internal)) - }) - - case .auto: break - } + _ = (location as DataItemSelectionInteraction).openItem?(from: nil, with: context, animated: true, pushViewController: true, completion: { (success) in + completion(success ? nil : NSError(ocError: .internal)) + }) } } - - previousLocation = location } let action = OCAction(title: title ?? "?", icon: icon, action: actionBlock) @@ -158,19 +105,10 @@ public extension OCLocation { breadcrumbs.insert(action, at: 0) } -// // Include file -// if currentLocation.type == .file { -// addCrumb(title: currentLocation.displayName(in: clientContext), icon: currentLocation.displayIcon(in: clientContext), location: currentLocation) -// -// if let parentLocation = currentLocation.parent { -// currentLocation = parentLocation -// } -// } - // Location in reverse - if currentLocation.type == .folder || currentLocation.type == .file { + if currentLocation.type == .folder { while !currentLocation.isRoot, currentLocation.path != nil { - if currentLocation.type == .folder || currentLocation.type == .file { + if currentLocation.type == .folder { addCrumb(title: currentLocation.displayName(in: clientContext), icon: currentLocation.displayIcon(in: clientContext), location: currentLocation) } @@ -183,23 +121,13 @@ public extension OCLocation { } // Drive name - if includeDriveName { - var location: OCLocation? - - if let driveID = self.driveID { - location = OCLocation(driveID: driveID, path: "/") - } else { - // avoid duplicate OC10 root breadcrumb when the server name is also included - effectiveIncludeServername = true // alternative would be: location = .legacyRoot - but then there's Files /and/ the server name in the breadcrumbs if includeServername already == true; so for consistency, instead of a "Files" breadcrumb the server name is shown - } - - if let location { - addCrumb(title: location.displayName(in: clientContext), icon: location.displayIcon(in: clientContext), location: location) - } + if let driveID = self.driveID, includeDriveName { + let location = OCLocation(driveID: driveID, path: "/") + addCrumb(title: location.displayName(in: clientContext), icon: location.displayIcon(in: clientContext), location: location) } // Server name - if let bookmark = clientContext.core?.bookmark, effectiveIncludeServername { + if let bookmark = clientContext.core?.bookmark, includeServerName { addCrumb(title: bookmark.displayName ?? bookmark.shortName, icon: OCSymbol.icon(forSymbolName: "server.rack"), location: (self.driveID == nil) ? OCLocation.legacyRoot : nil) } diff --git a/ownCloudAppShared/SDK Extensions/OCAction+UIAction.swift b/ownCloudAppShared/SDK Extensions/OCAction+UIAction.swift deleted file mode 100644 index afedd6db5..000000000 --- a/ownCloudAppShared/SDK Extensions/OCAction+UIAction.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// OCAction+UIAction.swift -// ownCloudAppShared -// -// Created by Felix Schwarz on 23.10.23. -// Copyright © 2023 ownCloud GmbH. All rights reserved. -// - -/* - * Copyright (C) 2023, ownCloud GmbH. - * - * This code is covered by the GNU Public License Version 3. - * - * For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ - * You should have received a copy of this license along with this program. If not, see . - * - */ - -import UIKit -import ownCloudSDK - -extension OCAction { - func uiAction(with options: [OCActionRunOptionKey : Any]? = nil) -> UIAction { - return UIAction(title: title, image: icon, attributes: [], handler: { action in - self.run(options: options) - }) - } -} diff --git a/ownCloudAppShared/UIKit Extension/UIView+Extension.swift b/ownCloudAppShared/UIKit Extension/UIView+Extension.swift index b281fd66f..b2d6f6b3d 100644 --- a/ownCloudAppShared/UIKit Extension/UIView+Extension.swift +++ b/ownCloudAppShared/UIKit Extension/UIView+Extension.swift @@ -60,20 +60,4 @@ public extension UIView { return nil } - - // MARK: - View controller - var hostingViewController: UIViewController? { - var responder: UIResponder? = self - var hostViewController: UIViewController? - - while hostViewController == nil && responder != nil { - if let viewController = responder as? UIViewController { - hostViewController = viewController - } - - responder = responder?.next - } - - return hostViewController - } } diff --git a/ownCloudAppShared/User Interface/SegmentView/UIView+EmbedAndLayout.swift b/ownCloudAppShared/User Interface/SegmentView/UIView+EmbedAndLayout.swift index 0820602e5..4a74781d6 100644 --- a/ownCloudAppShared/User Interface/SegmentView/UIView+EmbedAndLayout.swift +++ b/ownCloudAppShared/User Interface/SegmentView/UIView+EmbedAndLayout.swift @@ -23,19 +23,19 @@ public extension UIView { typealias ConstraintsModifier = (_ constraintSet: ConstraintSet) -> ConstraintSet struct ConstraintSet { - public var firstLeadingOrTopConstraint: NSLayoutConstraint? - public var lastTrailingOrBottomConstraint: NSLayoutConstraint? + var firstLeadingOrTopConstraint: NSLayoutConstraint? + var lastTrailingOrBottomConstraint: NSLayoutConstraint? } struct AnchorSet { - public var leadingAnchor: NSLayoutXAxisAnchor - public var trailingAnchor: NSLayoutXAxisAnchor + var leadingAnchor: NSLayoutXAxisAnchor + var trailingAnchor: NSLayoutXAxisAnchor - public var topAnchor: NSLayoutYAxisAnchor - public var bottomAnchor: NSLayoutYAxisAnchor + var topAnchor: NSLayoutYAxisAnchor + var bottomAnchor: NSLayoutYAxisAnchor - public var centerXAnchor: NSLayoutXAxisAnchor - public var centerYAnchor: NSLayoutYAxisAnchor + var centerXAnchor: NSLayoutXAxisAnchor + var centerYAnchor: NSLayoutYAxisAnchor } var defaultAnchorSet : AnchorSet { @@ -116,7 +116,7 @@ public extension UIView { return constraintSet } - @discardableResult func embedVertically(views: [UIView], insets: NSDirectionalEdgeInsets, enclosingAnchors: AnchorSet? = nil, spacingProvider: SpacingProvider? = nil, centered: Bool = true, constraintsModifier: ConstraintsModifier? = nil) -> ConstraintSet { + @discardableResult func embedVertically(views: [UIView], insets: NSDirectionalEdgeInsets, enclosingAnchors: AnchorSet? = nil, spacingProvider: SpacingProvider? = nil, constraintsModifier: ConstraintsModifier? = nil) -> ConstraintSet { var viewIdx : Int = 0 var previousView: UIView? var embedConstraints: [NSLayoutConstraint] = [] @@ -143,18 +143,11 @@ public extension UIView { } // - horizontal position + insets - if centered { - embedConstraints.append(contentsOf: [ - view.centerXAnchor.constraint(equalTo: anchorSet.centerXAnchor), - view.leadingAnchor.constraint(greaterThanOrEqualTo: anchorSet.leadingAnchor, constant: insets.leading), - view.trailingAnchor.constraint(lessThanOrEqualTo: anchorSet.trailingAnchor, constant: -insets.trailing) - ]) - } else { - embedConstraints.append(contentsOf: [ - view.leadingAnchor.constraint(equalTo: anchorSet.leadingAnchor, constant: insets.leading), - view.trailingAnchor.constraint(equalTo: anchorSet.trailingAnchor, constant: -insets.trailing) - ]) - } + embedConstraints.append(contentsOf: [ + view.centerXAnchor.constraint(equalTo: anchorSet.centerXAnchor), + view.leadingAnchor.constraint(greaterThanOrEqualTo: anchorSet.leadingAnchor, constant: insets.leading), + view.trailingAnchor.constraint(lessThanOrEqualTo: anchorSet.trailingAnchor, constant: -insets.trailing) + ]) // - bottom if viewIdx == (views.count-1) { @@ -201,12 +194,10 @@ public extension UIView { return constraints } - @discardableResult func embed(centered view: UIView, minimumInsets insets: NSDirectionalEdgeInsets = .zero, fixedSize: CGSize? = nil, minimumSize: CGSize? = nil, maximumSize: CGSize? = nil, enclosingAnchors: AnchorSet? = nil, constraintsOnly: Bool = false) -> [NSLayoutConstraint] { - if !constraintsOnly { - view.translatesAutoresizingMaskIntoConstraints = false + @discardableResult func embed(centered view: UIView, minimumInsets insets: NSDirectionalEdgeInsets = .zero, fixedSize: CGSize? = nil, minimumSize: CGSize? = nil, maximumSize: CGSize? = nil, enclosingAnchors: AnchorSet? = nil) -> [NSLayoutConstraint] { + view.translatesAutoresizingMaskIntoConstraints = false - addSubview(view) - } + addSubview(view) var constraints: [NSLayoutConstraint] let anchorSet = enclosingAnchors ?? defaultAnchorSet @@ -241,9 +232,7 @@ public extension UIView { ] } - if !constraintsOnly { - NSLayoutConstraint.activate(constraints) - } + NSLayoutConstraint.activate(constraints) return constraints } diff --git a/ownCloudAppShared/User Interface/StaticTableView/StaticTableViewRow.swift b/ownCloudAppShared/User Interface/StaticTableView/StaticTableViewRow.swift index ff607e669..aabbad6fa 100644 --- a/ownCloudAppShared/User Interface/StaticTableView/StaticTableViewRow.swift +++ b/ownCloudAppShared/User Interface/StaticTableView/StaticTableViewRow.swift @@ -528,21 +528,6 @@ open class StaticTableViewRow : NSObject, UITextFieldDelegate { return true } - public func textFieldShouldClear(_ textField: UITextField) -> Bool { - if let requiredFileExtension { - textField.text = "." + requiredFileExtension - textField.selectedTextRange = textField.textRange(from: textField.beginningOfDocument, to: textField.beginningOfDocument) - return false - } - return true - } - - open var requiredFileExtension: String? { - didSet { - (textField as? ThemeCSSTextField)?.requiredFileExtension = requiredFileExtension - } - } - // MARK: - Labels convenience public init(label: String, accessoryView: UIView? = nil, identifier: String? = nil) { self.init() diff --git a/ownCloudAppShared/User Interface/Theme/CSS/README.md b/ownCloudAppShared/User Interface/Theme/CSS/README.md index 70f47ed03..aeb32303f 100644 --- a/ownCloudAppShared/User Interface/Theme/CSS/README.md +++ b/ownCloudAppShared/User Interface/Theme/CSS/README.md @@ -113,7 +113,7 @@ getInteger | `Int` getCGFloat | `CGFloat` getBool | `Boolean`, `String` (`true` and `false`) getUserInterfaceStyle | `UIUserInterfaceStyle`, `Int`, `String` (`unspecified`, `light`, `dark`) -getStatusBarStyle | `UIStatusBarStyle`, `Int`, `String` (`default`, `lightContent`, `darkContent`, `white`, `black`) +getStatusBarStyle | `UIStatusBarStyle`, `Int`, `String` (`default`, `lightContent`, `darkContent`) getBarStyle | `UIBarStyle`, `Int`, `String` (`default`, `black`) getKeyboardAppearance | `UIKeyboardAppearance`, `Int`, `String` (`default`, `light`, `dark`) getActivityIndicatorStyle | `UIActivityIndicatorView.Style`, `Int`, `String` (`medium`, `large`) @@ -187,108 +187,33 @@ Matching: A way to change the value of the `stroke` property, then, would be to add a more specific record, f.ex. for `collection.cell.sortBar` - or possibly for `sortBar` directly (the last selector is weighted much higher). ## Adding styling via branding -Depending on how a client is branded, different options are used to add CSS records to f.ex. the `Branding.plist`. - -In all cases, the additional CSS records follow this format: +Additional CSS records can be added through the usual branding options, including `Branding.plist`, by providing an array of css records following this format: ``` selector1.selector2….property: value ``` -See *Debugging selectors and matching* > *Usage in practice* above for how to determine the selectors of a view on screen. - -### Branding on top of default themes -If `branding.theme-definitions` is **not** used, the app provides themes for light mode and dark mode to branded clients, with support for light customization through branding: -Option | Description ---|-- -`branding.theme-colors`| Values to use in system-color-based themes for branded clients. Mutually exclusive with theme-definitions. -`branding.theme-css-records` | CSS records to add to the CSS space of system-color-based themes for branded clients. Mutually exclusive with theme-definitions. - -Both options can be used together. - -#### Using `branding.theme-css-records` -Example for a `Branding.plist` filling the logo in the sidebar's navigation bar with red and the account pill with green: +Example for a `Branding.plist` that fills the logo in the sidebar's navigation bar with red color: ```xml -branding.theme-css-records +branding.theme-definitions$[0].cssRecords sidebar.navigationBar.logo.stroke: #ff0000 - sidebar.account.fill: #00ff00 ``` -Example in flat notation: -```xml -branding.theme-css-records$[0] -sidebar.navigationBar.logo.stroke: #ff0000 -branding.theme-css-records$[1] -sidebar.account.fill: #00ff00 -``` - -#### Using `branding.theme-colors` -For commonly branded elements, the app supports the following aliases to be used in key-value pairs in `branding.theme-colors`: - -Alias | Value ---|-- -`tint-color` | Color to use as tint/accent color for controls (in hex notation). Replaces `branding.theme-tint-color`. -`branding-background-color` | Color to use as background color for brand views (in hex notation). -`setup-status-bar-style` | The status bar style in the setup wizard, affecting the status bar text color. Can be either `default`, `black` or `white`. -`file-icon-color` | Color to fill file icons with (in hex notation). -`folder-icon-color` | Color to fill folder icons with (in hex notation). - -Each alias can be expanded to one or more CSS addresses internally, so that the values set here can be assigned to the right elements - even after major UI changes or refactoring. - -Example: -```xml -branding.theme-colors - - tint-color - #ff0000 - branding-background-color - #0ff0f0 - setup-status-bar-style - black - folder-icon-color - #00ff00 - file-icon-color - #0000ff - -```` - -Example in flat notation: -```xml -branding.theme-colors$tint-color -#ff0000 -branding.theme-colors$branding-background-color -#0ff0f0 -branding.theme-colors$setup-status-bar-style -black -branding.theme-colors$folder-icon-color -#00ff00 -branding.theme-colors$file-icon-color -#0000ff -```` - -### Branding with fully custom themes -For clients branded with fully custom themes via `branding.theme-definitions`, an array of additional CSS records can be added for each theme definition. - -Example for a `Branding.plist` filling the logo in the sidebar's navigation bar with red and the account pill with green: +See *Debugging selectors and matching* > *Usage in practice* above for how to determine the selectors of a view on screen. -```xml -branding.theme-definitions$[0].cssRecords - - sidebar.navigationBar.logo.stroke: #ff0000 - sidebar.account.fill: #00ff00 - -``` +#### Icon color CSS selectors +Icon colors are now also configured via CSS selectors: -Example in flat notation: -```xml -branding.theme-definitions$[0].cssRecords[0] -sidebar.navigationBar.logo.stroke: #ff0000 -branding.theme-definitions$[0].cssRecords[1] -sidebar.account.fill: #00ff00 -``` +TVG/Legacy Color | CSS selector string +------------------|------------------------------------ +`folderFillColor` | `vectorImage.folderColor.fill` +`fileFillColor` | `vectorImage.fileColor.fill` +`logoFillColor` | `vectorImage.logoColor.fill` +`iconFillColor` | `vectorImage.iconColor.fill` +`symbolFillColor` | `vectorImage.symbolColor.fill` ### Reference #### Selectors @@ -309,18 +234,7 @@ Property | Type | Description / Values `cornerRadius` | float | Corner radius (not widely used) `style` | `UIUserInterfaceStyle` | `unspecified`, `light`, `dark` `barStyle` | `UIBarStyle` | `default`, `black` -`statusBarStyle` | `UIStatusBarStyle` | `default`, `lightContent`, `darkContent`, `black`, `white` +`statusBarStyle` | `UIStatusBarStyle` | `default`, `lightContent`, `darkContent` `blurEffectStyle` | `UIBlurEffect.Style` | `regular`, `light`, `dark` `keyboardAppearance` | `UIKeyboardAppearance` | `default`, `light`, `dark` `activityIndicatorStyle` | `UIActivityIndicatorView.Style` | `medium`, `large` - -#### Icon color CSS selectors -Icon colors are now also configured via CSS selectors: - -TVG/Legacy Color | CSS selector string -------------------|------------------------------------ -`folderFillColor` | `vectorImage.folderColor.fill` -`fileFillColor` | `vectorImage.fileColor.fill` -`logoFillColor` | `vectorImage.logoColor.fill` -`iconFillColor` | `vectorImage.iconColor.fill` -`symbolFillColor` | `vectorImage.symbolColor.fill` diff --git a/ownCloudAppShared/User Interface/Theme/CSS/ThemeCSS.swift b/ownCloudAppShared/User Interface/Theme/CSS/ThemeCSS.swift index 46f50cde7..aabb1e872 100644 --- a/ownCloudAppShared/User Interface/Theme/CSS/ThemeCSS.swift +++ b/ownCloudAppShared/User Interface/Theme/CSS/ThemeCSS.swift @@ -317,8 +317,6 @@ open class ThemeCSS: NSObject { case "default": return .default case "lightContent": return .lightContent case "darkContent": return .darkContent - case "white": return .lightContent - case "black": return .darkContent default: break } } diff --git a/ownCloudAppShared/User Interface/Theme/CSS/Views/ThemeCSSTextField.swift b/ownCloudAppShared/User Interface/Theme/CSS/Views/ThemeCSSTextField.swift index 4b37e38e7..d22b6e34c 100644 --- a/ownCloudAppShared/User Interface/Theme/CSS/Views/ThemeCSSTextField.swift +++ b/ownCloudAppShared/User Interface/Theme/CSS/Views/ThemeCSSTextField.swift @@ -18,20 +18,9 @@ import UIKit -public extension UITextInput { - func range(from textRange: UITextRange) -> NSRange { - let startOffset = offset(from: beginningOfDocument, to: textRange.start) - let endOffset = offset(from: beginningOfDocument, to: textRange.end) - - return NSRange(location: startOffset, length: endOffset-startOffset+1) - } -} - public class ThemeCSSTextField: UITextField, Themeable { private var hasRegistered : Bool = false - open var requiredFileExtension: String? - override open func didMoveToWindow() { super.didMoveToWindow() @@ -52,26 +41,4 @@ public class ThemeCSSTextField: UITextField, Themeable { open func applyThemeCollection(theme: Theme, collection: ThemeCollection, event: ThemeEvent) { self.applyThemeCollection(collection) } - - public override func shouldChangeText(in range: UITextRange, replacementText: String) -> Bool { - if let requiredFileExtension, let previousText = text, - let textRange = Range(self.range(from: range), in: previousText) { - let newName = previousText.replacingCharacters(in: textRange, with: replacementText) - return (newName as NSString).pathExtension == requiredFileExtension || (newName == ".\(requiredFileExtension)") - } - - return super.shouldChangeText(in: range, replacementText: replacementText) - } - - public override var selectedTextRange: UITextRange? { - didSet { - if let requiredFileExtension { - if let selectedTextRange, - let maxAllowedPosition = position(from: endOfDocument, offset: -requiredFileExtension.count-1), - compare(selectedTextRange.end, to: maxAllowedPosition) == .orderedDescending { - self.selectedTextRange = textRange(from: selectedTextRange.start, to: maxAllowedPosition) - } - } - } - } } diff --git a/ownCloudAppShared/User Interface/Theme/NSObject+ThemeApplication.swift b/ownCloudAppShared/User Interface/Theme/NSObject+ThemeApplication.swift index 0e560e0b6..8f6a959ff 100644 --- a/ownCloudAppShared/User Interface/Theme/NSObject+ThemeApplication.swift +++ b/ownCloudAppShared/User Interface/Theme/NSObject+ThemeApplication.swift @@ -83,7 +83,7 @@ public extension NSObject { func applyThemeCollection(_ collection: ThemeCollection, itemStyle: ThemeItemStyle = .defaultForItem, itemState: ThemeItemState = .normal, cellState: UICellConfigurationState? = nil) { let css = collection.css - if let button = self as? UIButton, !(self is ThemeButton) { + if let button = self as? UIButton, (self as? ThemeButton) == nil { button.apply(css: css, properties: [.stroke]) } diff --git a/ownCloudAppShared/User Interface/Theme/ThemeCollection.swift b/ownCloudAppShared/User Interface/Theme/ThemeCollection.swift index d61680635..3cf6a354c 100644 --- a/ownCloudAppShared/User Interface/Theme/ThemeCollection.swift +++ b/ownCloudAppShared/User Interface/Theme/ThemeCollection.swift @@ -206,7 +206,7 @@ public class ThemeCollection : NSObject { return colorPairs } - init(darkBrandColor inDarkColor: UIColor, lightBrandColor inLightColor: UIColor, style: ThemeCollectionStyle = .dark, interfaceStyles: NSDictionary? = nil, useSystemColors: Bool = false, systemTintColor: UIColor? = nil) { + init(darkBrandColor darkColor: UIColor, lightBrandColor lightColor: UIColor, style: ThemeCollectionStyle = .dark, customColors: NSDictionary? = nil, genericColors: NSDictionary? = nil, interfaceStyles: NSDictionary? = nil) { var logoFillColor : UIColor? self.css = ThemeCSS() @@ -218,12 +218,8 @@ public class ThemeCollection : NSObject { var statusBarStyle : UIStatusBarStyle var barStyle : UIBarStyle - let styleTraitCollection = UITraitCollection(userInterfaceStyle: style.userInterfaceStyle) - - let darkBrandColor = inDarkColor.resolvedColor(with: styleTraitCollection) - let lightBrandColor = inLightColor.resolvedColor(with: styleTraitCollection) - - let resolvedSystemTintColor: UIColor = systemTintColor ?? .tintColor.resolvedColor(with: styleTraitCollection) + let darkBrandColor = darkColor + let lightBrandColor = lightColor /* Cells: @@ -245,8 +241,10 @@ public class ThemeCollection : NSObject { - confirm - .. */ - var lightBrandSet = ThemeColorSet.from(backgroundColor: lightBrandColor, tintColor: darkBrandColor, for: style.userInterfaceStyle) - let darkBrandSet = ThemeColorSet.from(backgroundColor: darkBrandColor, tintColor: lightBrandColor, for: style.userInterfaceStyle) + var lightBrandSet = ThemeColorSet.from(backgroundColor: lightColor, tintColor: darkColor, for: style.userInterfaceStyle) + let darkBrandSet = ThemeColorSet.from(backgroundColor: darkColor, tintColor: lightColor, for: style.userInterfaceStyle) + + let styleTraitCollection = UITraitCollection(userInterfaceStyle: interfaceStyle) var cellSet: ThemeColorSet var groupedCellSet: ThemeColorSet @@ -284,7 +282,7 @@ public class ThemeCollection : NSObject { var modalBackgroundColor: UIColor let lightBrandColors = ThemeColorCollection( - backgroundColor: lightBrandColor, + backgroundColor: lightColor, tintColor: UIColor.white, labelColor: UIColor.white, secondaryLabelColor: UIColor.lightGray, @@ -323,25 +321,25 @@ public class ThemeCollection : NSObject { navigationBarSet = darkBrandSet toolbarSet = darkBrandSet - cellSet = ThemeColorSet.from(backgroundColor: UIColor(hex: 0), tintColor: lightBrandColor, for: interfaceStyle) + cellSet = ThemeColorSet.from(backgroundColor: UIColor(hex: 0), tintColor: lightColor, for: interfaceStyle) cellStateSet = ThemeColorStateSet.from(colorSet: cellSet, for: interfaceStyle) - collectionBackgroundColor = darkBrandColor.darker(0.1) + collectionBackgroundColor = darkColor.darker(0.1) - groupedCellSet = ThemeColorSet.from(backgroundColor: darkBrandColor, tintColor: lightBrandColor, for: interfaceStyle) + groupedCellSet = ThemeColorSet.from(backgroundColor: darkColor, tintColor: lightColor, for: interfaceStyle) groupedCellStateSet = ThemeColorStateSet.from(colorSet: groupedCellSet, for: interfaceStyle) - groupedCollectionBackgroundColor = useSystemColors ? .systemGroupedBackground.resolvedColor(with: styleTraitCollection) : navigationBarSet.backgroundColor.darker(0.3) + groupedCollectionBackgroundColor = navigationBarSet.backgroundColor.darker(0.3) contentNavigationBarSet = cellSet contentToolbarSet = cellSet sidebarCellStateSet = ThemeColorStateSet.from(colorSet: darkBrandSet, for: interfaceStyle) - sidebarCellStateSet.selected.backgroundColor = useSystemColors ? resolvedSystemTintColor : sidebarCellStateSet.regular.labelColor - sidebarCellStateSet.selected.labelColor = useSystemColors ? .white : sidebarCellStateSet.regular.backgroundColor - sidebarCellStateSet.selected.iconColor = sidebarCellStateSet.selected.labelColor + sidebarCellStateSet.selected.backgroundColor = sidebarCellStateSet.regular.labelColor + sidebarCellStateSet.selected.labelColor = sidebarCellStateSet.regular.backgroundColor + sidebarCellStateSet.selected.iconColor = sidebarCellStateSet.regular.backgroundColor sidebarLogoIconColor = .white sidebarLogoLabel = .white - iconSymbolColor = lightBrandColor + iconSymbolColor = lightColor separatorColor = .darkGray @@ -350,7 +348,7 @@ public class ThemeCollection : NSObject { groupedSectionHeaderColor = .lightGray groupedSectionFooterColor = .lightGray - moreHeaderBackgroundColor = darkBrandColor.lighter(0.05) + moreHeaderBackgroundColor = darkColor.lighter(0.05) modalBackgroundColor = darkBrandColor @@ -378,10 +376,10 @@ public class ThemeCollection : NSObject { sidebarAccountCellSet = ThemeColorSet.from(backgroundColor: .white, tintColor: .white, for: interfaceStyle) accountCellSet = sidebarAccountCellSet - navigationBarSet = ThemeColorSet.from(backgroundColor: .systemBackground.resolvedColor(with: styleTraitCollection), tintColor: lightBrandColor, for: interfaceStyle) + navigationBarSet = ThemeColorSet.from(backgroundColor: .systemBackground.resolvedColor(with: styleTraitCollection), tintColor: lightColor, for: interfaceStyle) toolbarSet = navigationBarSet - cellSet = ThemeColorSet.from(backgroundColor: .systemBackground.resolvedColor(with: styleTraitCollection), tintColor: lightBrandColor, for: interfaceStyle) + cellSet = ThemeColorSet.from(backgroundColor: .systemBackground.resolvedColor(with: styleTraitCollection), tintColor: lightColor, for: interfaceStyle) cellStateSet = ThemeColorStateSet.from(colorSet: cellSet, for: interfaceStyle) collectionBackgroundColor = cellSet.backgroundColor @@ -393,14 +391,14 @@ public class ThemeCollection : NSObject { contentToolbarSet = cellSet sidebarCellStateSet = ThemeColorStateSet.from(colorSet: cellSet, for: interfaceStyle) - sidebarCellStateSet.regular.backgroundColor = .secondarySystemBackground.resolvedColor(with: styleTraitCollection) + sidebarCellStateSet.regular.backgroundColor = .secondarySystemBackground.resolvedColor(with: styleTraitCollection) sidebarCellStateSet.selected.labelColor = .white sidebarCellStateSet.selected.iconColor = .white - sidebarCellStateSet.selected.backgroundColor = useSystemColors ? resolvedSystemTintColor : darkBrandColor + sidebarCellStateSet.selected.backgroundColor = darkBrandColor sidebarLogoIconColor = darkBrandColor sidebarLogoLabel = darkBrandColor - iconSymbolColor = darkBrandColor + iconSymbolColor = darkColor sectionHeaderColor = .label.resolvedColor(with: styleTraitCollection) sectionFooterColor = .secondaryLabel.resolvedColor(with: styleTraitCollection) @@ -464,9 +462,6 @@ public class ThemeCollection : NSObject { ThemeCSSRecord(selectors: [.navigationBar, .label], property: .stroke, value: navigationBarSet.labelColor), ThemeCSSRecord(selectors: [.navigationBar], property: .fill, value: navigationBarSet.backgroundColor), - ThemeCSSRecord(selectors: [.navigationBar, .popupButton, .icon],property: .stroke, value: navigationBarSet.tintColor), - ThemeCSSRecord(selectors: [.navigationBar, .popupButton, .icon],property: .fill, value: UIColor(white: 0.5, alpha: 0.3)), - // - Toolbar ThemeCSSRecord(selectors: [.toolbar], property: .stroke, value: toolbarSet.tintColor), ThemeCSSRecord(selectors: [.toolbar], property: .fill, value: toolbarSet.backgroundColor), @@ -533,9 +528,6 @@ public class ThemeCollection : NSObject { ThemeCSSRecord(selectors: [.insetGrouped, .table, .cell], property: .fill, value: groupedCellStateSet.regular.backgroundColor), ThemeCSSRecord(selectors: [.insetGrouped, .table, .highlighted, .cell], property: .fill, value: groupedCellStateSet.highlighted.backgroundColor), - ThemeCSSRecord(selectors: [.insetGrouped, .table, .sectionHeader], property: .stroke, value: groupedSectionHeaderColor), - ThemeCSSRecord(selectors: [.insetGrouped, .table, .sectionFooter], property: .stroke, value: groupedSectionFooterColor), - ThemeCSSRecord(selectors: [.table, .sectionHeader], property: .stroke, value: sectionHeaderColor), ThemeCSSRecord(selectors: [.table, .sectionFooter], property: .stroke, value: sectionFooterColor), @@ -679,8 +671,8 @@ public class ThemeCollection : NSObject { ThemeCSSRecord(selectors: [.more, .favorite, .disabled], property: .stroke, value: favoriteDisabledColor), // - TVG icon colors - // ThemeCSSRecord(selectors: [.vectorImage, .folderColor], property: .fill, value: iconSymbolColor), // make TVG files use default colors extracted from original SVG files - // ThemeCSSRecord(selectors: [.vectorImage, .fileColor], property: .fill, value: iconSymbolColor), // make TVG files use default colors extracted from original SVG files + ThemeCSSRecord(selectors: [.vectorImage, .folderColor], property: .fill, value: iconSymbolColor), + ThemeCSSRecord(selectors: [.vectorImage, .fileColor], property: .fill, value: iconSymbolColor), ThemeCSSRecord(selectors: [.vectorImage, .logoColor], property: .fill, value: logoFillColor ?? UIColor.white), ThemeCSSRecord(selectors: [.vectorImage, .iconColor], property: .fill, value: iconSymbolColor), ThemeCSSRecord(selectors: [.vectorImage, .symbolColor], property: .fill, value: iconSymbolColor), @@ -694,23 +686,6 @@ public class ThemeCollection : NSObject { ThemeCSSRecord(selectors: [.welcome, .message, .button], property: .fill, value: darkBrandColor), ThemeCSSRecord(selectors: [.welcome], property: .statusBarStyle, value: UIStatusBarStyle.lightContent), - // Account Setup - ThemeCSSRecord(selectors: [.accountSetup, .message, .title], property: .stroke, value: UIColor.white), - ThemeCSSRecord(selectors: [.accountSetup, .header, .title], property: .stroke, value: UIColor.white), - ThemeCSSRecord(selectors: [.accountSetup, .welcome, .icon], property: .fill, value: darkBrandColor), - ThemeCSSRecord(selectors: [.accountSetup, .step, .title], property: .stroke, value: primaryLabelColor), - ThemeCSSRecord(selectors: [.accountSetup, .step, .message], property: .stroke, value: secondaryLabelColor), - ThemeCSSRecord(selectors: [.accountSetup, .step, .background], property: .fill, value: collectionBackgroundColor), - ThemeCSSRecord(selectors: [.accountSetup, .step, .button, .filled], property: .stroke, value: UIColor.white), - ThemeCSSRecord(selectors: [.accountSetup, .step, .button, .filled], property: .fill, value: lightBrandColor), - ThemeCSSRecord(selectors: [.accountSetup, .help, .subtitle], property: .stroke, value: UIColor.lightGray), - ThemeCSSRecord(selectors: [.accountSetup, .help, .button], property: .stroke, value: lightBrandColor), - ThemeCSSRecord(selectors: [.accountSetup, .help, .button], property: .fill, value: UIColor.clear), - ThemeCSSRecord(selectors: [.accountSetup], property: .fill, value: darkBrandColor), - ThemeCSSRecord(selectors: [.accountSetup], property: .statusBarStyle, value: UIStatusBarStyle.lightContent), - - ThemeCSSRecord(selectors: [.certificateSummary], property: .fill, value: UIColor.clear), - // Side Bar // - Interface Style ThemeCSSRecord(selectors: [.sidebar], property: .style, value: UIUserInterfaceStyle.light), @@ -739,14 +714,14 @@ public class ThemeCollection : NSObject { ThemeCSSRecord(selectors: [.sidebar, .account, .disconnect], property: .fill, value: sidebarAccountCellSet.labelColor), // - Navigation Bar - ThemeCSSRecord(selectors: [.sidebar, .navigationBar], property: .stroke, value: lightBrandColor), + ThemeCSSRecord(selectors: [.sidebar, .navigationBar], property: .stroke, value: lightColor), ThemeCSSRecord(selectors: [.sidebar, .navigationBar], property: .fill, value: nil), ThemeCSSRecord(selectors: [.sidebar, .navigationBar, .logo], property: .stroke, value: sidebarLogoIconColor), ThemeCSSRecord(selectors: [.sidebar, .navigationBar, .logo, .label],property: .stroke, value: sidebarLogoLabel), // - Toolbar ThemeCSSRecord(selectors: [.sidebar, .toolbar], property: .fill, value: sidebarCellStateSet.regular.backgroundColor), - ThemeCSSRecord(selectors: [.sidebar, .toolbar], property: .stroke, value: lightBrandColor), + ThemeCSSRecord(selectors: [.sidebar, .toolbar], property: .stroke, value: lightColor), // Content Area ThemeCSSRecord(selectors: [.content], property: .fill, value: collectionBackgroundColor), @@ -785,13 +760,7 @@ public class ThemeCollection : NSObject { _iconColors = [:] _iconColors?["folderFillColor"] = css.getColor(.fill, selectors: [.vectorImage, .folderColor], for: nil)?.hexString() - _iconColors?["fileFillColor"] = css.getColor(.fill, selectors: [.vectorImage, .fileColor], for: nil)?.hexString() - _iconColors?["documentFileFillColor"] = css.getColor(.fill, selectors: [.vectorImage, .documentFileColor], for: nil)?.hexString() - _iconColors?["presentationFileFillColor"] = css.getColor(.fill, selectors: [.vectorImage, .presentationFileColor], for: nil)?.hexString() - _iconColors?["spreadsheetFileFillColor"] = css.getColor(.fill, selectors: [.vectorImage, .spreadsheetFileColor], for: nil)?.hexString() - _iconColors?["pdfFileFillColor"] = css.getColor(.fill, selectors: [.vectorImage, .pdfFileColor], for: nil)?.hexString() - _iconColors?["logoFillColor"] = css.getColor(.fill, selectors: [.vectorImage, .logoColor], for: nil)?.hexString() _iconColors?["iconFillColor"] = css.getColor(.fill, selectors: [.vectorImage, .iconColor], for: nil)?.hexString() _iconColors?["symbolFillColor"] = css.getColor(.fill, selectors: [.vectorImage, .symbolColor], for: nil)?.hexString() @@ -804,10 +773,6 @@ public class ThemeCollection : NSObject { extension ThemeCSSSelector { static let folderColor = ThemeCSSSelector(rawValue: "folderColor") static let fileColor = ThemeCSSSelector(rawValue: "fileColor") - static let documentFileColor = ThemeCSSSelector(rawValue: "documentFileColor") - static let presentationFileColor = ThemeCSSSelector(rawValue: "presentationFileColor") - static let spreadsheetFileColor = ThemeCSSSelector(rawValue: "spreadsheetFileColor") - static let pdfFileColor = ThemeCSSSelector(rawValue: "pdfFileColor") static let logoColor = ThemeCSSSelector(rawValue: "logoColor") static let iconColor = ThemeCSSSelector(rawValue: "iconColor") static let symbolColor = ThemeCSSSelector(rawValue: "symbolColor") diff --git a/ownCloudAppShared/User Interface/Theme/ThemeStyle+DefaultStyles.swift b/ownCloudAppShared/User Interface/Theme/ThemeStyle+DefaultStyles.swift index 70c12f29d..4e52656af 100644 --- a/ownCloudAppShared/User Interface/Theme/ThemeStyle+DefaultStyles.swift +++ b/ownCloudAppShared/User Interface/Theme/ThemeStyle+DefaultStyles.swift @@ -26,10 +26,11 @@ extension UIColor { } extension ThemeStyle { - static public func systemLight(with tintColor: UIColor? = nil, cssRecordStrings: [String]? = nil) -> ThemeStyle { - return (ThemeStyle(styleIdentifier: "com.owncloud.light", darkStyleIdentifier: "com.owncloud.dark", localizedName: "Light".localized, lightColor: tintColor ?? .tintColor, darkColor: .label, themeStyle: .light, useSystemColors: true, systemTintColor: tintColor, cssRecordStrings: cssRecordStrings)) + static public var ownCloudLight : ThemeStyle { + return (ThemeStyle(styleIdentifier: "com.owncloud.light", darkStyleIdentifier: "com.owncloud.dark", localizedName: "Light".localized, lightColor: .ownCloudLightColor, darkColor: .ownCloudDarkColor, themeStyle: .light)) } - static public func systemDark(with tintColor: UIColor? = nil, cssRecordStrings: [String]? = nil) -> ThemeStyle { - return (ThemeStyle(styleIdentifier: "com.owncloud.dark", localizedName: "Dark".localized, lightColor: tintColor ?? .tintColor, darkColor: .secondarySystemGroupedBackground, themeStyle: .dark, useSystemColors: true, systemTintColor: tintColor, cssRecordStrings: cssRecordStrings)) + + static public var ownCloudDark : ThemeStyle { + return (ThemeStyle(styleIdentifier: "com.owncloud.dark", localizedName: "Dark".localized, lightColor: .ownCloudLightColor, darkColor: .ownCloudDarkColor, themeStyle: .dark)) } } diff --git a/ownCloudAppShared/User Interface/Theme/ThemeStyle+Extensions.swift b/ownCloudAppShared/User Interface/Theme/ThemeStyle+Extensions.swift index e9b8e2876..a64fd1c12 100644 --- a/ownCloudAppShared/User Interface/Theme/ThemeStyle+Extensions.swift +++ b/ownCloudAppShared/User Interface/Theme/ThemeStyle+Extensions.swift @@ -47,7 +47,7 @@ extension ThemeStyle { Log.error("Couldn't get defaultStyle") - return ThemeStyle.systemDark() + return ThemeStyle.ownCloudDark } static public var preferredStyle : ThemeStyle { @@ -100,11 +100,13 @@ extension ThemeStyle { if self.followSystemAppearance { if ThemeStyle.userInterfaceStyle() == .dark { - if let style = ThemeStyle.forIdentifier("com.owncloud.dark") { + if let darkStyleIdentifier = ThemeStyle.preferredStyle.darkStyleIdentifier, let style = ThemeStyle.forIdentifier(darkStyleIdentifier) { + ThemeStyle.preferredStyle = style applyStyle = style } } else { - if let style = ThemeStyle.forIdentifier("com.owncloud.light") { + if ThemeStyle.preferredStyle.themeStyle == .dark, let style = ThemeStyle.availableStyles(for: [.light])?.first { + ThemeStyle.preferredStyle = style applyStyle = style } } @@ -142,7 +144,7 @@ extension ThemeStyle { } if followSystemAppearance == nil { - followSystemAppearance = true + followSystemAppearance = false } return followSystemAppearance! @@ -183,8 +185,8 @@ extension ThemeStyle { static public func registerDefaultStyles() { if !Branding.shared.setupThemeStyles() { - OCExtensionManager.shared.addExtension(ThemeStyle.systemLight().themeStyleExtension(isDefault: true)) - OCExtensionManager.shared.addExtension(ThemeStyle.systemDark().themeStyleExtension()) + OCExtensionManager.shared.addExtension(ThemeStyle.ownCloudLight.themeStyleExtension(isDefault: true)) + OCExtensionManager.shared.addExtension(ThemeStyle.ownCloudDark.themeStyleExtension()) } } diff --git a/ownCloudAppShared/User Interface/Theme/ThemeStyle.swift b/ownCloudAppShared/User Interface/Theme/ThemeStyle.swift index b156f8099..67548bb2f 100644 --- a/ownCloudAppShared/User Interface/Theme/ThemeStyle.swift +++ b/ownCloudAppShared/User Interface/Theme/ThemeStyle.swift @@ -30,22 +30,21 @@ public class ThemeStyle : NSObject { public var darkStyleIdentifier: String? + public var customColors : NSDictionary? + public var genericColors : NSDictionary? public var styles : NSDictionary? - public var useSystemColors: Bool - public var systemTintColor: UIColor? - public var cssRecordStrings: [String]? - public init(styleIdentifier: String, darkStyleIdentifier darkIdentifier: String? = nil, localizedName name: String, lightColor lColor: UIColor, darkColor dColor: UIColor, themeStyle style: ThemeCollectionStyle = .light, useSystemColors: Bool = false, systemTintColor: UIColor? = nil, interfaceStyles: NSDictionary? = nil, cssRecordStrings: [String]? = nil) { + public init(styleIdentifier: String, darkStyleIdentifier darkIdentifier: String? = nil, localizedName name: String, lightColor lColor: UIColor, darkColor dColor: UIColor, themeStyle style: ThemeCollectionStyle = .light, customColors: NSDictionary? = nil, genericColors: NSDictionary? = nil, interfaceStyles: NSDictionary? = nil, cssRecordStrings: [String]? = nil) { self.identifier = styleIdentifier self.darkStyleIdentifier = darkIdentifier self.localizedName = name self.lightColor = lColor self.darkColor = dColor self.themeStyle = style - self.useSystemColors = useSystemColors - self.systemTintColor = systemTintColor + self.customColors = customColors + self.genericColors = genericColors self.styles = interfaceStyles self.cssRecordStrings = cssRecordStrings } @@ -108,7 +107,7 @@ public extension ThemeCSSRecord { public extension ThemeCollection { convenience init(with style: ThemeStyle) { - self.init(darkBrandColor: style.darkColor, lightBrandColor: style.lightColor, style: style.themeStyle, interfaceStyles: style.styles, useSystemColors: style.useSystemColors, systemTintColor: style.systemTintColor) + self.init(darkBrandColor: style.darkColor, lightBrandColor: style.lightColor, style: style.themeStyle, customColors: style.customColors, genericColors: style.genericColors, interfaceStyles: style.styles) if let cssRecordStrings = style.cssRecordStrings, let records = ThemeCSSRecord.from(cssRecordStrings) { css.add(records: records) diff --git a/ownCloudAppShared/User Interface/Theme/UI/ThemeNavigationController.swift b/ownCloudAppShared/User Interface/Theme/UI/ThemeNavigationController.swift index 30b707514..830072b67 100644 --- a/ownCloudAppShared/User Interface/Theme/UI/ThemeNavigationController.swift +++ b/ownCloudAppShared/User Interface/Theme/UI/ThemeNavigationController.swift @@ -42,22 +42,6 @@ open class ThemeNavigationController: UINavigationController, Themeable { return Theme.shared.activeCollection.css.getStatusBarStyle(for: self) ?? .default } - open override var supportedInterfaceOrientations: UIInterfaceOrientationMask { - if let viewController = viewControllers.last { - return viewController.supportedInterfaceOrientations - } - - return super.supportedInterfaceOrientations - } - - open override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { - if let viewController = viewControllers.last { - return viewController.preferredInterfaceOrientationForPresentation - } - - return super.preferredInterfaceOrientationForPresentation - } - open override var childForStatusBarStyle: UIViewController? { return nil } diff --git a/removeExtension.sh b/removeExtension.sh deleted file mode 100755 index 69bf41518..000000000 --- a/removeExtension.sh +++ /dev/null @@ -1,84 +0,0 @@ -#! /bin/bash - - # Copyright (C) 2023, ownCloud GmbH. - # - # This code is covered by the GNU Public License Version 3. - # - # For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/ - # You should have received a copy of this license along with this program. If not, see . - - VERSION="1.0.0" - - #Define output formats - BOLD="$(tput bold)" - WARN="$(tput setaf 1)" - SUCCESS="$(tput setaf 2)" - INFO="$(tput setaf 3)" - NC="$(tput sgr0)" # No Color - - usage() - { - echo "Usage: $0 \"Path to IPA\" \"Target Name\"" - echo "Version: ${VERSION}" - echo "" - exit 1 - } - - - #Check if all required parameters exist - if [ $# -lt 2 ]; then - usage - fi - - echo - echo "${BOLD}${SUCCESS}Remove Extension Tool${NC}" - echo "Version ${VERSION}" - echo - - # Extract the file name from the path -IPA_FILE=$1 - APPTEMP="apptemp" - APPPATH="$APPTEMP/ownCloud.app" - - - # Delete previous temporal app folder if exist - if [ -d "$APPTEMP" ]; then - rm -rf "$APPTEMP" - fi - - # Create temp directory - mkdir $APPTEMP - - export PATH=$PATH:/usr/libexec - - # Unzip ipa - echo "${SUCCESS}Unzipping ipa…${NC}" - echo "" - - unzip -q "$IPA_FILE" -d "$APPTEMP" || { echo "${WARN}Failed to unzip ipa file${NC}"; exit 1; } - - if [ ! -d "$APPPATH" ]; then - APPPATH="$APPTEMP/Payload/ownCloud.app" - fi - -EXTENSIONPATH="$APPPATH/PlugIns/$2.appex" - -echo "${SUCCESS}Remove $EXTENSIONPATH ${NC}" - -# Remove the extension -rm -rf "$EXTENSIONPATH" - -# Delete input IPA file -rm -rf "$IPA_FILE" - -# Generate new Payload -echo "" -echo "${SUCCESS}Packing new ipa…${NC}" -pushd "$APPTEMP" -zip -q -r "../$IPA_FILE" * -popd - -# Delete previous temporal app folder if exist -if [ -d "$APPTEMP" ]; then - rm -rf "$APPTEMP" -fi \ No newline at end of file diff --git a/tools/GenerateDocs/templates/configuration.adoc.tmpl b/tools/GenerateDocs/templates/configuration.adoc.tmpl index ab9684dd5..f0826d78f 100644 --- a/tools/GenerateDocs/templates/configuration.adoc.tmpl +++ b/tools/GenerateDocs/templates/configuration.adoc.tmpl @@ -39,18 +39,6 @@ tag::{{$categoryTag | strings.ToLower }}[] {{end}} !=== {{end}} -{{- if has $option "possibleKeys"}} -[cols="1,1"] -!=== -! Key -! Value - -{{- range $possibleKeyIndex, $possibleKey := $option.possibleKeys }} -! `{{ $possibleKey.value }}` -! {{ $possibleKey.description }} -{{end}} -!=== -{{end}} |{{- $option.status}}{{if ne $option.status "debugOnly"}} `candidate`{{end}} {{end}} {{- end}}