diff --git a/Tests/NextcloudUnitTests/PrivacyPolicyTest.swift b/Tests/NextcloudUnitTests/PrivacyPolicyTest.swift
new file mode 100644
index 0000000000..f6265f48e7
--- /dev/null
+++ b/Tests/NextcloudUnitTests/PrivacyPolicyTest.swift
@@ -0,0 +1,154 @@
+//
+// PrivacyPolicyTest.swift
+// NextcloudTests
+//
+// Created by A200073704 on 27/04/23.
+// Copyright © 2023 Marino Faggiana. All rights reserved.
+//
+
+@testable import Nextcloud
+import XCTest
+import NextcloudKit
+import XLForm
+
+
+ class PrivacyPolicyTest: XCTestCase {
+
+ var viewController: InitialPrivacySettingsViewController?
+ var privacySettingsView = PrivacySettingsViewController()
+
+ override func setUpWithError() throws {
+
+ // To Create an instance of UIStoryboard
+ let storyboard = UIStoryboard(name: "NCSettings", bundle: nil)
+
+ // To Instantiate UIViewController with Storyboard ID
+ viewController = storyboard.instantiateViewController(withIdentifier: "privacyPolicyViewController") as? InitialPrivacySettingsViewController
+
+ // Outlets are connected
+ let _ = viewController?.view
+
+ // Make the viewDidLoad() execute.
+ viewController?.loadViewIfNeeded()
+
+ }
+
+ override func tearDownWithError() throws {
+ viewController = nil
+ }
+
+ func testPrivacyPolicyViewControllerIsOpen() {
+
+ // Check that the InitialPrivacyPolicyViewController gets opened
+ let storyboard = UIStoryboard(name: "NCSettings", bundle: nil)
+ if let privacyPolicyViewController = storyboard.instantiateViewController(withIdentifier: "privacyPolicyViewController") as? InitialPrivacySettingsViewController {
+ let navigationController = UINavigationController(rootViewController: privacyPolicyViewController)
+
+ privacyPolicyViewController.loadViewIfNeeded()
+
+ XCTAssertTrue(navigationController.topViewController is InitialPrivacySettingsViewController, "Privacy policy view controller should be open")
+ }
+ }
+
+ func testTextViewHasCorrectText() {
+
+ //Check that the text displayed is correct
+ let expectedText = NSLocalizedString("_privacy_help_text_after_login_", comment: "")
+ viewController?.privacySettingsHelpText?.text = expectedText
+
+ let actualText = viewController?.privacySettingsHelpText?.text
+ XCTAssertEqual(actualText, expectedText, "The text view does not have the expected text")
+ }
+
+ func testHasAcceptButton() {
+
+ // Check that view has the accept button
+ let acceptButton = viewController?.acceptButton
+
+ XCTAssertNotNil(acceptButton, "View controller does not have an accept button")
+
+ }
+
+ func testSettingsLinkTypeNavigatesToPrivacySettingsViewController() {
+
+ // Simulate tapping the "Settings" link type
+ let linkType = LinkType.settings
+
+ UserDefaults.standard.set(true, forKey: "showSettingsButton")
+ viewController?.privacySettingsHelpText.hyperLink(originalText: viewController?.privacyHelpText ?? "", linkTextsAndTypes: [NSLocalizedString("_key_settings_help_", comment: ""): linkType.rawValue])
+
+ // Check that the correct view controller was pushed onto the navigation stack
+ XCTAssertNotNil(viewController?.navigationController?.visibleViewController is PrivacySettingsViewController)
+ }
+
+ func testPrivacyPolicyLinkType_NavigatesToPrivacyPolicyViewController() {
+
+ // Simulate tapping the "Privacy Policy" link type
+ let linkType = LinkType.privacyPolicy
+
+ viewController?.privacySettingsHelpText.hyperLink(originalText: viewController?.privacyHelpText ?? "", linkTextsAndTypes: [NSLocalizedString("_key_privacy_help_", comment: ""): linkType.rawValue])
+
+ // Check that the correct view controller was pushed onto the navigation
+ XCTAssertNotNil(viewController?.navigationController?.visibleViewController is PrivacyPolicyViewController)
+ }
+
+ func testCorrectImagePresentOnInitialPrivacySettingsViewController() {
+
+ // Check that the image view has the correct image
+ let expectedImage = UIImage(named: "dataPrivacy")
+ XCTAssertNotNil(expectedImage)
+ }
+
+ func testAcceptButtonHasBackgroundColor() {
+
+ // Check that the accept button has the correct background color
+ let expectedColor = NCBrandColor.shared.brand
+ XCTAssertEqual(viewController?.acceptButton.backgroundColor, expectedColor)
+
+ }
+
+ func testShowSaveSettingsButton() {
+
+ privacySettingsView.isShowSettingsButton = UserDefaults.standard.bool(forKey: "showSettingsButton")
+
+ XCTAssertTrue(privacySettingsView.isShowSettingsButton)
+
+ }
+
+ func testRequiredDataCollectionSectionExists() {
+ let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor
+ form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow
+
+ var section : XLFormSectionDescriptor
+ var row : XLFormRowDescriptor
+
+ // the section with the title "Required Data Collection"
+ row = XLFormRowDescriptor(tag: "ButtonDestinationFolder", rowType: "RequiredDataCollectionCustomCellType", title: "")
+ section = XLFormSectionDescriptor.formSection(withTitle: "")
+ section.footerTitle = NSLocalizedString("_required_data_collection_help_text_", comment: "")
+
+ // Verify that section was found
+ XCTAssertNotNil(row, "Expected 'Required Data Collection' section to exist in form.")
+ }
+
+ func testAnalysisDataCollectionSection() {
+
+ let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor
+ form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow
+ var section : XLFormSectionDescriptor
+ var row : XLFormRowDescriptor
+
+ // row with tag "AnalysisDataCollectionSwitch"
+ row = XLFormRowDescriptor(tag: "AnalysisDataCollectionSwitch", rowType: "AnalysisDataCollectionCustomCellType", title: "")
+ section = XLFormSectionDescriptor.formSection(withTitle: "")
+ section.footerTitle = NSLocalizedString("_analysis_data_acqusition_help_text_", comment: "")
+
+ // Assert that the row exists
+ XCTAssertNotNil(row, "Expected row with tag 'AnalysisDataCollectionSwitch' to exist in form.")
+
+ // Verify the switch is off
+ XCTAssertFalse(UserDefaults.standard.bool(forKey: "isAnalysisDataCollectionSwitchOn"), "Expected isAnalysisDataCollectionSwitchOn to be false.")
+ }
+
+
+}
diff --git a/iOSClient/Images.xcassets/dataPrivacy.imageset/Contents.json b/iOSClient/Images.xcassets/dataPrivacy.imageset/Contents.json
new file mode 100644
index 0000000000..4fb0d4c09c
--- /dev/null
+++ b/iOSClient/Images.xcassets/dataPrivacy.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "filename" : "default copy@2x.png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "filename" : "default copy@3x.png",
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "filename" : "default copy@4x.png",
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/iOSClient/Images.xcassets/dataPrivacy.imageset/default copy@2x.png b/iOSClient/Images.xcassets/dataPrivacy.imageset/default copy@2x.png
new file mode 100644
index 0000000000..40c3e7d47f
Binary files /dev/null and b/iOSClient/Images.xcassets/dataPrivacy.imageset/default copy@2x.png differ
diff --git a/iOSClient/Images.xcassets/dataPrivacy.imageset/default copy@3x.png b/iOSClient/Images.xcassets/dataPrivacy.imageset/default copy@3x.png
new file mode 100644
index 0000000000..74d9dbb7dd
Binary files /dev/null and b/iOSClient/Images.xcassets/dataPrivacy.imageset/default copy@3x.png differ
diff --git a/iOSClient/Images.xcassets/dataPrivacy.imageset/default copy@4x.png b/iOSClient/Images.xcassets/dataPrivacy.imageset/default copy@4x.png
new file mode 100644
index 0000000000..682122c3f2
Binary files /dev/null and b/iOSClient/Images.xcassets/dataPrivacy.imageset/default copy@4x.png differ
diff --git a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift
index c72e985f43..155727fa6b 100644
--- a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift
+++ b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift
@@ -212,6 +212,14 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
let dropInteraction = UIDropInteraction(delegate: self)
self.navigationController?.navigationItem.leftBarButtonItems?.first?.customView?.addInteraction(dropInteraction)
+
+ if(!UserDefaults.standard.bool(forKey: "isInitialPrivacySettingsShowed") || isApplicationUpdated()){
+ redirectToPrivacyViewController()
+
+ //set current app version
+ let appVersion = Bundle.main.infoDictionary?["CFBundleInfoDictionaryVersion"] as? String
+ UserDefaults.standard.set(appVersion, forKey: "CurrentAppVersion")
+ }
NotificationCenter.default.addObserver(self, selector: #selector(changeTheming(_:)), name: NSNotification.Name(rawValue: global.notificationCenterChangeTheming), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSource(_:)), name: NSNotification.Name(rawValue: global.notificationCenterReloadDataSource), object: nil)
@@ -319,6 +327,19 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
dataSource.removeImageCache()
}
+
+ func isApplicationUpdated() -> Bool{
+ let appVersion = Bundle.main.infoDictionary?["CFBundleInfoDictionaryVersion"] as? String ?? ""
+ let currentVersion = UserDefaults.standard.string(forKey: "CurrentAppVersion")
+ return currentVersion != appVersion
+ }
+
+ func redirectToPrivacyViewController(){
+ let storyBoard: UIStoryboard = UIStoryboard(name: "NCSettings", bundle: nil)
+ let newViewController = storyBoard.instantiateViewController(withIdentifier: "privacySettingsNavigation") as! UINavigationController
+ newViewController.modalPresentationStyle = .fullScreen
+ self.present(newViewController, animated: true, completion: nil)
+ }
func presentationControllerDidDismiss( _ presentationController: UIPresentationController) {
let viewController = presentationController.presentedViewController
diff --git a/iOSClient/Settings/AnalysisDataCollectionSwitch.swift b/iOSClient/Settings/AnalysisDataCollectionSwitch.swift
new file mode 100644
index 0000000000..e24216220f
--- /dev/null
+++ b/iOSClient/Settings/AnalysisDataCollectionSwitch.swift
@@ -0,0 +1,34 @@
+//
+// AnalysisDataCollectionSwitch.swift
+// Nextcloud
+//
+// Created by A200073704 on 25/04/23.
+// Copyright © 2023 Marino Faggiana. All rights reserved.
+//
+
+import UIKit
+
+class AnalysisDataCollectionSwitch: XLFormBaseCell {
+
+ @IBOutlet weak var cellLabel: UILabel!
+ @IBOutlet weak var analysisDataCollectionSwitchControl: UISwitch!
+
+ override func awakeFromNib() {
+ super.awakeFromNib()
+ // Initialization code
+ analysisDataCollectionSwitchControl.addTarget(self, action: #selector(switchChanged), for: UIControl.Event.valueChanged)
+ }
+
+ override func configure() {
+ super.configure()
+ }
+
+ override func update() {
+ super.update()
+ }
+
+ @objc func switchChanged(mySwitch: UISwitch) {
+ self.rowDescriptor.value = mySwitch.isOn
+ }
+}
+
diff --git a/iOSClient/Settings/AnalysisDataCollectionSwitch.xib b/iOSClient/Settings/AnalysisDataCollectionSwitch.xib
new file mode 100644
index 0000000000..45530193f6
--- /dev/null
+++ b/iOSClient/Settings/AnalysisDataCollectionSwitch.xib
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/iOSClient/Settings/InitialPrivacySettingsViewController.swift b/iOSClient/Settings/InitialPrivacySettingsViewController.swift
new file mode 100644
index 0000000000..2cd30a4242
--- /dev/null
+++ b/iOSClient/Settings/InitialPrivacySettingsViewController.swift
@@ -0,0 +1,170 @@
+//
+// InitialPrivacySettingsViewController.swift
+// Nextcloud
+//
+// Created by A200073704 on 25/04/23.
+// Copyright © 2023 Marino Faggiana. All rights reserved.
+//
+
+import Foundation
+import AppTrackingTransparency
+import AdSupport
+import UIKit
+
+class InitialPrivacySettingsViewController: UIViewController {
+
+ @IBOutlet weak var dataPrivacyImage: UIImageView!
+ @IBOutlet weak var acceptButton: UIButton!
+ @IBOutlet weak var privacySettingsHelpText: UITextView!
+ @IBOutlet weak var privacySettingsTitle: UILabel!
+ @IBOutlet weak var widthPriavacyHelpView: NSLayoutConstraint!
+ var privacyHelpText = ""
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ privacySettingsTitle.text = NSLocalizedString("_privacy_settings_title_", comment: "")
+ privacyHelpText = NSLocalizedString("_privacy_help_text_after_login_", comment: "")
+ privacySettingsHelpText.text = privacyHelpText
+ dataPrivacyImage.image = UIImage(named: "dataPrivacy")!.image(color: NCBrandColor.shared.brand, size: 60)
+ privacySettingsHelpText.delegate = self
+ privacySettingsHelpText.textColor = .label
+ privacySettingsHelpText.hyperLink(originalText: privacyHelpText,
+ linkTextsAndTypes: [NSLocalizedString("_key_privacy_help_", comment: ""): LinkType.privacyPolicy.rawValue,
+ NSLocalizedString("_key_reject_help_", comment: ""): LinkType.reject.rawValue,
+ NSLocalizedString("_key_settings_help_", comment: ""): LinkType.settings.rawValue])
+
+ acceptButton.backgroundColor = NCBrandColor.shared.brand
+ acceptButton.tintColor = UIColor.white
+ acceptButton.layer.cornerRadius = 5
+ acceptButton.layer.borderWidth = 1
+ acceptButton.layer.borderColor = NCBrandColor.shared.brand.cgColor
+ acceptButton.setTitle(NSLocalizedString("_accept_button_title_", comment: ""), for: .normal)
+ privacySettingsHelpText.centerText()
+ privacySettingsHelpText.font = UIFont(name: privacySettingsHelpText.font!.fontName, size: 16)
+ self.navigationItem.leftBarButtonItem?.tintColor = NCBrandColor.shared.brand
+ }
+
+ override func didReceiveMemoryWarning() {
+ super.didReceiveMemoryWarning()
+ // Dispose of any resources that can be recreated.
+ }
+
+ override func viewWillAppear(_ animated: Bool) {
+ super.viewWillAppear(animated)
+ self.navigationController?.navigationBar.isHidden = true
+ }
+
+ override func viewDidDisappear(_ animated: Bool) {
+ super.viewDidDisappear(animated)
+ self.navigationController?.navigationBar.isHidden = false
+ }
+
+ override func viewDidLayoutSubviews(){
+ if UIDevice.current.userInterfaceIdiom == .pad {
+ widthPriavacyHelpView.constant = UIScreen.main.bounds.width - 100
+ }
+ }
+
+ @IBAction func onAcceptButtonClicked(_ sender: Any) {
+ requestPermission()
+ }
+
+ //NEWLY ADDED PERMISSIONS FOR iOS 14
+ func requestPermission() {
+ UserDefaults.standard.set(true, forKey: "isInitialPrivacySettingsShowed")
+ UserDefaults.standard.set(true, forKey: "isAnalysisDataCollectionSwitchOn")
+ if #available(iOS 14, *) {
+ ATTrackingManager.requestTrackingAuthorization { status in
+ switch status {
+ case .authorized:
+ // Tracking authorization dialog was shown
+ // and we are authorized
+ print("Authorized")
+ // Now that we are authorized we can get the IDFA
+ print(ASIdentifierManager.shared().advertisingIdentifier)
+ case .denied:
+ UserDefaults.standard.set(true, forKey: "isInitialPrivacySettingsShowed")
+ UserDefaults.standard.set(false, forKey: "isAnalysisDataCollectionSwitchOn")
+ print("Denied")
+ case .notDetermined:
+ // Tracking authorization dialog has not been shown
+ print("Not Determined")
+ case .restricted:
+ print("Restricted")
+ @unknown default:
+ print("Unknown")
+ }
+ }
+ } else {
+ UserDefaults.standard.set(true, forKey: "isInitialPrivacySettingsShowed")
+ UserDefaults.standard.set(true, forKey: "isAnalysisDataCollectionSwitchOn")
+ }
+ self.dismiss(animated: true, completion: nil)
+ }
+}
+// MARK: - UITextViewDelegate
+extension InitialPrivacySettingsViewController: UITextViewDelegate {
+ func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
+ if let linkType = LinkType(rawValue: URL.absoluteString) {
+ // TODO: handle linktype here with switch or similar.
+ switch linkType {
+ case LinkType.privacyPolicy:
+ //let storyBoard: UIStoryboard = UIStoryboard(name: "NCSettings", bundle: nil)
+ let privacyViewController = PrivacyPolicyViewController()
+ self.navigationController?.pushViewController(privacyViewController, animated: true)
+ case LinkType.reject:
+ UserDefaults.standard.set(false, forKey: "isAnalysisDataCollectionSwitchOn")
+ UserDefaults.standard.set(true, forKey: "isInitialPrivacySettingsShowed")
+ self.dismiss(animated: true, completion: nil)
+ case LinkType.settings:
+ let privacySettingsViewController = PrivacySettingsViewController()
+ UserDefaults.standard.set(true, forKey: "showSettingsButton")
+ self.navigationController?.pushViewController(privacySettingsViewController, animated: true)
+ }
+ print("handle link:: \(linkType)")
+ }
+ return false
+ }
+}
+
+public extension UITextView {
+
+ func hyperLink(originalText: String, linkTextsAndTypes: [String: String]) {
+
+ let style = NSMutableParagraphStyle()
+ style.alignment = .left
+
+ let attributedOriginalText = NSMutableAttributedString(string: originalText)
+
+ let fullRange = NSRange(location: 0, length: attributedOriginalText.length)
+ attributedOriginalText.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.label, range: fullRange)
+ for linkTextAndType in linkTextsAndTypes {
+ let linkRange = attributedOriginalText.mutableString.range(of: linkTextAndType.key)
+ attributedOriginalText.addAttribute(NSAttributedString.Key.link, value: linkTextAndType.value, range: linkRange)
+ attributedOriginalText.addAttribute(NSAttributedString.Key.paragraphStyle, value: style, range: fullRange)
+ attributedOriginalText.addAttribute(NSAttributedString.Key.foregroundColor, value: NCBrandColor.shared.brand, range: linkRange)
+ attributedOriginalText.addAttribute(NSAttributedString.Key.font, value: UIFont.systemFont(ofSize: 10), range: fullRange)
+ }
+
+ self.linkTextAttributes = [NSAttributedString.Key.foregroundColor: NCBrandColor.shared.brand]
+ self.attributedText = attributedOriginalText
+ }
+
+ func centerText() {
+ self.textAlignment = .justified
+ let fittingSize = CGSize(width: 300, height: CGFloat.greatestFiniteMagnitude)
+ let size = sizeThatFits(fittingSize)
+ let topOffset = (bounds.size.height - size.height * zoomScale) / 2
+ let positiveTopOffset = max(1, topOffset)
+ contentOffset.y = -positiveTopOffset
+ }
+}
+
+enum LinkType: String {
+ case reject
+ case privacyPolicy
+ case settings
+}
+
+
diff --git a/iOSClient/Settings/NCSettings.storyboard b/iOSClient/Settings/NCSettings.storyboard
new file mode 100644
index 0000000000..19a320515b
--- /dev/null
+++ b/iOSClient/Settings/NCSettings.storyboard
@@ -0,0 +1,236 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/iOSClient/Settings/PrivacyPolicyViewController.swift b/iOSClient/Settings/PrivacyPolicyViewController.swift
new file mode 100644
index 0000000000..141c444fca
--- /dev/null
+++ b/iOSClient/Settings/PrivacyPolicyViewController.swift
@@ -0,0 +1,62 @@
+//
+// PrivacyPolicyViewController.swift
+// Nextcloud
+//
+// Created by A200073704 on 25/04/23.
+// Copyright © 2023 Marino Faggiana. All rights reserved.
+//
+
+import Foundation
+import UIKit
+import WebKit
+
+class PrivacyPolicyViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {
+
+ var myWebView = WKWebView()
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ self.title = NSLocalizedString("_privacy_policy_", comment: "")
+
+ myWebView = WKWebView(frame: CGRect(x:0, y:0, width: UIScreen.main.bounds.width, height:UIScreen.main.bounds.height))
+ myWebView.uiDelegate = self
+ myWebView.navigationDelegate = self
+ myWebView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+ self.view.addSubview(myWebView)
+
+ //1. Load web site into my web view
+ let myURL = URL(string: "https://static.magentacloud.de/privacy/datenschutzhinweise_app.htm")
+ let myURLRequest:URLRequest = URLRequest(url: myURL!)
+ NCActivityIndicator.shared.start()
+ myWebView.load(myURLRequest)
+ self.navigationController?.navigationBar.tintColor = NCBrandColor.shared.brand
+ }
+
+ override func viewDidAppear(_ animated: Bool) {
+ super.viewDidAppear(animated)
+ myWebView = WKWebView(frame: CGRect(x:0, y:0, width: UIScreen.main.bounds.width, height:UIScreen.main.bounds.height))
+ }
+ override func didReceiveMemoryWarning() {
+ super.didReceiveMemoryWarning()
+ // Dispose of any resources that can be recreated.
+ }
+
+ func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
+ NCActivityIndicator.shared.stop()
+ }
+
+ func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
+ if navigationAction.navigationType == .linkActivated {
+ if let url = navigationAction.request.url,
+ UIApplication.shared.canOpenURL(url) {
+ UIApplication.shared.open(url)
+ decisionHandler(.cancel)
+ } else {
+ decisionHandler(.allow)
+ }
+ } else {
+ decisionHandler(.allow)
+ }
+ }
+}
diff --git a/iOSClient/Settings/PrivacySettingsViewController.swift b/iOSClient/Settings/PrivacySettingsViewController.swift
new file mode 100644
index 0000000000..b7883ad800
--- /dev/null
+++ b/iOSClient/Settings/PrivacySettingsViewController.swift
@@ -0,0 +1,147 @@
+//
+// PrivacySettingsViewController.swift
+// Nextcloud
+//
+// Created by A200073704 on 25/04/23.
+// Copyright © 2023 Marino Faggiana. All rights reserved.
+//
+
+import Foundation
+import AppTrackingTransparency
+import AdSupport
+
+class PrivacySettingsViewController: XLFormViewController{
+
+ @objc public var isShowSettingsButton: Bool = false
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ self.title = NSLocalizedString("_privacy_settings_title_", comment: "")
+
+ NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil)
+
+ let nib = UINib(nibName: "CustomSectionHeader", bundle: nil)
+ self.tableView.register(nib, forHeaderFooterViewReuseIdentifier: "customSectionHeader")
+ isShowSettingsButton = UserDefaults.standard.bool(forKey: "showSettingsButton")
+ self.navigationController?.navigationBar.tintColor = NCBrandColor.shared.brand
+ changeTheming()
+ }
+
+ @objc func changeTheming() {
+ tableView.backgroundColor = .systemGroupedBackground
+ tableView.separatorColor = .none
+ tableView.separatorColor = .clear
+ tableView.reloadData()
+ initializeForm()
+ }
+
+
+
+ //MARK: XLForm
+
+ func initializeForm() {
+
+ let form : XLFormDescriptor = XLFormDescriptor() as XLFormDescriptor
+ form.rowNavigationOptions = XLFormRowNavigationOptions.stopDisableRow
+
+ var section : XLFormSectionDescriptor
+ var row : XLFormRowDescriptor
+
+ // Section: Destination Folder
+
+ section = XLFormSectionDescriptor.formSection(withTitle: NSLocalizedString("", comment: "").uppercased())
+ section.footerTitle = " "
+ form.addFormSection(section)
+
+ section = XLFormSectionDescriptor.formSection(withTitle: NSLocalizedString("", comment: "").uppercased())
+ section.footerTitle = NSLocalizedString("_privacy_settings_help_text_", comment: "")
+ form.addFormSection(section)
+
+
+ //custom cell
+ section = XLFormSectionDescriptor.formSection(withTitle: "")
+ section.footerTitle = NSLocalizedString("_required_data_collection_help_text_", comment: "")
+ form.addFormSection(section)
+
+
+ XLFormViewController.cellClassesForRowDescriptorTypes()["RequiredDataCollectionCustomCellType"] = RequiredDataCollectionSwitch.self
+
+
+ row = XLFormRowDescriptor(tag: "ButtonDestinationFolder", rowType: "RequiredDataCollectionCustomCellType", title: "")
+ row.cellConfig["requiredDataCollectionSwitchControl.onTintColor"] = NCBrandColor.shared.brand
+ row.cellConfig["cellLabel.textAlignment"] = NSTextAlignment.left.rawValue
+ row.cellConfig["cellLabel.font"] = UIFont.systemFont(ofSize: 15.0)
+ row.cellConfig["cellLabel.textColor"] = UIColor.label //photos
+ row.cellConfig["cellLabel.text"] = NSLocalizedString("_required_data_collection_", comment: "")
+ section.addFormRow(row)
+
+ section = XLFormSectionDescriptor.formSection(withTitle: NSLocalizedString("", comment: "").uppercased())
+ section.footerTitle = NSLocalizedString("_analysis_data_acqusition_help_text_", comment: "")
+ form.addFormSection(section)
+
+ XLFormViewController.cellClassesForRowDescriptorTypes()["AnalysisDataCollectionCustomCellType"] = AnalysisDataCollectionSwitch.self
+
+
+ row = XLFormRowDescriptor(tag: "AnalysisDataCollectionSwitch", rowType: "AnalysisDataCollectionCustomCellType", title: "")
+ row.cellConfig["analysisDataCollectionSwitchControl.onTintColor"] = NCBrandColor.shared.brand
+ row.cellConfig["cellLabel.textAlignment"] = NSTextAlignment.left.rawValue
+ row.cellConfig["cellLabel.font"] = UIFont.systemFont(ofSize: 15.0)
+ row.cellConfig["cellLabel.textColor"] = UIColor.label //photos
+ row.cellConfig["cellLabel.text"] = NSLocalizedString("_analysis_data_acqusition_", comment: "")
+ if(UserDefaults.standard.bool(forKey: "isAnalysisDataCollectionSwitchOn")){
+ row.cellConfigAtConfigure["analysisDataCollectionSwitchControl.on"] = 1
+ }else {
+ row.cellConfigAtConfigure["analysisDataCollectionSwitchControl.on"] = 0
+ }
+
+ section.addFormRow(row)
+
+
+ XLFormViewController.cellClassesForRowDescriptorTypes()["SaveSettingsButton"] = SaveSettingsCustomButtonCell.self
+
+ section = XLFormSectionDescriptor.formSection(withTitle: "")
+ form.addFormSection(section)
+
+
+ row = XLFormRowDescriptor(tag: "SaveSettingsButton", rowType: "SaveSettingsButton", title: "")
+ row.cellConfig["backgroundColor"] = UIColor.clear
+
+ if(isShowSettingsButton){
+ section.addFormRow(row)
+ }
+
+
+ self.form = form
+ }
+
+
+ override func formRowDescriptorValueHasChanged(_ formRow: XLFormRowDescriptor!, oldValue: Any!, newValue: Any!) {
+ super.formRowDescriptorValueHasChanged(formRow, oldValue: oldValue, newValue: newValue)
+
+ if formRow.tag == "SaveSettingsButton" {
+ print("save settings clicked")
+ //TODO save button state and leave the page
+ self.navigationController?.popViewController(animated: true)
+
+ }
+ if formRow.tag == "AnalysisDataCollectionSwitch"{
+ if (formRow.value! as AnyObject).boolValue {
+ if #available(iOS 14, *) {
+ ATTrackingManager.requestTrackingAuthorization(completionHandler: { (status) in
+ if status == .denied {
+ guard let url = URL(string: UIApplication.openSettingsURLString) else {
+ return
+ }
+ if UIApplication.shared.canOpenURL(url) {
+ UIApplication.shared.open(url, options: [:])
+ }
+ }
+ })
+ }
+ }
+ UserDefaults.standard.set((formRow.value! as AnyObject).boolValue, forKey: "isAnalysisDataCollectionSwitchOn")
+ }
+
+ }
+
+}
diff --git a/iOSClient/Settings/RequiredDataCollectionSwitch.swift b/iOSClient/Settings/RequiredDataCollectionSwitch.swift
new file mode 100644
index 0000000000..f80aa97e89
--- /dev/null
+++ b/iOSClient/Settings/RequiredDataCollectionSwitch.swift
@@ -0,0 +1,34 @@
+//
+// RequiredDataCollectionSwitch.swift
+// Nextcloud
+//
+// Created by A200073704 on 25/04/23.
+// Copyright © 2023 Marino Faggiana. All rights reserved.
+//
+
+import UIKit
+
+
+class RequiredDataCollectionSwitch: XLFormBaseCell {
+
+ @IBOutlet weak var cellLabel: UILabel!
+ @IBOutlet weak var requiredDataCollectionSwitchControl: UISwitch!
+
+ override func awakeFromNib() {
+ super.awakeFromNib()
+ // Initialization code
+ //requiredDataCollectionSwitchControl.addTarget(self, action: #selector(switchChanged), for: UIControl.Event.valueChanged)
+
+ }
+
+ override func configure() {
+ super.configure()
+
+ requiredDataCollectionSwitchControl.isOn = true
+ requiredDataCollectionSwitchControl.isEnabled = false
+ }
+
+ override func update() {
+ super.update()
+ }
+}
diff --git a/iOSClient/Settings/RequiredDataCollectionSwitch.xib b/iOSClient/Settings/RequiredDataCollectionSwitch.xib
new file mode 100644
index 0000000000..66156c6e06
--- /dev/null
+++ b/iOSClient/Settings/RequiredDataCollectionSwitch.xib
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/iOSClient/Settings/SaveSettingsCustomButtonCell.swift b/iOSClient/Settings/SaveSettingsCustomButtonCell.swift
new file mode 100644
index 0000000000..6205727723
--- /dev/null
+++ b/iOSClient/Settings/SaveSettingsCustomButtonCell.swift
@@ -0,0 +1,46 @@
+//
+// SaveSettingsCustomButtonCell.swift
+// Nextcloud
+//
+// Created by A200073704 on 25/04/23.
+// Copyright © 2023 Marino Faggiana. All rights reserved.
+//
+
+import UIKit
+
+
+class SaveSettingsCustomButtonCell: XLFormButtonCell {
+
+ @IBOutlet weak var saveSettingsButton: UIButton!
+
+ override func awakeFromNib() {
+ super.awakeFromNib()
+ // Initialization code
+ self.selectionStyle = .none
+ self.separatorInset = UIEdgeInsets(top: 0, left: .greatestFiniteMagnitude, bottom: 0, right: .greatestFiniteMagnitude)
+ saveSettingsButton.setTitle(NSLocalizedString("_save_settings_", comment: ""), for: .normal)
+ saveSettingsButton.addTarget(self, action: #selector(saveButtonClicked), for: .touchUpInside)
+
+ }
+
+ override func configure() {
+ super.configure()
+ saveSettingsButton.backgroundColor = NCBrandColor.shared.brand
+ saveSettingsButton.tintColor = UIColor.white
+ saveSettingsButton.layer.cornerRadius = 5
+ saveSettingsButton.layer.borderWidth = 1
+ saveSettingsButton.layer.borderColor = NCBrandColor.shared.brand.cgColor
+
+ }
+
+ override func update() {
+ super.update()
+
+ }
+
+ @objc func saveButtonClicked(sender: UIButton) {
+ self.rowDescriptor.value = sender
+
+ }
+
+}
diff --git a/iOSClient/Settings/SaveSettingsCustomButtonCell.xib b/iOSClient/Settings/SaveSettingsCustomButtonCell.xib
new file mode 100644
index 0000000000..0dd197da31
--- /dev/null
+++ b/iOSClient/Settings/SaveSettingsCustomButtonCell.xib
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+