mirror of
https://github.com/confirmedcode/Lockdown-iOS.git
synced 2025-12-21 12:14:02 +01:00
commit 1c1067e30104c2670c6339d1f16b7bd55406481b Merge: d3d2df9 70a2319 Author: Pavel Vilbik <Pavel.Vilbik@joinappex.com> Date: Wed Jun 28 14:07:47 2023 +0300 Merge branch 'local/KB-6393_questionnaire' of https://github.com/joinappex/lockdown-ios-2.0 into local/KB-6393_questionnaire commit d3d2df991e9b6358982ba6d38541f726772f2fd1 Author: Pavel Vilbik <Pavel.Vilbik@joinappex.com> Date: Wed Jun 28 13:19:42 2023 +0300 add sending message commit 70a23193dcb3deae1341ee318bf536e49ecf3c2a Author: Pavel Vilbik <Pavel.Vilbik@joinappex.com> Date: Wed Jun 28 13:19:42 2023 +0300 add sending message commit 9a290eb556f0ad4751b49cd53be17de903edd0ac Author: Pavel Vilbik <Pavel.Vilbik@joinappex.com> Date: Wed Jun 28 13:05:32 2023 +0300 add generating message commit 341293cab9466eab31a1886b6d43d59cc43a3e61 Author: Pavel Vilbik <Pavel.Vilbik@joinappex.com> Date: Wed Jun 28 12:35:53 2023 +0300 refactoring model of questions commit 0482bce1c1955a0562deaaabeb48aca04f16302c Author: Pavel Vilbik <Pavel.Vilbik@joinappex.com> Date: Wed Jun 28 12:12:02 2023 +0300 add select region commit 151b94c742fe9cc29e730c18d57a7cf868878ea3 Author: Pavel Vilbik <Pavel.Vilbik@joinappex.com> Date: Wed Jun 28 11:30:03 2023 +0300 add select country commit f75596a13b9e17dacfc05a57674acb4d65680229 Author: Pavel Vilbik <Pavel.Vilbik@joinappex.com> Date: Tue Jun 27 14:19:40 2023 +0300 add navigation link view commit a9a83f462ffa3c7ec066d8ee5254b2d8cb6416ed Author: Pavel Vilbik <Pavel.Vilbik@joinappex.com> Date: Mon Jun 26 18:25:23 2023 +0300 add questions title view commit 08d3eb1d7873bf4ccedd4b8fbf280213520bb9c3 Author: Pavel Vilbik <Pavel.Vilbik@joinappex.com> Date: Mon Jun 26 16:20:01 2023 +0300 add yes/no views commit b6a16aa2bbd0c1bbe607170d16f430ad522c4d5f Author: Pavel Vilbik <Pavel.Vilbik@joinappex.com> Date: Mon Jun 26 12:48:23 2023 +0300 fixed skip button commit 5bf7fb8799f4b79e1a37a58a2f3b5862ea9f1da5 Author: Pavel Vilbik <Pavel.Vilbik@joinappex.com> Date: Mon Jun 26 12:41:59 2023 +0300 refactoring step view model commit 8871dc2ebc0728d3491e6807b4426963741baa4a Author: Pavel Vilbik <Pavel.Vilbik@joinappex.com> Date: Mon Jun 26 12:04:26 2023 +0300 refactoring step view model commit e5b2e02191217546d47454a471e101c242d89464 Author: Pavel Vilbik <Pavel.Vilbik@joinappex.com> Date: Fri Jun 23 18:49:07 2023 +0300 add view model for content commit b84b9130771aaa521acee0abdf28f3bba2b82771 Author: Pavel Vilbik <p.vilbik@softteco.com> Date: Fri Jun 23 14:44:41 2023 +0300 add textview cell commit e0985ae6c1a5c519e4fd83d5359b68621a18093b Author: Pavel Vilbik <p.vilbik@softteco.com> Date: Fri Jun 23 12:16:51 2023 +0300 add title view commit 24908af4d5b914364df3542b77cecdaaa497d105 Author: Pavel Vilbik <p.vilbik@softteco.com> Date: Thu Jun 22 17:34:07 2023 +0300 add view for problem cell commit 9df1a479a404528efba0452bde0d4291648b49b7 Author: Pavel Vilbik <p.vilbik@softteco.com> Date: Thu Jun 22 17:14:49 2023 +0300 add radio switcher view commit 5ed6c1d3bd4acf00d40f5dbe81cfcbbbd8bf63c0 Author: Pavel Vilbik <p.vilbik@softteco.com> Date: Thu Jun 22 15:49:32 2023 +0300 add base view for questionnaire
376 lines
16 KiB
Swift
376 lines
16 KiB
Swift
//
|
|
// BaseViewController.swift
|
|
// Lockdown
|
|
//
|
|
// Copyright © 2019 Confirmed Inc. All rights reserved.
|
|
//
|
|
|
|
import UIKit
|
|
import MessageUI
|
|
import CocoaLumberjackSwift
|
|
import PopupDialog
|
|
|
|
open class BaseViewController: UIViewController, MFMailComposeViewControllerDelegate {
|
|
|
|
let interactionBlockViewTag = 84814
|
|
|
|
override open func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
|
|
// disable swipe down to dismiss
|
|
if #available(iOS 13.0, *) {
|
|
self.isModalInPresentation = true
|
|
}
|
|
|
|
// let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(emailTeam))
|
|
// longPressRecognizer.minimumPressDuration = 4
|
|
// self.view.addGestureRecognizer(longPressRecognizer)
|
|
|
|
// let doubleLongPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(signoutUser))
|
|
// doubleLongPressRecognizer.minimumPressDuration = 5
|
|
// doubleLongPressRecognizer.numberOfTouchesRequired = 2
|
|
// self.view.addGestureRecognizer(doubleLongPressRecognizer)
|
|
}
|
|
|
|
// MARK: - AwesomeSpotlight Helper
|
|
|
|
func getRectForView(_ v: UIView) -> CGRect {
|
|
if let sv = v.superview {
|
|
return sv.convert(v.frame, to: self.view)
|
|
}
|
|
return CGRect.zero;
|
|
}
|
|
|
|
// MARK: - Handle NSURLError and APIErrors
|
|
|
|
func popupErrorAsNSURLError(_ error: Error) -> Bool {
|
|
let nsError = error as NSError
|
|
if nsError.domain == NSURLErrorDomain {
|
|
self.showPopupDialog(title: NSLocalizedString("Network Error", comment: ""), message: NSLocalizedString("Please check your internet connection. If this persists, please contact team@lockdownprivacy.com.\n\nError Description\n", comment: "") + nsError.localizedDescription, acceptButton: NSLocalizedString("Okay", comment: ""))
|
|
return true
|
|
}
|
|
else {
|
|
return false
|
|
}
|
|
}
|
|
|
|
func popupErrorAsApiError(_ error: Error) -> Bool {
|
|
if let e = error as? ApiError {
|
|
self.showPopupDialog(title: NSLocalizedString("Error Code ", comment: "") + "\(e.code)", message: "\(e.message)" + NSLocalizedString("\n\n If this persists, please contact team@lockdownprivacy.com.", comment: ""), acceptButton: NSLocalizedString("Okay", comment: ""))
|
|
return true
|
|
}
|
|
else {
|
|
return false
|
|
}
|
|
}
|
|
|
|
func showWhyTrustPopup() {
|
|
let popup = PopupDialog(
|
|
title: NSLocalizedString("Why Trust Lockdown?", comment: ""),
|
|
message: NSLocalizedString("Lockdown is open source and fully transparent, which means anyone can see exactly what it's doing. Also, Lockdown Firewall has a simple, strict Privacy Policy, while Lockdown VPN is fully audited by security experts.", comment: ""),
|
|
image: UIImage(named: "whyTrustImage")!,
|
|
buttonAlignment: .vertical,
|
|
transitionStyle: .bounceDown,
|
|
preferredWidth: 300.0,
|
|
tapGestureDismissal: true,
|
|
panGestureDismissal: false,
|
|
hideStatusBar: true,
|
|
completion: nil)
|
|
|
|
let privacyPolicyButton = DefaultButton(title: NSLocalizedString("Privacy Policy", comment: ""), dismissOnTap: true) {
|
|
self.showPrivacyPolicyModal()
|
|
}
|
|
|
|
let auditReportsButton = DefaultButton(title: NSLocalizedString("Audit Reports", comment: ""), dismissOnTap: true) {
|
|
self.showAuditModal()
|
|
}
|
|
|
|
let pressButton = DefaultButton(title: NSLocalizedString("Press & Media", comment: ""), dismissOnTap: true) {
|
|
self.showWebsitePressModal()
|
|
}
|
|
|
|
let okayButton = CancelButton(title: NSLocalizedString("Done", comment: ""), dismissOnTap: true) { }
|
|
popup.addButtons([privacyPolicyButton, auditReportsButton, pressButton, okayButton])
|
|
|
|
self.present(popup, animated: true, completion: nil)
|
|
}
|
|
|
|
func showVPNDetails() {
|
|
self.showModalWebView(title: NSLocalizedString("Secure Tunnel VPN", comment: ""), urlString: "https://lockdownprivacy.com/secure-tunnel")
|
|
// let popup = PopupDialog(
|
|
// title: NSLocalizedString("About Lockdown VPN", comment: ""),
|
|
// message: NSLocalizedString("Lockdown VPN is powered by Confirmed VPN, the open source, no-logs, and fully audited VPN.", comment: ""),
|
|
// buttonAlignment: .vertical,
|
|
// transitionStyle: .bounceDown,
|
|
// preferredWidth: 300.0,
|
|
// tapGestureDismissal: true,
|
|
// panGestureDismissal: false,
|
|
// hideStatusBar: true,
|
|
// completion: nil)
|
|
//
|
|
// let whyUseVPNButton = DefaultButton(title: NSLocalizedString("Why Use VPN?", comment: ""), dismissOnTap: true) {
|
|
// self.showModalWebView(title: NSLocalizedString("Why Use VPN?", comment: ""), urlString: "https://confirmedvpn.com/why-vpn")
|
|
// }
|
|
//
|
|
// let auditReportsButton = DefaultButton(title: NSLocalizedString("Audit Reports", comment: ""), dismissOnTap: true) {
|
|
// self.showAuditModal()
|
|
// }
|
|
//
|
|
// let confirmedWebsiteButton = DefaultButton(title: NSLocalizedString("Confirmed Site", comment: ""), dismissOnTap: true) {
|
|
// self.showModalWebView(title: NSLocalizedString("Why Use VPN?", comment: ""), urlString: "https://confirmedvpn.com")
|
|
// }
|
|
|
|
// let okayButton = CancelButton(title: NSLocalizedString("Done", comment: ""), dismissOnTap: true) { }
|
|
// popup.addButtons([whyUseVPNButton, auditReportsButton, confirmedWebsiteButton, okayButton])
|
|
//
|
|
// self.present(popup, animated: true, completion: nil)
|
|
}
|
|
|
|
// MARK: - WebView
|
|
|
|
func showWhatsNewModal() {
|
|
let vc = WhatsNewViewController()
|
|
present(vc, animated: true)
|
|
}
|
|
|
|
func showPrivacyPolicyModal() {
|
|
self.showModalWebView(title: NSLocalizedString("Privacy Policy", comment: ""), urlString: "https://lockdownprivacy.com/privacy")
|
|
}
|
|
|
|
func showTermsModal() {
|
|
self.showModalWebView(title: NSLocalizedString("Terms", comment: ""), urlString: "https://lockdownprivacy.com/terms")
|
|
}
|
|
|
|
func showFAQsModal() {
|
|
self.showModalWebView(title: NSLocalizedString("FAQs", comment: ""), urlString: "https://lockdownprivacy.com/faq")
|
|
}
|
|
|
|
func showWebsiteModal() {
|
|
self.showModalWebView(title: NSLocalizedString("Website", comment: ""), urlString: "https://lockdownprivacy.com")
|
|
}
|
|
|
|
func showWebsitePressModal() {
|
|
self.showModalWebView(title: NSLocalizedString("Press & Media", comment: ""), urlString: "https://lockdownprivacy.com/#press")
|
|
}
|
|
|
|
func showAuditModal() {
|
|
self.showModalWebView(title: NSLocalizedString("Audit Reports", comment: ""), urlString: "https://openaudit.com/lockdownprivacy")
|
|
}
|
|
|
|
func showModalWebView(title: String, urlString: String) {
|
|
if let url = URL(string: urlString) {
|
|
let storyboardToUse = storyboard != nil ? storyboard! : UIStoryboard(name: "Main", bundle: nil)
|
|
if let webViewVC = storyboardToUse.instantiateViewController(withIdentifier: "webview") as? WebViewViewController {
|
|
webViewVC.titleLabelText = title
|
|
webViewVC.url = url
|
|
self.present(webViewVC, animated: true, completion: nil)
|
|
}
|
|
else {
|
|
DDLogError("Unable to instantiate webview VC")
|
|
}
|
|
}
|
|
else {
|
|
DDLogError("Invalid URL \(urlString)")
|
|
}
|
|
}
|
|
|
|
// MARK: - Block user interactions during transactions
|
|
|
|
func unblockUserInteraction() {
|
|
let view = self.view.viewWithTag(interactionBlockViewTag)
|
|
if view != nil {
|
|
view?.removeFromSuperview()
|
|
}
|
|
}
|
|
|
|
func blockUserInteraction() {
|
|
let view = UIView(frame: self.view.frame)
|
|
view.tag = interactionBlockViewTag
|
|
view.backgroundColor = UIColor.init(white: 1.0, alpha: 0.0)
|
|
self.view.addSubview(view)
|
|
}
|
|
|
|
// MARK: - Popup Helper
|
|
|
|
func showPopupDialog(title: String, message: String, acceptButton: String, completionHandler: @escaping () -> () = {}) {
|
|
let popup = PopupDialog(title: title.uppercased(), message: message, image: nil, transitionStyle: .bounceDown, hideStatusBar: false)
|
|
|
|
let acceptButton = DefaultButton(title: NSLocalizedString("OK", comment: ""), dismissOnTap: true) { completionHandler() }
|
|
popup.addButtons([acceptButton])
|
|
|
|
self.present(popup, animated: true, completion: nil)
|
|
}
|
|
|
|
enum PopupButton {
|
|
case custom(PopupDialogButton)
|
|
case defaultAccept(completion: () -> ())
|
|
|
|
static func custom(title: String, titleColor: UIColor? = nil, completion: @escaping () -> ()) -> PopupButton {
|
|
let button = DefaultButton(title: title, dismissOnTap: true, action: completion)
|
|
if let color = titleColor {
|
|
button.titleColor = color
|
|
}
|
|
return .custom(button)
|
|
}
|
|
|
|
static func destructive(title: String, completion: @escaping () -> ()) -> PopupButton {
|
|
return .custom(title: title, titleColor: UIColor.systemRed, completion: completion)
|
|
}
|
|
|
|
static func cancel(completion: @escaping () -> () = { }) -> PopupButton {
|
|
return .custom(CancelButton(title: NSLocalizedString("Cancel", comment: ""), dismissOnTap: true, action: completion))
|
|
}
|
|
|
|
static func preferredCancel(completion: @escaping () -> () = { }) -> PopupButton {
|
|
return .custom(title: NSLocalizedString("Cancel", comment: ""), titleColor: nil, completion: completion)
|
|
}
|
|
|
|
fileprivate func makeButton() -> PopupDialogButton {
|
|
switch self {
|
|
case .custom(let button):
|
|
return button
|
|
case .defaultAccept(completion: let completion):
|
|
let acceptButton = DefaultButton(title: NSLocalizedString("OK", comment: ""), dismissOnTap: true) { completion() }
|
|
return acceptButton
|
|
}
|
|
}
|
|
}
|
|
|
|
func showPopupDialog(title: String?, message: String?, buttons: [PopupButton]) {
|
|
let popup = PopupDialog(title: title?.uppercased(), message: message, image: nil, transitionStyle: .bounceDown, tapGestureDismissal: false, panGestureDismissal: false, hideStatusBar: false)
|
|
|
|
for action in buttons {
|
|
let button = action.makeButton()
|
|
popup.addButton(button)
|
|
}
|
|
|
|
self.present(popup, animated: true, completion: nil)
|
|
}
|
|
|
|
func showFixFirewallConnectionDialog(completion: @escaping () -> ()) {
|
|
VPNController.shared.isConfigurationExisting { (exists) in
|
|
if exists {
|
|
// if VPN configuration exists, the system will not show an alert,
|
|
// so we do need to warn users about it
|
|
completion()
|
|
} else {
|
|
// if there is no existing VPN configuration,
|
|
// we need to show a dialog explaining the
|
|
// upcoming popup
|
|
self.showPopupDialog(
|
|
title: "Tap \"Allow\" on the Next Popup",
|
|
message: "Due to a recent iOS or Lockdown update, the Firewall needs to be refreshed to run properly.\n\nIf asked, tap \"Allow\" on the next dialog to automatically complete this process.",
|
|
buttons: [
|
|
.cancel(),
|
|
.defaultAccept(completion: {
|
|
completion()
|
|
})
|
|
]
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
// func showPopupDialogSubmitError(title : String = "Sorry, An Error Occurred", message : String, error: Error?) {
|
|
// let popup = PopupDialog(title: title, message: message, image: nil, transitionStyle: .zoomIn, hideStatusBar: false)
|
|
// let acceptButton = DefaultButton(title: "Don't Submit", dismissOnTap: true) { }
|
|
// let submitButton = DefaultButton(title: "Submit", dismissOnTap: true) {
|
|
// self.emailTeam(messageBody: "Hey Lockdown Team, \nI encountered a bug while using Lockdown, and I'm reporting it here. \n (To the user: just tap Send at the top right to submit the bug report -- no need to do anything else and we'll get back to you ASAP.", messageErrorBody: error ? error! || "")
|
|
// }
|
|
// popup.addButtons([acceptButton, submitButton])
|
|
// self.present(popup, animated: true, completion: nil)
|
|
// }
|
|
|
|
@objc func emailTeam(messageBody: String = NSLocalizedString("Hi, my question or feedback for Lockdown is: ", comment: ""), messageErrorBody: String = "") {
|
|
DDLogInfo("")
|
|
DDLogInfo("UserId: \(keychain[kVPNCredentialsId] ?? "No User ID")")
|
|
DDLogInfo("UserReceipt: \(keychain[kVPNCredentialsKeyBase64] ?? "No User Receipt")")
|
|
|
|
if (Client.hasValidCookie()) {
|
|
DDLogInfo("Has loaded cookie.")
|
|
}
|
|
DDLogInfo("")
|
|
PacketTunnelProviderLogs.flush()
|
|
DDLogInfo("")
|
|
|
|
var appendString = ""
|
|
if (getUserWantsVPNEnabled()) {
|
|
appendString = appendString + " - S"
|
|
}
|
|
let subject = "Lockdown Question or Feedback (iOS \(Bundle.main.versionString))" + appendString
|
|
|
|
var message = messageBody
|
|
if messageErrorBody != "" {
|
|
message = messageBody + "\n\nError Details: " + messageErrorBody
|
|
}
|
|
message += "\n\n\n"
|
|
|
|
sendMessage(message, subject: subject)
|
|
}
|
|
|
|
func sendMessage(_ message: String, subject: String) {
|
|
let recipient = "team@lockdownprivacy.com"
|
|
if MFMailComposeViewController.canSendMail() {
|
|
let composeVC = MFMailComposeViewController()
|
|
composeVC.mailComposeDelegate = self
|
|
composeVC.setToRecipients([recipient])
|
|
composeVC.setSubject(subject)
|
|
composeVC.setMessageBody(message, isHTML: false)
|
|
let attachmentData = NSMutableData()
|
|
for logFileData in logFileDataArray {
|
|
attachmentData.append(logFileData as Data)
|
|
}
|
|
composeVC.addAttachmentData(attachmentData as Data, mimeType: "text/plain", fileName: "diagnostics.txt")
|
|
self.present(composeVC, animated: true, completion: nil)
|
|
} else {
|
|
|
|
guard let mailtoURL = Mailto.generateURL(recipient: recipient, subject: subject, body: message) else {
|
|
DDLogError("Failed to generate mailto url")
|
|
return
|
|
}
|
|
|
|
UIApplication.shared.open(mailtoURL, options: [:]) { (success) in
|
|
if !success {
|
|
self.showPopupDialog(
|
|
title: NSLocalizedString("Couldn't Find Your Email Client", comment: ""),
|
|
message: NSLocalizedString("Please make sure you have added an e-mail account to your iOS device and try again.", comment: ""),
|
|
acceptButton: NSLocalizedString("OK", comment: "")
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// @objc func signoutUser() {
|
|
// // TODO: complete this debug functionality
|
|
// let title = "CLEAR RECEIPT DATA?"
|
|
// let message = "Would you like to clear your local receipts?"
|
|
//
|
|
// let popup = PopupDialog(title: title, message: message, image: nil, buttonAlignment: .horizontal)
|
|
//
|
|
// let acceptButton = DefaultButton(title: "YES", dismissOnTap: true) {
|
|
// // Auth.clearCookies()
|
|
// // Auth.signoutUser()
|
|
// }
|
|
// let cancelButton = DefaultButton(title: "CANCEL", dismissOnTap: true) { }
|
|
// popup.addButtons([cancelButton, acceptButton])
|
|
//
|
|
// self.present(popup, animated: true, completion: nil)
|
|
// }
|
|
|
|
// MARK: - Email Team
|
|
|
|
public func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
|
|
controller.dismiss(animated: true) { [weak self] in
|
|
self?.actionUponEmailComposeClosure()
|
|
}
|
|
}
|
|
|
|
func actionUponEmailComposeClosure() {}
|
|
|
|
}
|
|
|
|
extension UIStoryboard {
|
|
static let main = UIStoryboard(name: "Main", bundle: nil)
|
|
}
|