Browse Source

Merge pull request #2530 from nextcloud/2460-add-other-nextcloud-apps-to-settings-as-suggestions

Add other Nextcloud apps to settings as suggestions
Marino Faggiana 1 year ago
parent
commit
50f5df214f

+ 20 - 19
Brand/NCBrand.swift

@@ -58,29 +58,30 @@ import UIKit
     @objc public var userAgent: String = "Nextcloud-iOS"                                                            // Don't touch me !!
 
     // BRAND ONLY
-    @objc public var use_login_web_personalized:        Bool = false                                                // Don't touch me !!
-    @objc public var use_AppConfig:                     Bool = false                                                // Don't touch me !!
-    @objc public var use_GroupApps:                     Bool = true                                                 // Don't touch me !!
+    @objc public var use_login_web_personalized:                   Bool = false                                                // Don't touch me !!
+    @objc public var use_AppConfig:                                Bool = false                                                // Don't touch me !!
+    @objc public var use_GroupApps:                                Bool = true                                                 // Don't touch me !!
 
     // Options
-    @objc public var use_default_auto_upload:           Bool = false
-    @objc public var use_themingColor:                  Bool = true
-    @objc public var use_themingLogo:                   Bool = false
-    @objc public var use_storeLocalAutoUploadAll:       Bool = false
-    @objc public var use_loginflowv2:                   Bool = false                                                // Don't touch me !!
-
-    @objc public var disable_intro:                     Bool = false
-    @objc public var disable_request_login_url:         Bool = false
-    @objc public var disable_multiaccount:              Bool = false
-    @objc public var disable_manage_account:            Bool = false
-    @objc public var disable_more_external_site:        Bool = false
-    @objc public var disable_openin_file:               Bool = false                                                // Don't touch me !!
-    @objc public var disable_crash_service:             Bool = false
-    @objc public var disable_log:                       Bool = false
-    @objc public var disable_mobileconfig:              Bool = false
+    @objc public var use_default_auto_upload:                      Bool = false
+    @objc public var use_themingColor:                             Bool = true
+    @objc public var use_themingLogo:                              Bool = false
+    @objc public var use_storeLocalAutoUploadAll:                  Bool = false
+    @objc public var use_loginflowv2:                              Bool = false                                                // Don't touch me !!
+
+    @objc public var disable_intro:                                Bool = false
+    @objc public var disable_request_login_url:                    Bool = false
+    @objc public var disable_multiaccount:                         Bool = false
+    @objc public var disable_manage_account:                       Bool = false
+    @objc public var disable_more_external_site:                   Bool = false
+    @objc public var disable_openin_file:                          Bool = false                                                // Don't touch me !!
+    @objc public var disable_crash_service:                        Bool = false
+    @objc public var disable_log:                                  Bool = false
+    @objc public var disable_mobileconfig:                         Bool = false
+    @objc public var disable_show_more_nextcloud_apps_in_settings: Bool = false
 
     // Internal option behaviour
-    @objc public var cleanUpDay:                        Int = 0                                                     // Set default "Delete, in the cache, all files older than" possible days value are: 0, 1, 7, 30, 90, 180, 365
+    @objc public var cleanUpDay:                                   Int = 0                                                     // Set default "Delete, in the cache, all files older than" possible days value are: 0, 1, 7, 30, 90, 180, 365
 
     // Info Paging
     enum NCInfoPagingTab: Int, CaseIterable {

+ 41 - 3
Nextcloud.xcodeproj/project.pbxproj

@@ -102,6 +102,7 @@
 		F31F69662A2F929600162F76 /* PreviewSnapshotsTesting in Frameworks */ = {isa = PBXBuildFile; productRef = F31F69652A2F929600162F76 /* PreviewSnapshotsTesting */; };
 		F31F69692A2F92F000162F76 /* SnapshotTestingHEIC in Frameworks */ = {isa = PBXBuildFile; productRef = F31F69682A2F92F000162F76 /* SnapshotTestingHEIC */; };
 		F32ED5062A2F254400EABA81 /* EnvVars.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = F30A96302A27AEBF00D7BCFE /* EnvVars.generated.swift */; };
+		F33AAF9A2A60394C006ECCBD /* NCMoreUserCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F33AAF992A60394C006ECCBD /* NCMoreUserCell.xib */; };
 		F343A4B32A1E01FF00DDA874 /* PHAsset+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343A4B22A1E01FF00DDA874 /* PHAsset+Extension.swift */; };
 		F343A4B42A1E084100DDA874 /* PHAsset+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343A4B22A1E01FF00DDA874 /* PHAsset+Extension.swift */; };
 		F343A4B52A1E084200DDA874 /* PHAsset+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343A4B22A1E01FF00DDA874 /* PHAsset+Extension.swift */; };
@@ -116,8 +117,13 @@
 		F343A4BF2A1E734600DDA874 /* Optional+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343A4BA2A1E734600DDA874 /* Optional+Extension.swift */; };
 		F343A4C02A1E734600DDA874 /* Optional+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343A4BA2A1E734600DDA874 /* Optional+Extension.swift */; };
 		F343A4C12A1E734600DDA874 /* Optional+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343A4BA2A1E734600DDA874 /* Optional+Extension.swift */; };
+		F39298972A3B12CB00509762 /* BaseNCMoreCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F39298962A3B12CB00509762 /* BaseNCMoreCell.swift */; };
 		F3953BD72A6E87E000EE03F9 /* BaseIntegrationXCTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3953BD62A6E87E000EE03F9 /* BaseIntegrationXCTestCase.swift */; };
 		F3A7AFC62A41AA82001FC89C /* BaseUIXCTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3A7AFC52A41AA82001FC89C /* BaseUIXCTestCase.swift */; };
+		F3BB464D2A39ADCC00461F6E /* NCMoreAppSuggestionsCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F3BB464C2A39ADCC00461F6E /* NCMoreAppSuggestionsCell.xib */; };
+		F3BB464F2A39EBE500461F6E /* NCMoreUserCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BB464E2A39EBE500461F6E /* NCMoreUserCell.swift */; };
+		F3BB46522A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BB46512A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift */; };
+		F3BB46542A3A1E9D00461F6E /* CCCellMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BB46532A3A1E9D00461F6E /* CCCellMore.swift */; };
 		F700222C1EC479840080073F /* Custom.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F700222B1EC479840080073F /* Custom.xcassets */; };
 		F700222D1EC479840080073F /* Custom.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F700222B1EC479840080073F /* Custom.xcassets */; };
 		F700510122DF63AC003A3356 /* NCShare.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F700510022DF63AC003A3356 /* NCShare.storyboard */; };
@@ -589,7 +595,6 @@
 		F7CB689A2541676B0050EC94 /* NCMore.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7CB68992541676B0050EC94 /* NCMore.storyboard */; };
 		F7CB68A0254169530050EC94 /* NCSettings.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7CB689F254169530050EC94 /* NCSettings.storyboard */; };
 		F7CBC31C24F78E79004D3812 /* NCSortMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7CBC31B24F78E79004D3812 /* NCSortMenu.swift */; };
-		F7CF16A32A4D7C7A000FF107 /* NCMoreUserCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7CF16A22A4D7C7A000FF107 /* NCMoreUserCell.xib */; };
 		F7D1612023CF19E30039EBBF /* NCViewerRichWorkspace.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7D1611F23CF19E30039EBBF /* NCViewerRichWorkspace.storyboard */; };
 		F7D56B1A2972405500FA46C4 /* Mantis in Frameworks */ = {isa = PBXBuildFile; productRef = F7D56B192972405500FA46C4 /* Mantis */; };
 		F7D57C8626317BDA00DE301D /* NCAccountRequest.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7CA212C25F1333200826ABB /* NCAccountRequest.storyboard */; };
@@ -810,10 +815,16 @@
 		F31F69442A2F6D4600162F76 /* NextcloudSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextcloudSnapshotTests.swift; sourceTree = "<group>"; };
 		F31F694F2A2F707E00162F76 /* SwiftUIView+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwiftUIView+Extensions.swift"; sourceTree = "<group>"; };
 		F31F69602A2F907800162F76 /* __Snapshots__ */ = {isa = PBXFileReference; lastKnownFileType = folder; path = __Snapshots__; sourceTree = "<group>"; };
+		F33AAF992A60394C006ECCBD /* NCMoreUserCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCMoreUserCell.xib; sourceTree = "<group>"; };
 		F343A4B22A1E01FF00DDA874 /* PHAsset+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PHAsset+Extension.swift"; sourceTree = "<group>"; };
 		F343A4BA2A1E734600DDA874 /* Optional+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optional+Extension.swift"; sourceTree = "<group>"; };
+		F39298962A3B12CB00509762 /* BaseNCMoreCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseNCMoreCell.swift; sourceTree = "<group>"; };
 		F3953BD62A6E87E000EE03F9 /* BaseIntegrationXCTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseIntegrationXCTestCase.swift; sourceTree = "<group>"; };
 		F3A7AFC52A41AA82001FC89C /* BaseUIXCTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseUIXCTestCase.swift; sourceTree = "<group>"; };
+		F3BB464C2A39ADCC00461F6E /* NCMoreAppSuggestionsCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCMoreAppSuggestionsCell.xib; sourceTree = "<group>"; };
+		F3BB464E2A39EBE500461F6E /* NCMoreUserCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMoreUserCell.swift; sourceTree = "<group>"; };
+		F3BB46512A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMoreAppSuggestionsCell.swift; sourceTree = "<group>"; };
+		F3BB46532A3A1E9D00461F6E /* CCCellMore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CCCellMore.swift; sourceTree = "<group>"; };
 		F700222B1EC479840080073F /* Custom.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Custom.xcassets; sourceTree = "<group>"; };
 		F700510022DF63AC003A3356 /* NCShare.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCShare.storyboard; sourceTree = "<group>"; };
 		F700510222DF6897003A3356 /* Parchment.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Parchment.framework; path = Carthage/Build/iOS/Parchment.framework; sourceTree = "<group>"; };
@@ -1586,6 +1597,27 @@
 			path = Extensions;
 			sourceTree = "<group>";
 		};
+		F33AAF982A601465006ECCBD /* Recovered References */ = {
+			isa = PBXGroup;
+			children = (
+				F7CF16A22A4D7C7A000FF107 /* NCMoreUserCell.xib */,
+			);
+			name = "Recovered References";
+			sourceTree = "<group>";
+		};
+		F3BB46502A39EC2D00461F6E /* Cells */ = {
+			isa = PBXGroup;
+			children = (
+				F3BB464C2A39ADCC00461F6E /* NCMoreAppSuggestionsCell.xib */,
+				F3BB46512A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift */,
+				F33AAF992A60394C006ECCBD /* NCMoreUserCell.xib */,
+				F3BB464E2A39EBE500461F6E /* NCMoreUserCell.swift */,
+				F3BB46532A3A1E9D00461F6E /* CCCellMore.swift */,
+				F39298962A3B12CB00509762 /* BaseNCMoreCell.swift */,
+			);
+			path = Cells;
+			sourceTree = "<group>";
+		};
 		F70211F31BAC56E9003FC03E /* Main */ = {
 			isa = PBXGroup;
 			children = (
@@ -2268,7 +2300,7 @@
 		F7CB68942541670D0050EC94 /* More */ = {
 			isa = PBXGroup;
 			children = (
-				F7CF16A22A4D7C7A000FF107 /* NCMoreUserCell.xib */,
+				F3BB46502A39EC2D00461F6E /* Cells */,
 				F7CB68992541676B0050EC94 /* NCMore.storyboard */,
 				F73F537E1E929C8500F8678D /* NCMore.swift */,
 			);
@@ -2373,6 +2405,7 @@
 				C0046CDA2A17B98400D87C9D /* NextcloudUITests.xctest */,
 				C04E2F202A17BB4D001BAD85 /* NextcloudIntegrationTests.xctest */,
 				F31F69422A2F6D4500162F76 /* NextcloudSnapshotTests.xctest */,
+				F33AAF982A601465006ECCBD /* Recovered References */,
 			);
 			sourceTree = "<group>";
 		};
@@ -3105,6 +3138,7 @@
 				F7362A1F220C853A005101B5 /* LaunchScreen.storyboard in Resources */,
 				F77444F622281649000D5EB0 /* NCGridMediaCell.xib in Resources */,
 				F78ACD4421903CF20088454D /* NCListCell.xib in Resources */,
+				F3BB464D2A39ADCC00461F6E /* NCMoreAppSuggestionsCell.xib in Resources */,
 				F7F4F10727ECDBDB008676F9 /* Inconsolata-Black.ttf in Resources */,
 				F761856D29E98543006EB3B0 /* NCIntroCollectionViewCell.xib in Resources */,
 				F78ACD4621903D010088454D /* NCGridCell.xib in Resources */,
@@ -3118,6 +3152,7 @@
 				F723985C253C95CE00257F49 /* NCViewerRichdocument.storyboard in Resources */,
 				F758B45A212C564000515F55 /* NCScan.storyboard in Resources */,
 				F70D87CF25EE6E58008CBBBD /* NCRenameFile.storyboard in Resources */,
+				F33AAF9A2A60394C006ECCBD /* NCMoreUserCell.xib in Resources */,
 				F765F73225237E3F00391DBE /* NCRecent.storyboard in Resources */,
 				F78F74342163757000C2ADAD /* NCTrash.storyboard in Resources */,
 				F702F30225EE5D2C008F8E80 /* english.txt in Resources */,
@@ -3166,7 +3201,6 @@
 				F77B0F611D118A16002130FE /* Acknowledgements.rtf in Resources */,
 				F7EDE509262DA9D600414FE6 /* NCSelectCommandViewSelect.xib in Resources */,
 				F732D23327CF8AED000B0F1B /* NCPlayerToolBar.xib in Resources */,
-				F7CF16A32A4D7C7A000FF107 /* NCMoreUserCell.xib in Resources */,
 				F73D11FA253C5F4800DF9BEC /* NCViewerNextcloudText.storyboard in Resources */,
 				F7EDE51B262DD0C400414FE6 /* NCSelectCommandViewCopyMove.xib in Resources */,
 				F73B422B2476764F00A30FD3 /* NCNotification.storyboard in Resources */,
@@ -3601,6 +3635,7 @@
 				F7B8CD91261AF3F7007C1359 /* NCNetworkingChunkedUpload.swift in Sources */,
 				F757CC8D29E82D0500F31428 /* NCGroupfolders.swift in Sources */,
 				F760329F252F0F8E0015A421 /* NCTransferCell.swift in Sources */,
+				F3BB46542A3A1E9D00461F6E /* CCCellMore.swift in Sources */,
 				AF68326A27BE65A90010BF0B /* NCMenuAction.swift in Sources */,
 				F7682FE023C36B0500983A04 /* NCMainTabBar.swift in Sources */,
 				F7A0D1352591FBC5008F8A13 /* String+Extension.swift in Sources */,
@@ -3610,6 +3645,7 @@
 				F70460522499061800BB98A7 /* NotificationCenter+MainThread.swift in Sources */,
 				F78F74362163781100C2ADAD /* NCTrash.swift in Sources */,
 				AF817EF1274BC781009ED85B /* NCUserBaseUrl.swift in Sources */,
+				F39298972A3B12CB00509762 /* BaseNCMoreCell.swift in Sources */,
 				AF2D7C7C2742556F00ADF566 /* NCShareLinkCell.swift in Sources */,
 				F7E41316294A19B300839300 /* UIView+Extension.swift in Sources */,
 				F31F69502A2F707E00162F76 /* SwiftUIView+Extensions.swift in Sources */,
@@ -3667,6 +3703,7 @@
 				F76D364628A4F8BF00214537 /* NCActivityIndicator.swift in Sources */,
 				F7020FCE2233D7F700B7297D /* NCCreateFormUploadVoiceNote.swift in Sources */,
 				F7134186259747BA00768D21 /* NCPushNotification.m in Sources */,
+				F3BB464F2A39EBE500461F6E /* NCMoreUserCell.swift in Sources */,
 				F726EEEC1FED1C820030B9C8 /* NCEndToEndInitialize.swift in Sources */,
 				F79A65C62191D95E00FF6DCC /* NCSelect.swift in Sources */,
 				F75D19E325EFE09000D74598 /* NCTrash+Menu.swift in Sources */,
@@ -3696,6 +3733,7 @@
 				F749B64A297B0CBB00087535 /* NCManageDatabase+Share.swift in Sources */,
 				F7C9555521F0C5470024296E /* NCActivity.swift in Sources */,
 				F7725A60251F33BB00D125E0 /* NCFiles.swift in Sources */,
+				F3BB46522A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift in Sources */,
 				F704B5E52430AA8000632F5F /* NCCreateFormUploadConflict.swift in Sources */,
 				F765608F23BF813600765969 /* NCContentPresenter.swift in Sources */,
 				F343A4BB2A1E734600DDA874 /* Optional+Extension.swift in Sources */,

+ 1 - 1
iOSClient/Extensions/UINavigationController+Extension.swift

@@ -51,7 +51,7 @@ extension UINavigationController {
         navigationBar.scrollEdgeAppearance = scrollEdgeAppearance
     }
 
-    func setGroupeAppreance() {
+    func setGroupAppearance() {
 
         navigationBar.tintColor = .systemBlue
 

+ 44 - 0
iOSClient/More/Cells/BaseNCMoreCell.swift

@@ -0,0 +1,44 @@
+//
+//  BaseNCMoreCell.swift
+//  Nextcloud
+//
+//  Created by Milen on 15.06.23.
+//  Copyright © 2023 Marino Faggiana. All rights reserved.
+//
+
+import Foundation
+
+class BaseNCMoreCell: UITableViewCell {
+    let selectionColor: UIView = UIView()
+    let defaultCornerRadius: CGFloat = 10.0
+
+    override var frame: CGRect {
+        get {
+            return super.frame
+        }
+        set (newFrame) {
+            var frame = newFrame
+            let newWidth = frame.width * 0.90
+            let space = (frame.width - newWidth) / 2
+            frame.size.width = newWidth
+            frame.origin.x += space
+            super.frame = frame
+        }
+    }
+
+    override func awakeFromNib() {
+        super.awakeFromNib()
+
+        selectedBackgroundView = selectionColor
+        backgroundColor = .secondarySystemGroupedBackground
+        applyCornerRadius()
+    }
+
+    func applyCornerRadius() {
+        layer.cornerRadius = defaultCornerRadius
+    }
+
+    func removeCornerRadius() {
+        layer.cornerRadius = 0
+    }
+}

+ 18 - 0
iOSClient/More/Cells/CCCellMore.swift

@@ -0,0 +1,18 @@
+//
+//  CCCellMore.swift
+//  Nextcloud
+//
+//  Created by Milen on 14.06.23.
+//  Copyright © 2023 Marino Faggiana. All rights reserved.
+//
+
+import Foundation
+
+class CCCellMore: BaseNCMoreCell {
+    @IBOutlet weak var labelText: UILabel!
+    @IBOutlet weak var imageIcon: UIImageView!
+    @IBOutlet weak var separator: UIView!
+    @IBOutlet weak var separatorHeigth: NSLayoutConstraint!
+
+    static let reuseIdentifier = "CCCellMore"
+}

+ 57 - 0
iOSClient/More/Cells/NCMoreAppSuggestionsCell.swift

@@ -0,0 +1,57 @@
+//
+//  NCMoreAppSuggestionsCell.swift
+//  Nextcloud
+//
+//  Created by Milen on 14.06.23.
+//  Copyright © 2023 Marino Faggiana. All rights reserved.
+//
+
+import Foundation
+
+class NCMoreAppSuggestionsCell: BaseNCMoreCell {
+    @IBOutlet weak var talkView: UIStackView!
+    @IBOutlet weak var notesView: UIStackView!
+    @IBOutlet weak var moreAppsView: UIStackView!
+
+    static let reuseIdentifier = "NCMoreAppSuggestionsCell"
+
+    static func fromNib() -> UINib {
+        return UINib(nibName: "NCMoreAppSuggestionsCell", bundle: nil)
+    }
+
+    override func awakeFromNib() {
+        super.awakeFromNib()
+        backgroundColor = .clear
+
+        talkView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(talkTapped)))
+        notesView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(notesTapped)))
+        moreAppsView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(moreAppsTapped)))
+    }
+
+    @objc func talkTapped() {
+        guard let url = URL(string: NCGlobal.shared.talkSchemeUrl) else { return }
+
+        if UIApplication.shared.canOpenURL(url) {
+            UIApplication.shared.open(url)
+        } else {
+            guard let url = URL(string: NCGlobal.shared.talkAppStoreUrl) else { return }
+            UIApplication.shared.open(url)
+        }
+    }
+
+    @objc func notesTapped() {
+        guard let url = URL(string: NCGlobal.shared.notesSchemeUrl) else { return }
+
+        if UIApplication.shared.canOpenURL(url) {
+            UIApplication.shared.open(url)
+        } else {
+            guard let url = URL(string: NCGlobal.shared.notesAppStoreUrl) else { return }
+            UIApplication.shared.open(url)
+        }
+    }
+
+    @objc func moreAppsTapped() {
+        guard let url = URL(string: NCGlobal.shared.moreAppsUrl) else { return }
+        UIApplication.shared.open(url)
+    }
+}

+ 157 - 0
iOSClient/More/Cells/NCMoreAppSuggestionsCell.xib

@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="22113.3" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina6_0" orientation="portrait" appearance="dark"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22089.1"/>
+        <capability name="System colors in document resources" minToolsVersion="11.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="0.0" id="dVh-cS-UwU" userLabel="App Suggestion Cell" customClass="NCMoreAppSuggestionsCell" customModule="Nextcloud" customModuleProvider="target">
+            <rect key="frame" x="0.0" y="0.0" width="1076" height="44"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="dVh-cS-UwU" id="9Ma-CX-ckc">
+                <rect key="frame" x="0.0" y="0.0" width="1076" height="44"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="ppx-X2-oTM">
+                        <rect key="frame" x="0.0" y="0.0" width="1076" height="44"/>
+                        <subviews>
+                            <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalCentering" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="Tbt-MZ-3jf">
+                                <rect key="frame" x="0.0" y="0.0" width="353.33333333333331" height="44"/>
+                                <subviews>
+                                    <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="749" image="talk-template" translatesAutoresizingMaskIntoConstraints="NO" id="Uby-L5-yV4" userLabel="Icon">
+                                        <rect key="frame" x="167.66666666666666" y="8" width="18" height="18"/>
+                                        <color key="tintColor" systemColor="linkColor"/>
+                                        <constraints>
+                                            <constraint firstAttribute="height" constant="18" id="Vl1-Ip-OUw"/>
+                                            <constraint firstAttribute="width" constant="18" id="m7P-Or-Esh"/>
+                                        </constraints>
+                                    </imageView>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Talk" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9cY-LF-9EI">
+                                        <rect key="frame" x="167" y="26" width="19.333333333333343" height="10"/>
+                                        <fontDescription key="fontDescription" type="system" pointSize="10"/>
+                                        <color key="textColor" systemColor="systemBlueColor"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                </subviews>
+                                <color key="backgroundColor" systemColor="secondarySystemGroupedBackgroundColor"/>
+                                <constraints>
+                                    <constraint firstAttribute="bottom" secondItem="9cY-LF-9EI" secondAttribute="bottom" constant="8" id="BIL-hp-tNO"/>
+                                    <constraint firstItem="9cY-LF-9EI" firstAttribute="top" secondItem="Uby-L5-yV4" secondAttribute="bottom" id="twR-46-lPV"/>
+                                    <constraint firstItem="Uby-L5-yV4" firstAttribute="top" secondItem="Tbt-MZ-3jf" secondAttribute="top" constant="8" id="xcP-gx-xol"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
+                                        <integer key="value" value="8"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </stackView>
+                            <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalCentering" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="4jA-wm-kCc">
+                                <rect key="frame" x="361.33333333333337" y="0.0" width="353.33333333333337" height="44"/>
+                                <subviews>
+                                    <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="749" image="notes-template" translatesAutoresizingMaskIntoConstraints="NO" id="BT7-Nt-9RH" userLabel="Icon">
+                                        <rect key="frame" x="167.66666666666669" y="8" width="18" height="18"/>
+                                        <color key="tintColor" systemColor="linkColor"/>
+                                        <constraints>
+                                            <constraint firstAttribute="height" constant="18" id="3YI-i4-Ykd"/>
+                                            <constraint firstAttribute="width" constant="18" id="Riu-Cr-O0l"/>
+                                        </constraints>
+                                    </imageView>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Notes" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tQM-o0-e3W">
+                                        <rect key="frame" x="162.33333333333331" y="26" width="28.666666666666657" height="10"/>
+                                        <fontDescription key="fontDescription" type="system" pointSize="10"/>
+                                        <color key="textColor" systemColor="systemBlueColor"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                </subviews>
+                                <color key="backgroundColor" systemColor="secondarySystemGroupedBackgroundColor"/>
+                                <constraints>
+                                    <constraint firstItem="tQM-o0-e3W" firstAttribute="top" secondItem="BT7-Nt-9RH" secondAttribute="bottom" id="1ho-7Y-4Ty"/>
+                                    <constraint firstItem="BT7-Nt-9RH" firstAttribute="top" secondItem="4jA-wm-kCc" secondAttribute="top" constant="8" id="4QH-zk-5ph"/>
+                                    <constraint firstAttribute="bottom" secondItem="tQM-o0-e3W" secondAttribute="bottom" constant="8" id="E3e-ra-dwn"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
+                                        <integer key="value" value="8"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </stackView>
+                            <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalCentering" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="SA6-fX-Xmx">
+                                <rect key="frame" x="722.66666666666663" y="0.0" width="353.33333333333337" height="44"/>
+                                <subviews>
+                                    <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="749" image="more-apps-template" translatesAutoresizingMaskIntoConstraints="NO" id="dzE-0b-iBn" userLabel="Icon">
+                                        <rect key="frame" x="167.66666666666674" y="8" width="18" height="18"/>
+                                        <color key="tintColor" systemColor="linkColor"/>
+                                        <constraints>
+                                            <constraint firstAttribute="width" constant="18" id="Yo0-sL-LJN"/>
+                                            <constraint firstAttribute="height" constant="18" id="bOc-vN-4Ry"/>
+                                        </constraints>
+                                    </imageView>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="More apps" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="GIQ-5h-VeA">
+                                        <rect key="frame" x="151.33333333333337" y="26" width="51" height="12"/>
+                                        <fontDescription key="fontDescription" type="system" pointSize="10"/>
+                                        <color key="textColor" systemColor="systemBlueColor"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                </subviews>
+                                <color key="backgroundColor" systemColor="secondarySystemGroupedBackgroundColor"/>
+                                <constraints>
+                                    <constraint firstAttribute="bottom" secondItem="GIQ-5h-VeA" secondAttribute="bottom" constant="8" id="8xI-Ad-3Gc"/>
+                                    <constraint firstItem="dzE-0b-iBn" firstAttribute="top" secondItem="SA6-fX-Xmx" secondAttribute="top" constant="8" id="ixx-ut-Ss2"/>
+                                    <constraint firstItem="GIQ-5h-VeA" firstAttribute="top" secondItem="dzE-0b-iBn" secondAttribute="bottom" id="rWG-kv-J2m"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
+                                        <integer key="value" value="8"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </stackView>
+                        </subviews>
+                        <constraints>
+                            <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="400" id="D00-QX-V4P"/>
+                            <constraint firstAttribute="bottom" secondItem="Tbt-MZ-3jf" secondAttribute="bottom" id="hS2-sl-Kz0"/>
+                            <constraint firstItem="Tbt-MZ-3jf" firstAttribute="top" secondItem="ppx-X2-oTM" secondAttribute="top" id="u4O-GE-2yF"/>
+                        </constraints>
+                    </stackView>
+                </subviews>
+                <constraints>
+                    <constraint firstAttribute="bottom" secondItem="ppx-X2-oTM" secondAttribute="bottom" id="Ler-rD-wfw"/>
+                    <constraint firstAttribute="trailing" secondItem="ppx-X2-oTM" secondAttribute="trailing" id="XRL-5j-YM1"/>
+                    <constraint firstItem="ppx-X2-oTM" firstAttribute="top" secondItem="9Ma-CX-ckc" secondAttribute="top" id="Yxe-5b-StO"/>
+                    <constraint firstItem="ppx-X2-oTM" firstAttribute="centerX" secondItem="9Ma-CX-ckc" secondAttribute="centerX" id="mtt-g7-1xb"/>
+                    <constraint firstItem="ppx-X2-oTM" firstAttribute="leading" secondItem="9Ma-CX-ckc" secondAttribute="leading" id="yEM-LQ-UIV"/>
+                </constraints>
+                <variation key="widthClass=regular">
+                    <mask key="constraints">
+                        <exclude reference="XRL-5j-YM1"/>
+                        <exclude reference="yEM-LQ-UIV"/>
+                    </mask>
+                </variation>
+            </tableViewCellContentView>
+            <connections>
+                <outlet property="moreAppsView" destination="SA6-fX-Xmx" id="fiE-FN-en3"/>
+                <outlet property="notesView" destination="4jA-wm-kCc" id="XuQ-8X-RDH"/>
+                <outlet property="talkView" destination="Tbt-MZ-3jf" id="1Tf-ff-0k1"/>
+            </connections>
+            <point key="canvasLocation" x="209.30232558139534" y="-65.665236051502148"/>
+        </tableViewCell>
+    </objects>
+    <resources>
+        <image name="more-apps-template" width="32" height="32"/>
+        <image name="notes-template" width="24" height="24"/>
+        <image name="talk-template" width="600" height="600"/>
+        <systemColor name="linkColor">
+            <color red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </systemColor>
+        <systemColor name="secondarySystemGroupedBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+        <systemColor name="systemBlueColor">
+            <color red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </systemColor>
+    </resources>
+</document>

+ 23 - 0
iOSClient/More/Cells/NCMoreUserCell.swift

@@ -0,0 +1,23 @@
+//
+//  NCMoreUserCell.swift
+//  Nextcloud
+//
+//  Created by Milen on 14.06.23.
+//  Copyright © 2023 Marino Faggiana. All rights reserved.
+//
+
+import Foundation
+import MarqueeLabel
+
+class NCMoreUserCell: BaseNCMoreCell {
+    @IBOutlet weak var displayName: UILabel!
+    @IBOutlet weak var avatar: UIImageView!
+    @IBOutlet weak var icon: UIImageView!
+    @IBOutlet weak var status: MarqueeLabel!
+
+    static let reuseIdentifier = "NCMoreUserCell"
+
+    static func fromNib() -> UINib {
+        return UINib(nibName: "NCMoreUserCell", bundle: nil)
+    }
+}

+ 3 - 3
iOSClient/More/NCMoreUserCell.xib → iOSClient/More/Cells/NCMoreUserCell.xib

@@ -1,15 +1,15 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21225" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
     <device id="retina4_7" orientation="portrait" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21207"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21678"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <objects>
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="CustomCellFileAndDirectory"/>
         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <tableViewCell contentMode="scaleToFill" selectionStyle="blue" indentationWidth="0.0" reuseIdentifier="userCell" rowHeight="107" id="2" customClass="NCMoreUserCell" customModule="Nextcloud" customModuleProvider="target">
+        <tableViewCell contentMode="scaleToFill" selectionStyle="blue" indentationWidth="0.0" reuseIdentifier="NCMoreUserCell" rowHeight="107" id="2" customClass="NCMoreUserCell" customModule="Nextcloud" customModuleProvider="target">
             <rect key="frame" x="0.0" y="0.0" width="600" height="75"/>
             <autoresizingMask key="autoresizingMask" flexibleMaxY="YES"/>
             <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="2" id="sQq-jC-UEV">

+ 3 - 3
iOSClient/More/NCMore.storyboard

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21225" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22113.3" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
     <device id="retina6_1" orientation="portrait" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21207"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22089.1"/>
         <capability name="Safe area layout guides" minToolsVersion="9.0"/>
         <capability name="System colors in document resources" minToolsVersion="11.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@@ -22,7 +22,7 @@
                                 <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                                 <inset key="separatorInset" minX="56" minY="0.0" maxX="0.0" maxY="0.0"/>
                                 <prototypes>
-                                    <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" rowHeight="50" id="qwS-lS-XzK" customClass="CCCellMore" customModule="Nextcloud" customModuleProvider="target">
+                                    <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="CCCellMore" rowHeight="50" id="qwS-lS-XzK" customClass="CCCellMore" customModule="Nextcloud" customModuleProvider="target">
                                         <rect key="frame" x="0.0" y="55.5" width="414" height="50"/>
                                         <autoresizingMask key="autoresizingMask"/>
                                         <tableViewCellContentView key="contentView" multipleTouchEnabled="YES" contentMode="center" tableViewCell="qwS-lS-XzK" id="1FG-Yi-cbC">

+ 78 - 160
iOSClient/More/NCMore.swift

@@ -23,7 +23,6 @@
 
 import UIKit
 import NextcloudKit
-import MarqueeLabel
 
 class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
 
@@ -33,16 +32,28 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
     @IBOutlet weak var progressQuota: UIProgressView!
     @IBOutlet weak var viewQuota: UIView!
 
-    var functionMenu: [NKExternalSite] = []
-    var externalSiteMenu: [NKExternalSite] = []
-    var settingsMenu: [NKExternalSite] = []
-    var quotaMenu: [NKExternalSite] = []
+    private var functionMenu: [NKExternalSite] = []
+    private var externalSiteMenu: [NKExternalSite] = []
+    private var settingsMenu: [NKExternalSite] = []
+    private var quotaMenu: [NKExternalSite] = []
 
-    let appDelegate = UIApplication.shared.delegate as! AppDelegate
-    let defaultCornerRadius: CGFloat = 10.0
-    let applicationHandle = NCApplicationHandle()
-    
-    var tabAccount: tableAccount?
+    private let appDelegate = UIApplication.shared.delegate as! AppDelegate
+    private let applicationHandle = NCApplicationHandle()
+
+    private var tabAccount: tableAccount?
+
+    private struct Section {
+        var items: [NKExternalSite]
+        var type: SectionType
+
+        enum SectionType {
+            case account
+            case moreApps
+            case regular
+        }
+    }
+
+    private var sections: [Section] = []
 
     // MARK: - View Life Cycle
 
@@ -52,10 +63,12 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
         self.navigationItem.title = NSLocalizedString("_more_", comment: "")
         view.backgroundColor = .systemGroupedBackground
 
+        tableView.insetsContentViewsToSafeArea = false
         tableView.delegate = self
         tableView.dataSource = self
         tableView.backgroundColor = .systemGroupedBackground
-        tableView.register(UINib(nibName: "NCMoreUserCell", bundle: nil), forCellReuseIdentifier: "userCell")
+        tableView.register(NCMoreUserCell.fromNib(), forCellReuseIdentifier: NCMoreUserCell.reuseIdentifier)
+        tableView.register(NCMoreAppSuggestionsCell.fromNib(), forCellReuseIdentifier: NCMoreAppSuggestionsCell.reuseIdentifier)
 
         // create tap gesture recognizer
         let tapQuota = UITapGestureRecognizer(target: self, action: #selector(tapLabelQuotaExternalSite))
@@ -69,7 +82,7 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
     override func viewWillAppear(_ animated: Bool) {
         super.viewWillAppear(animated)
 
-        navigationController?.setGroupeAppreance()
+        navigationController?.setGroupAppearance()
         
         appDelegate.activeViewController = self
         loadItems()
@@ -229,6 +242,30 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
                 }
             }
         }
+
+        loadSections()
+    }
+
+    private func loadSections() {
+        if tabAccount != nil {
+            sections.append(Section(items: [NKExternalSite()], type: .account))
+        }
+
+        if !NCBrandOptions.shared.disable_show_more_nextcloud_apps_in_settings {
+            sections.append(Section(items: [NKExternalSite()], type: .moreApps))
+        }
+
+        if !functionMenu.isEmpty {
+            sections.append(Section(items: functionMenu, type: .regular))
+        }
+
+        if !externalSiteMenu.isEmpty {
+            sections.append(Section(items: externalSiteMenu, type: .regular))
+        }
+
+        if !settingsMenu.isEmpty {
+            sections.append(Section(items: settingsMenu, type: .regular))
+        }
     }
 
     // MARK: - Action
@@ -257,7 +294,7 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
     // MARK: -
 
     func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
-        if indexPath.section == 0 {
+        if sections[indexPath.section].type == .account {
             return 75
         } else {
             return NCGlobal.shared.heightCellSettings
@@ -265,65 +302,31 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
     }
 
     func numberOfSections(in tableView: UITableView) -> Int {
-
-        if externalSiteMenu.count == 0 {
-            return 3
-        } else {
-            return 4
-        }
+        return sections.count
     }
     
-    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
-        
-        if section == 0 {
+    func tableView(_ tableView: UITableView, heightForHeaderInSection index: Int) -> CGFloat {
+        let section = sections[index]
+
+        if section.type == .account {
             return 10
+        } else if section.type == .moreApps || sections[index - 1].type == .moreApps {
+            return 1
         } else {
             return 20
         }
     }
 
-    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-
-        var cont = 0
-
-        if section == 0 {
-            cont = tabAccount == nil ? 0 : 1
-        } else if section == 1 {
-            // Menu Normal
-            cont = functionMenu.count
-        } else {
-            switch numberOfSections(in: tableView) {
-            case 3:
-                // Menu Settings
-                if section == 2 {
-                    cont = settingsMenu.count
-                }
-            case 4:
-                // Menu External Site
-                if section == 2 {
-                    cont = externalSiteMenu.count
-                }
-                // Menu Settings
-                if section == 3 {
-                    cont = settingsMenu.count
-                }
-            default:
-                cont = 0
-            }
-        }
-
-        return cont
+    func tableView(_ tableView: UITableView, numberOfRowsInSection index: Int) -> Int {
+        return sections[index].items.count
     }
-    
-    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
 
-        var item = NKExternalSite()
+    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        let section = sections[indexPath.section]
 
-        // change color selection and disclosure indicator
-        let selectionColor: UIView = UIView()
-        if indexPath.section == 0 {
+        if section.type == .account {
 
-            let cell = tableView.dequeueReusableCell(withIdentifier: "userCell", for: indexPath) as! NCMoreUserCell
+            let cell = tableView.dequeueReusableCell(withIdentifier: NCMoreUserCell.reuseIdentifier, for: indexPath) as! NCMoreUserCell
 
             cell.avatar.image = nil
             cell.icon.image = nil
@@ -331,10 +334,7 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
             cell.displayName.text = ""
 
             if let account = tabAccount {
-                cell.avatar.image = NCUtility.shared.loadUserImage(
-                    for: account.user,
-                       displayName: account.displayName,
-                       userBaseUrl: appDelegate)
+                cell.avatar.image = NCUtility.shared.loadUserImage(for: account.user, displayName: account.displayName, userBaseUrl: appDelegate)
 
                 if account.alias == "" {
                     cell.displayName?.text = account.displayName
@@ -343,8 +343,6 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
                 }
                 cell.displayName.textColor = .label
             }
-            cell.selectedBackgroundView = selectionColor
-            cell.backgroundColor = .secondarySystemGroupedBackground
             cell.accessoryType = UITableViewCell.AccessoryType.disclosureIndicator
 
             if NCGlobal.shared.capabilityUserStatusEnabled, let account = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", appDelegate.account)) {
@@ -360,45 +358,34 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
                 }
             }
             
-            cell.layer.cornerRadius = defaultCornerRadius
             cell.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner, .layerMaxXMaxYCorner, .layerMinXMaxYCorner]
 
             return cell
 
+        } else if section.type == .moreApps {
+            let cell = tableView.dequeueReusableCell(withIdentifier: NCMoreAppSuggestionsCell.reuseIdentifier, for: indexPath) as! NCMoreAppSuggestionsCell
+
+            return cell
         } else {
+            let cell = tableView.dequeueReusableCell(withIdentifier: CCCellMore.reuseIdentifier, for: indexPath) as! CCCellMore
 
-            let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CCCellMore
-
-            // Menu Normal
-            if indexPath.section == 1 {
-                item = functionMenu[indexPath.row]
-            }
-            // Menu External Site
-            if numberOfSections(in: tableView) == 4 && indexPath.section == 2 {
-                item = externalSiteMenu[indexPath.row]
-            }
-            // Menu Settings
-            if (numberOfSections(in: tableView) == 3 && indexPath.section == 2) || (numberOfSections(in: tableView) == 4 && indexPath.section == 3) {
-                item = settingsMenu[indexPath.row]
-            }
+            let item = sections[indexPath.section].items[indexPath.row]
 
             cell.imageIcon?.image = NCUtility.shared.loadImage(named: item.icon)
             cell.imageIcon?.contentMode = .scaleAspectFit
             cell.labelText?.text = NSLocalizedString(item.name, comment: "")
             cell.labelText.textColor = .label
 
-            cell.selectedBackgroundView = selectionColor
-            cell.backgroundColor = .secondarySystemGroupedBackground
             cell.accessoryType = UITableViewCell.AccessoryType.disclosureIndicator
 
             cell.separator.backgroundColor = .separator
             cell.separatorHeigth.constant = 0.4
-            
-            cell.layer.cornerRadius = 0
+
+            cell.removeCornerRadius()
             let rows = tableView.numberOfRows(inSection: indexPath.section)
             
             if indexPath.row == 0 {
-                cell.layer.cornerRadius = defaultCornerRadius
+                cell.applyCornerRadius()
                 if indexPath.row == rows - 1 {
                     cell.separator.backgroundColor = .clear
                     cell.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner, .layerMaxXMaxYCorner, .layerMinXMaxYCorner]
@@ -406,56 +393,35 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
                     cell.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner]
                 }
             } else if indexPath.row == rows - 1 {
-                cell.layer.cornerRadius = defaultCornerRadius
+                cell.applyCornerRadius()
                 cell.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner]
                 cell.separator.backgroundColor = .clear
             }
-            
+
             return cell
         }
     }
 
-    // method to run when table view cell is tapped
     func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+        let item = sections[indexPath.section].items[indexPath.row]
 
-        var item = NKExternalSite()
-
-        if indexPath.section == 0 {
+        // Menu Function
+        if sections[indexPath.section].type == .account {
             tapImageLogoManageAccount()
             return
         }
 
-        // Menu Function
-        if indexPath.section == 1 {
-            item = functionMenu[indexPath.row]
-        }
-
-        // Menu External Site
-        if numberOfSections(in: tableView) == 4 && indexPath.section == 2 {
-            item = externalSiteMenu[indexPath.row]
-        }
-
-        // Menu Settings
-        if (numberOfSections(in: tableView) == 3 && indexPath.section == 2) || (numberOfSections(in: tableView) == 4 && indexPath.section == 3) {
-            item = settingsMenu[indexPath.row]
-        }
-
         // Action
         if item.url.contains("segue") && !item.url.contains("//") {
-
             self.navigationController?.performSegue(withIdentifier: item.url, sender: self)
-
         } else if item.url.contains("openStoryboard") && !item.url.contains("//") {
-
             let nameStoryboard = item.url.replacingOccurrences(of: "openStoryboard", with: "")
             let storyboard = UIStoryboard(name: nameStoryboard, bundle: nil)
             if let controller = storyboard.instantiateInitialViewController() {
                 controller.modalPresentationStyle = UIModalPresentationStyle.pageSheet
                 present(controller, animated: true, completion: nil)
             }
-
         } else if item.url.contains("//") {
-
             let browserWebVC = UIStoryboard(name: "NCBrowserWeb", bundle: nil).instantiateInitialViewController() as! NCBrowserWeb
             browserWebVC.urlBase = item.url
             browserWebVC.isHiddenButtonExit = true
@@ -463,13 +429,10 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
 
             self.navigationController?.pushViewController(browserWebVC, animated: true)
             self.navigationController?.navigationBar.isHidden = false
-
         } else if item.url == "logout" {
-
             let alertController = UIAlertController(title: "", message: NSLocalizedString("_want_delete_", comment: ""), preferredStyle: .alert)
 
             let actionYes = UIAlertAction(title: NSLocalizedString("_yes_delete_", comment: ""), style: .default) { (_: UIAlertAction) in
-
                 let manageAccount = CCManageAccount()
                 manageAccount.delete(self.appDelegate.account)
 
@@ -483,53 +446,8 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource {
             alertController.addAction(actionYes)
             alertController.addAction(actionNo)
             self.present(alertController, animated: true, completion: nil)
-
         } else {
             applicationHandle.didSelectItem(item, viewController: self)
         }
     }
 }
-
-class CCCellMore: UITableViewCell {
-
-    @IBOutlet weak var labelText: UILabel!
-    @IBOutlet weak var imageIcon: UIImageView!
-    @IBOutlet weak var separator: UIView!
-    @IBOutlet weak var separatorHeigth: NSLayoutConstraint!
-
-    override var frame: CGRect {
-        get {
-            return super.frame
-        }
-        set (newFrame) {
-            var frame = newFrame
-            let newWidth = frame.width * 0.90
-            let space = (frame.width - newWidth) / 2
-            frame.size.width = newWidth
-            frame.origin.x += space
-            super.frame = frame
-        }
-    }
-}
-
-class NCMoreUserCell: UITableViewCell {
-
-    @IBOutlet weak var displayName: UILabel!
-    @IBOutlet weak var avatar: UIImageView!
-    @IBOutlet weak var icon: UIImageView!
-    @IBOutlet weak var status: MarqueeLabel!
-    
-    override var frame: CGRect {
-        get {
-            return super.frame
-        }
-        set (newFrame) {
-            var frame = newFrame
-            let newWidth = frame.width * 0.90
-            let space = (frame.width - newWidth) / 2
-            frame.size.width = newWidth
-            frame.origin.x += space
-            super.frame = frame
-        }
-    }
-}

+ 1 - 1
iOSClient/NCGlobal.swift

@@ -449,7 +449,7 @@ class NCGlobal: NSObject {
     var capabilityExternalSites: Bool                           = false
     var capabilityGroupfoldersEnabled: Bool                     = false // NC27
 
-    // MORE APPS
+    // MORE NEXTCLOUD APPS
     let talkSchemeUrl                                           = "nextcloudtalk://"
     let notesSchemeUrl                                          = "nextcloudnotes://"
     let talkAppStoreUrl                                         = "https://apps.apple.com/de/app/nextcloud-talk/id1296825574"