Skip to content

Commit 6c410bc

Browse files
committed
- HelpAndSupportViewController: new view controller providing an overview of help and support options with a brief textual description, adding the forums to the mix
- MoreSettingsSection: for non-branded apps show "Help & Support" instead of "Documentation", "Help" and "Feedback" in the Settings - VendorServices+App / MoreSettingsSection: refactor to make openSFWebView(on:for:withConfirmation:) part of VendorServices and thereby available to the whole code base - PDFViewerViewController: make use of VendorServices new openSFWebView(on:for:withConfirmation:) method to ask the user before opening URLs
1 parent 885dd57 commit 6c410bc

File tree

6 files changed

+185
-33
lines changed

6 files changed

+185
-33
lines changed

ownCloud.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@
224224
DC16213E2B8FF06800EB17F8 /* OCSidebarItem+Interactions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC16213D2B8FF06800EB17F8 /* OCSidebarItem+Interactions.swift */; };
225225
DC18898E218A773700CFB3F9 /* ownCloudMocking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC0196A620F754CA00C41B78 /* ownCloudMocking.framework */; };
226226
DC1B270C209CF34B004715E1 /* BookmarkViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC1B270B209CF34B004715E1 /* BookmarkViewController.swift */; };
227+
DC1BEEF62C2DFE940016C94F /* HelpAndSupportViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC1BEEF52C2DFE940016C94F /* HelpAndSupportViewController.swift */; };
227228
DC20DE6A21C01B210096000B /* ownCloudSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 239369782076110900BCE21A /* ownCloudSDK.framework */; };
228229
DC20DE6B21C01B210096000B /* ownCloudUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2393697C2076110900BCE21A /* ownCloudUI.framework */; };
229230
DC2218C62822C5B900808BCE /* OCVFSNode+FileProviderItem.m in Sources */ = {isa = PBXBuildFile; fileRef = DC2218C52822C5B900808BCE /* OCVFSNode+FileProviderItem.m */; };
@@ -1290,6 +1291,7 @@
12901291
DC16213D2B8FF06800EB17F8 /* OCSidebarItem+Interactions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OCSidebarItem+Interactions.swift"; sourceTree = "<group>"; };
12911292
DC1AC7CF2319ADAE002B7892 /* ScanViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanViewController.swift; sourceTree = "<group>"; };
12921293
DC1B270B209CF34B004715E1 /* BookmarkViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkViewController.swift; sourceTree = "<group>"; };
1294+
DC1BEEF52C2DFE940016C94F /* HelpAndSupportViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpAndSupportViewController.swift; sourceTree = "<group>"; };
12931295
DC2218C42822C5B900808BCE /* OCVFSNode+FileProviderItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "OCVFSNode+FileProviderItem.h"; sourceTree = "<group>"; };
12941296
DC2218C52822C5B900808BCE /* OCVFSNode+FileProviderItem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "OCVFSNode+FileProviderItem.m"; sourceTree = "<group>"; };
12951297
DC2218CA2823329100808BCE /* FileProviderContentEnumerator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FileProviderContentEnumerator.h; sourceTree = "<group>"; };
@@ -2626,6 +2628,7 @@
26262628
4C1561E7222321E0009C4EF3 /* PhotoSelectionViewController.swift */,
26272629
4C1561EE22232357009C4EF3 /* PhotoSelectionViewCell.swift */,
26282630
DC6CC3142642C3560040ECAC /* ExternalBrowserBusyHandler.swift */,
2631+
DC1BEEF52C2DFE940016C94F /* HelpAndSupportViewController.swift */,
26292632
);
26302633
path = Client;
26312634
sourceTree = "<group>";
@@ -4666,6 +4669,7 @@
46664669
DC63208521FCEBE9007EC0A8 /* ClientActivityCell.swift in Sources */,
46674670
DC62514A225CEB4300736874 /* UploadMediaAction.swift in Sources */,
46684671
025FC72924781659009307A7 /* AutoUploadSettingsSection.swift in Sources */,
4672+
DC1BEEF62C2DFE940016C94F /* HelpAndSupportViewController.swift in Sources */,
46694673
DC9BFBBD20A1C37B007064B5 /* PasswordManagerAccess.swift in Sources */,
46704674
23D5241521491C670002C566 /* DisplayViewController.swift in Sources */,
46714675
DCB7969D2BCE71C300D6D759 /* OpenShortcutFileAction.swift in Sources */,
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//
2+
// HelpAndSupportViewController.swift
3+
// ownCloud
4+
//
5+
// Created by Felix Schwarz on 27.06.24.
6+
// Copyright © 2024 ownCloud GmbH. All rights reserved.
7+
//
8+
9+
/*
10+
* Copyright (C) 2024, ownCloud GmbH.
11+
*
12+
* This code is covered by the GNU Public License Version 3.
13+
*
14+
* For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/
15+
* You should have received a copy of this license along with this program. If not, see <http://www.gnu.org/licenses/gpl-3.0.en.html>.
16+
*
17+
*/
18+
19+
import UIKit
20+
import ownCloudSDK
21+
import ownCloudApp
22+
import ownCloudAppShared
23+
24+
class HelpAndSupportViewController: CollectionViewController {
25+
init() {
26+
super.init(context: nil, sections: nil, useStackViewRoot: true)
27+
28+
add(sections: [
29+
helpAndSupportSection()
30+
])
31+
}
32+
33+
required init?(coder: NSCoder) {
34+
fatalError("init(coder:) has not been implemented")
35+
}
36+
37+
override func viewDidLoad() {
38+
super.viewDidLoad()
39+
40+
cssSelectors = [.modal]
41+
42+
navigationItem.title = "Help & Support".localized
43+
navigationItem.largeTitleDisplayMode = .always
44+
45+
navigationItem.rightBarButtonItem = UIBarButtonItem(systemItem: .close, primaryAction: UIAction(handler: { [weak self] _ in
46+
self?.dismiss(animated: true)
47+
}))
48+
}
49+
50+
func helpAndSupportSection() -> CollectionViewSection {
51+
var elements: [ComposedMessageElement] = []
52+
53+
if let documentationURL = VendorServices.shared.documentationURL {
54+
elements.append(contentsOf: [
55+
.title("Documentation".localized),
56+
.text("Find information, answers and solutions in the detailed documentation.".localized, style: .informal, cssSelectors: [.message]),
57+
.spacing(5),
58+
59+
.button("View documentation".localized, action: UIAction(handler: { [weak self] _ in
60+
if let self {
61+
VendorServices.shared.openSFWebView(on: self, for: documentationURL)
62+
}
63+
}), image: nil, cssSelectors: [ .info ]),
64+
65+
.spacing(20)
66+
])
67+
}
68+
69+
elements.append(contentsOf: [
70+
.title("Help".localized),
71+
.text("Get in touch with our community in the forums - or file a GitHub issue to report a bug or request a feature.".localized, style: .informal, cssSelectors: [.message]),
72+
.spacing(5),
73+
74+
.button("File an issue".localized, action: UIAction(handler: { [weak self] _ in
75+
if let self {
76+
VendorServices.shared.openSFWebView(on: self, for: URL(string: "https://github.com/owncloud/ios-app/issues/new/choose")!)
77+
}
78+
}), image: nil, cssSelectors: [ .info ]),
79+
80+
.button("Visit the forums".localized, action: UIAction(handler: { [weak self] _ in
81+
if let self {
82+
VendorServices.shared.openSFWebView(on: self, for: URL(string: "https://central.owncloud.org/c/ios/")!)
83+
}
84+
}), image: nil, cssSelectors: [ .info ]),
85+
86+
.spacing(20)
87+
])
88+
89+
if (VendorServices.shared.feedbackMail != nil) || (Branding.shared.feedbackURL != nil) {
90+
elements.append(contentsOf: [
91+
.title("Send feedback".localized),
92+
93+
.text("If you don't need a response and just want to send us feedback, you can also send us a mail.".localized, style: .informal, cssSelectors: [.message]),
94+
.spacing(5),
95+
96+
.button("Send feedback".localized, action: UIAction(handler: { _ in
97+
VendorServices.shared.sendFeedback(from: self)
98+
}), image: nil, cssSelectors: [ .info ], insets: .zero)
99+
])
100+
}
101+
102+
let section = CollectionViewSection(identifier: "helpAndSupport", dataSource: OCDataSourceArray(items: [
103+
ComposedMessageView(elements: elements)
104+
]))
105+
106+
return section
107+
}
108+
}

ownCloud/Client/Viewer/PDF/PDFViewerViewController.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import UIKit
2020
import ownCloudSDK
2121
import ownCloudAppShared
2222
import PDFKit
23-
import SafariServices
2423

2524
class PulsatingButton: UIButton {
2625

@@ -510,7 +509,6 @@ class PDFViewerViewController: DisplayViewController, DisplayExtension, UIPopove
510509

511510
extension PDFViewerViewController : PDFViewDelegate {
512511
func pdfViewWillClick(onLink sender: PDFView, with url: URL) {
513-
let vc = SFSafariViewController(url: url)
514-
present(vc, animated: true)
512+
VendorServices.shared.openSFWebView(on: self, for: url)
515513
}
516514
}

ownCloud/Resources/en.lproj/Localizable.strings

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,17 @@
319319
"App Version" = "App Version";
320320
"Version information were copied to the clipboard" = "Version information were copied to the clipboard";
321321

322+
/* Help and support */
323+
"Help & Support" = "Help & Support";
324+
325+
"Find information, answers and solutions in the detailed documentation." = "Find information, answers and solutions in the detailed documentation.";
326+
"View documentation" = "View documentation";
327+
328+
"Get in touch with our community in the forums - or file a GitHub issue to report a bug or request a feature." = "Get in touch with our community in the forums - or file a GitHub issue to report a bug or request a feature.";
329+
"File an issue" = "File an issue";
330+
"Visit the forums" = "Visit the forums";
331+
332+
"If you don't need a response and just want to send us feedback, you can also send us a mail." = "If you don't need a response and just want to send us feedback, you can also send us a mail.";
322333

323334
/* User Interface Settings */
324335
"Theme" = "Theme";

ownCloud/Settings/MoreSettingsSection.swift

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import CoreFoundation
2020
import UIKit
2121
import WebKit
2222
import MessageUI
23-
import SafariServices
2423
import ownCloudSDK
2524
import ownCloudApp
2625
import ownCloudAppShared
@@ -31,6 +30,7 @@ class MoreSettingsSection: SettingsSection {
3130
private var documentationRow: StaticTableViewRow?
3231
private var helpRow: StaticTableViewRow?
3332
private var sendFeedbackRow: StaticTableViewRow?
33+
private var helpAndSupportRow: StaticTableViewRow?
3434
private var recommendRow: StaticTableViewRow?
3535
private var privacyPolicyRow: StaticTableViewRow?
3636
private var termsOfUseRow: StaticTableViewRow?
@@ -52,14 +52,16 @@ class MoreSettingsSection: SettingsSection {
5252
private func createRows() {
5353

5454
documentationRow = StaticTableViewRow(rowWithAction: { [weak self] (_, _) in
55-
if let url = VendorServices.shared.documentationURL {
56-
self?.openSFWebViewWithConfirmation(for: url)
55+
if let url = VendorServices.shared.documentationURL, let viewController = self?.viewController {
56+
VendorServices.shared.openSFWebView(on: viewController, for: url)
5757
}
5858
}, title: "Documentation".localized, accessoryType: .disclosureIndicator, identifier: "documentation")
5959

6060
if let helpURL = VendorServices.shared.helpURL {
6161
helpRow = StaticTableViewRow(rowWithAction: { [weak self] (_, _) in
62-
self?.openSFWebViewWithConfirmation(for: helpURL)
62+
if let viewController = self?.viewController {
63+
VendorServices.shared.openSFWebView(on: viewController, for: helpURL)
64+
}
6365
}, title: "Help".localized, accessoryType: .disclosureIndicator, identifier: "help")
6466
}
6567

@@ -69,6 +71,12 @@ class MoreSettingsSection: SettingsSection {
6971
}
7072
}, title: "Send feedback".localized, accessoryType: .disclosureIndicator, identifier: "send-feedback")
7173

74+
helpAndSupportRow = StaticTableViewRow(rowWithAction: { [weak self] (_, _) in
75+
if let viewController = self?.viewController {
76+
VendorServices.shared.showHelpAndSupportOptions(from: viewController)
77+
}
78+
}, title: "Help & Support".localized, accessoryType: .disclosureIndicator, identifier: "help-and-support")
79+
7280
recommendRow = StaticTableViewRow(rowWithAction: { [weak self] (_, _) in
7381
if let viewController = self?.viewController {
7482
VendorServices.shared.recommendToFriend(from: viewController)
@@ -77,13 +85,17 @@ class MoreSettingsSection: SettingsSection {
7785

7886
if let privacyURL = VendorServices.shared.privacyURL {
7987
privacyPolicyRow = StaticTableViewRow(rowWithAction: { [weak self] (_, _) in
80-
self?.openSFWebViewWithConfirmation(for: privacyURL)
88+
if let viewController = self?.viewController {
89+
VendorServices.shared.openSFWebView(on: viewController, for: privacyURL)
90+
}
8191
}, title: "Privacy Policy".localized, accessoryType: .disclosureIndicator, identifier: "privacy-policy")
8292
}
8393

8494
if let termsOfUseURL = VendorServices.shared.termsOfUseURL {
8595
termsOfUseRow = StaticTableViewRow(rowWithAction: { [weak self] (_, _) in
86-
self?.openSFWebViewWithConfirmation(for: termsOfUseURL)
96+
if let viewController = self?.viewController {
97+
VendorServices.shared.openSFWebView(on: viewController, for: termsOfUseURL)
98+
}
8799
}, title: "Terms Of Use".localized, accessoryType: .disclosureIndicator, identifier: "terms-of-use")
88100
}
89101

@@ -115,16 +127,22 @@ class MoreSettingsSection: SettingsSection {
115127
func updateUI() {
116128
var rows : [StaticTableViewRow] = []
117129

118-
if VendorServices.shared.documentationURL != nil {
119-
rows.append(documentationRow!)
120-
}
130+
if Branding.shared.isBranded {
131+
if VendorServices.shared.documentationURL != nil {
132+
rows.append(documentationRow!)
133+
}
121134

122-
if VendorServices.shared.helpURL != nil {
123-
rows.append(helpRow!)
124-
}
135+
if VendorServices.shared.helpURL != nil {
136+
rows.append(helpRow!)
137+
}
125138

126-
if VendorServices.shared.feedbackMail != nil || Branding.shared.feedbackURL != nil {
127-
rows.append(sendFeedbackRow!)
139+
if VendorServices.shared.feedbackMail != nil || Branding.shared.feedbackURL != nil {
140+
rows.append(sendFeedbackRow!)
141+
}
142+
} else {
143+
if VendorServices.shared.documentationURL != nil || (VendorServices.shared.feedbackMail != nil || Branding.shared.feedbackURL != nil) {
144+
rows.append(helpAndSupportRow!)
145+
}
128146
}
129147

130148
if let recommendToFriend = VendorServices.classSetting(forOCClassSettingsKey: .recommendToFriendEnabled) as? Bool, recommendToFriend {
@@ -142,18 +160,4 @@ class MoreSettingsSection: SettingsSection {
142160

143161
add(rows: rows)
144162
}
145-
146-
private func openSFWebViewWithConfirmation(for url: URL) {
147-
let alert = ThemedAlertController(title: "Do you want to open the following URL?".localized,
148-
message: url.absoluteString,
149-
preferredStyle: .alert)
150-
151-
let okAction = UIAlertAction(title: "OK", style: .default) { (_) in
152-
self.viewController?.present(SFSafariViewController(url: url), animated: true)
153-
}
154-
let cancelAction = UIAlertAction(title: "Cancel".localized, style: .cancel)
155-
alert.addAction(okAction)
156-
alert.addAction(cancelAction)
157-
self.viewController?.present(alert, animated: true)
158-
}
159163
}

ownCloud/Tools/VendorServices+App.swift

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ import MessageUI
2121
import ownCloudApp
2222
import ownCloudAppShared
2323
import ownCloudSDK
24+
import SafariServices
2425

2526
extension VendorServices {
2627
public func recommendToFriend(from viewController: UIViewController) {
27-
2828
guard let appStoreLink = self.classSetting(forOCClassSettingsKey: .appStoreLink) as? String else {
29-
return
29+
return
3030
}
3131
let appName = VendorServices.shared.appName
3232

@@ -37,6 +37,15 @@ extension VendorServices {
3737
self.sendMail(to: nil, subject: "Try \(appName) on your smartphone!", message: message, from: viewController)
3838
}
3939

40+
public func showHelpAndSupportOptions(from viewController: UIViewController) {
41+
let feedbackViewController = HelpAndSupportViewController()
42+
43+
let navigationViewController = ThemeNavigationController(rootViewController: feedbackViewController)
44+
navigationViewController.navigationBar.prefersLargeTitles = true
45+
46+
viewController.present(navigationViewController, animated: true)
47+
}
48+
4049
public func sendFeedback(from viewController: UIViewController) {
4150
if let sendFeedbackURL = Branding.shared.feedbackURL {
4251
UIApplication.shared.open(sendFeedbackURL, options: [:], completionHandler: nil)
@@ -86,6 +95,24 @@ extension VendorServices {
8695
viewController.present(alert, animated: true)
8796
}
8897
}
98+
99+
public func openSFWebView(on viewController: UIViewController, for url: URL, withConfirmation: Bool = true) {
100+
if withConfirmation {
101+
let alert = ThemedAlertController(title: "Do you want to open the following URL?".localized,
102+
message: url.absoluteString,
103+
preferredStyle: .alert)
104+
105+
let okAction = UIAlertAction(title: "OK", style: .default) { (_) in
106+
viewController.present(SFSafariViewController(url: url), animated: true)
107+
}
108+
let cancelAction = UIAlertAction(title: "Cancel".localized, style: .cancel)
109+
alert.addAction(okAction)
110+
alert.addAction(cancelAction)
111+
viewController.present(alert, animated: true)
112+
} else {
113+
viewController.present(SFSafariViewController(url: url), animated: true)
114+
}
115+
}
89116
}
90117

91118
extension VendorServices: MFMailComposeViewControllerDelegate {

0 commit comments

Comments
 (0)