mirror of
https://github.com/confirmedcode/Lockdown-iOS.git
synced 2025-12-21 12:14:02 +01:00
321 lines
12 KiB
Swift
321 lines
12 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
|
|
isModalInPresentation = true
|
|
}
|
|
|
|
// 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 {
|
|
let message = """
|
|
Please check your internet connection. If this persists, please contact team@lockdownprivacy.com.
|
|
|
|
Error Description\n
|
|
"""
|
|
let title: String = .localized("Network Error")
|
|
self.showPopupDialog(title: title, message: .localized(message) + nsError.localizedDescription, acceptButton: .localizedOkay)
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
|
|
func popupErrorAsApiError(_ error: Error) -> Bool {
|
|
if let e = error as? ApiError {
|
|
let title = .localized("Error Code ") + "\(e.code)"
|
|
let message = "\(e.message)" + .localized("\n\n If this persists, please contact team@lockdownprivacy.com.")
|
|
self.showPopupDialog(title: title, message: message, acceptButton: .localizedOkay)
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
|
|
func showWhyTrustPopup() {
|
|
let message = """
|
|
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.
|
|
"""
|
|
let popup = PopupDialog(
|
|
title: .localized("Why Trust Lockdown?"),
|
|
message: .localized(message),
|
|
image: UIImage(named: "whyTrustImage")!,
|
|
buttonAlignment: .vertical,
|
|
transitionStyle: .bounceDown,
|
|
preferredWidth: 300.0,
|
|
tapGestureDismissal: true,
|
|
panGestureDismissal: false,
|
|
hideStatusBar: true,
|
|
completion: nil)
|
|
(popup.view as? PopupDialogContainerView)?.cornerRadius = 16
|
|
(popup.view as? PopupDialogContainerView)?.layer.cornerCurve = .continuous
|
|
|
|
let privacyPolicyButton = DefaultButton(title: .localized("Privacy Policy"), dismissOnTap: true) {
|
|
self.showPrivacyPolicyModal()
|
|
}
|
|
|
|
let auditReportsButton = DefaultButton(title: .localized("Audit Reports"), dismissOnTap: true) {
|
|
self.showAuditModal()
|
|
}
|
|
|
|
let pressButton = DefaultButton(title: .localized("Press & Media"), dismissOnTap: true) {
|
|
self.showWebsitePressModal()
|
|
}
|
|
|
|
let okayButton = CancelButton(title: .localized("Done"), dismissOnTap: true) { }
|
|
popup.addButtons([privacyPolicyButton, auditReportsButton, pressButton, okayButton])
|
|
|
|
self.present(popup, animated: true, completion: nil)
|
|
}
|
|
|
|
func showVPNDetails() {
|
|
self.showModalWebView(title: .localized("Secure Tunnel VPN"), 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 showPrivacyPolicyModal() {
|
|
self.showModalWebView(title: .localized("Privacy Policy"), urlString: "https://lockdownprivacy.com/privacy")
|
|
}
|
|
|
|
func showTermsModal() {
|
|
self.showModalWebView(title: .localized("Terms"), urlString: "https://lockdownprivacy.com/terms")
|
|
}
|
|
|
|
func showFAQsModal() {
|
|
self.showModalWebView(title: .localized("FAQs"), urlString: "https://lockdownprivacy.com/faq")
|
|
}
|
|
|
|
func showWebsiteModal() {
|
|
self.showModalWebView(title: .localized("Website"), urlString: "https://lockdownprivacy.com")
|
|
}
|
|
|
|
func showWebsitePressModal() {
|
|
self.showModalWebView(title: .localized("Press & Media"), urlString: "https://lockdownprivacy.com/#press")
|
|
}
|
|
|
|
func showAuditModal() {
|
|
self.showModalWebView(title: .localized("Audit Reports"), urlString: "https://openaudit.com/lockdownprivacy")
|
|
}
|
|
|
|
func showModalWebView(title: String, urlString: String, delegate: WebViewViewControllerDelegate? = nil) {
|
|
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
|
|
webViewVC.delegate = delegate
|
|
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,
|
|
transitionStyle: PopupDialogTransitionStyle = .bounceDown,
|
|
acceptButton: String,
|
|
tapGestureDismissal: Bool = true,
|
|
panGestureDismissal: Bool = true,
|
|
completionHandler: @escaping () -> Void = {}) {
|
|
let popup = PopupDialog(
|
|
title: title.uppercased(),
|
|
message: message, image: nil,
|
|
transitionStyle: transitionStyle,
|
|
tapGestureDismissal: tapGestureDismissal,
|
|
panGestureDismissal: panGestureDismissal,
|
|
hideStatusBar: false)
|
|
(popup.view as? PopupDialogContainerView)?.cornerRadius = 16
|
|
(popup.view as? PopupDialogContainerView)?.layer.cornerCurve = .continuous
|
|
|
|
let acceptButton = DefaultButton(title: .localizedOK, dismissOnTap: true) { completionHandler() }
|
|
popup.addButtons([acceptButton])
|
|
|
|
self.present(popup, animated: true, completion: nil)
|
|
}
|
|
|
|
enum PopupButton {
|
|
case custom(PopupDialogButton)
|
|
case defaultAccept(completion: () -> Void)
|
|
|
|
static func custom(title: String, titleColor: UIColor? = nil, completion: @escaping () -> Void) -> PopupButton {
|
|
let button = DefaultButton(title: title, dismissOnTap: true, action: completion)
|
|
button.titleLabel?.adjustsFontSizeToFitWidth = true
|
|
button.titleLabel?.lineBreakMode = .byClipping
|
|
button.contentEdgeInsets = .init(top: 0, left: 16, bottom: 0, right: 16)
|
|
|
|
if let color = titleColor {
|
|
button.titleColor = color
|
|
}
|
|
return .custom(button)
|
|
}
|
|
|
|
static func destructive(title: String, completion: @escaping () -> Void) -> PopupButton {
|
|
return .custom(title: title, titleColor: UIColor.systemRed, completion: completion)
|
|
}
|
|
|
|
static func cancel(completion: @escaping () -> Void = { }) -> PopupButton {
|
|
return .custom(CancelButton(title: .localizedCancel, dismissOnTap: true, action: completion))
|
|
}
|
|
|
|
static func preferredCancel(completion: @escaping () -> Void = { }) -> PopupButton {
|
|
return .custom(title: .localizedCancel, 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: .localizedOK, dismissOnTap: true) { completion() }
|
|
return acceptButton
|
|
}
|
|
}
|
|
}
|
|
|
|
func showPopupDialog(
|
|
title: String?,
|
|
message: String?,
|
|
buttonAlignment: NSLayoutConstraint.Axis = .vertical,
|
|
hideStatusBar: Bool = false,
|
|
buttons: [PopupButton]) {
|
|
let popup = PopupDialog(
|
|
title: title?.uppercased(),
|
|
message: message,
|
|
image: nil,
|
|
buttonAlignment: buttonAlignment,
|
|
transitionStyle: .bounceDown,
|
|
tapGestureDismissal: false,
|
|
panGestureDismissal: false,
|
|
hideStatusBar: hideStatusBar)
|
|
|
|
(popup.view as? PopupDialogContainerView)?.cornerRadius = 16
|
|
(popup.view as? PopupDialogContainerView)?.layer.cornerCurve = .continuous
|
|
|
|
for action in buttons {
|
|
let button = action.makeButton()
|
|
popup.addButton(button)
|
|
}
|
|
|
|
self.present(popup, animated: true, completion: nil)
|
|
}
|
|
|
|
func showFixFirewallConnectionDialog(completion: @escaping () -> Void) {
|
|
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
|
|
let 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.
|
|
"""
|
|
self.showPopupDialog(
|
|
title: "Tap \"Allow\" on the Next Popup",
|
|
message: message,
|
|
buttons: [
|
|
.cancel(),
|
|
.defaultAccept(completion: {
|
|
completion()
|
|
})
|
|
]
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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)
|
|
}
|