passepartout-apple/Passepartout/App/Views/DiagnosticsView+OpenVPN.swift

203 lines
6.0 KiB
Swift
Raw Normal View History

2022-04-12 13:09:14 +00:00
//
// DiagnosticsView+OpenVPN.swift
// Passepartout
//
// Created by Davide De Rosa on 3/11/22.
2023-03-17 15:56:19 +00:00
// Copyright (c) 2023 Davide De Rosa. All rights reserved.
2022-04-12 13:09:14 +00:00
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
2022-06-23 21:31:01 +00:00
import PassepartoutLibrary
import SwiftUI
2022-04-12 13:09:14 +00:00
import TunnelKitOpenVPN
extension DiagnosticsView {
struct OpenVPNView: View {
enum AlertType: Int, Identifiable {
case emailNotConfigured
2023-03-17 20:55:47 +00:00
2022-04-12 13:09:14 +00:00
var id: Int {
return rawValue
}
}
@ObservedObject private var providerManager: ProviderManager
2022-04-12 13:09:14 +00:00
@ObservedObject private var vpnManager: VPNManager
2023-03-17 20:55:47 +00:00
2022-06-23 21:31:01 +00:00
@ObservedObject private var currentVPNState: ObservableVPNState
2022-04-12 13:09:14 +00:00
@ObservedObject private var productManager: ProductManager
private let providerName: ProviderName?
2023-03-17 20:55:47 +00:00
2022-04-12 13:09:14 +00:00
@State private var isReportingIssue = false
@State private var isAlertPresented = false
2022-04-12 13:09:14 +00:00
@State private var alertType: AlertType?
2023-03-17 20:55:47 +00:00
2022-04-12 13:09:14 +00:00
private let vpnProtocol: VPNProtocolType = .openVPN
2023-03-17 20:55:47 +00:00
2022-04-12 13:09:14 +00:00
init(providerName: ProviderName?) {
providerManager = .shared
vpnManager = .shared
currentVPNState = .shared
productManager = .shared
self.providerName = providerName
}
var body: some View {
List {
serverConfigurationSection
debugLogSection
// eligibility: to report a connectivity issue
if isEligibleForFeedback {
issueReporterSection
}
}.sheet(isPresented: $isReportingIssue, content: reportIssueView)
.alert(
L10n.ReportIssue.Alert.title,
isPresented: $isAlertPresented,
presenting: alertType,
actions: alertActions,
message: alertMessage
)
}
}
}
// MARK: -
2022-04-12 13:09:14 +00:00
private extension DiagnosticsView.OpenVPNView {
func alertActions(_ alertType: AlertType) -> some View {
Button(role: .cancel) {
} label: {
Text(L10n.Global.Strings.ok)
2022-04-12 13:09:14 +00:00
}
}
2022-04-12 13:09:14 +00:00
func alertMessage(_ alertType: AlertType) -> some View {
switch alertType {
case .emailNotConfigured:
return Text(L10n.Global.Messages.emailNotConfigured)
2022-04-12 13:09:14 +00:00
}
}
2023-03-17 20:55:47 +00:00
var serverConfigurationSection: some View {
Section {
let cfg = currentServerConfiguration
NavigationLink(L10n.Diagnostics.Items.ServerConfiguration.caption) {
cfg.map {
EndpointAdvancedView.OpenVPNView(
builder: .constant($0),
isReadonly: true,
isServerPushed: true
).navigationTitle(L10n.Diagnostics.Items.ServerConfiguration.caption)
}
}.disabled(cfg == nil)
2022-04-12 13:09:14 +00:00
}
}
2023-03-17 20:55:47 +00:00
var debugLogSection: some View {
Section {
DiagnosticsView.DebugLogGroup(appLogURL: appLogURL, tunnelLogURL: tunnelLogURL)
Toggle(L10n.Diagnostics.Items.MasksPrivateData.caption, isOn: $vpnManager.masksPrivateData)
} header: {
Text(L10n.DebugLog.title)
} footer: {
Text(L10n.Diagnostics.Sections.DebugLog.footer)
2022-04-12 13:09:14 +00:00
}
}
2022-04-12 13:09:14 +00:00
var issueReporterSection: some View {
Section {
Button(L10n.Diagnostics.Items.ReportIssue.caption, action: presentReportIssue)
}
}
2022-04-12 13:09:14 +00:00
func reportIssueView() -> some View {
let logURL = vpnManager.debugLogURL(forProtocol: vpnProtocol)
var metadata: ProviderMetadata?
var lastUpdate: Date?
if let name = providerName {
metadata = providerManager.provider(withName: name)
lastUpdate = providerManager.lastUpdate(name, vpnProtocol: vpnProtocol)
2022-04-12 13:09:14 +00:00
}
return ReportIssueView(
isPresented: $isReportingIssue,
vpnProtocol: vpnProtocol,
logURL: logURL,
providerMetadata: metadata,
lastUpdate: lastUpdate
)
2022-04-12 13:09:14 +00:00
}
var currentServerConfiguration: OpenVPN.ConfigurationBuilder? {
2022-04-12 13:09:14 +00:00
guard currentVPNState.vpnStatus == .connected else {
return nil
}
guard let cfg = vpnManager.serverConfiguration(forProtocol: vpnProtocol) as? OpenVPN.Configuration else {
return nil
}
// "withFallbacks: false" for view to hide nil options
return cfg.builder(withFallbacks: false)
}
var appLogURL: URL? {
2023-05-24 16:19:47 +00:00
Passepartout.shared.logger.logFile
}
var tunnelLogURL: URL? {
2022-09-04 18:09:31 +00:00
vpnManager.debugLogURL(forProtocol: vpnProtocol)
2022-04-12 13:09:14 +00:00
}
var isEligibleForFeedback: Bool {
productManager.isEligibleForFeedback()
}
2022-04-12 13:09:14 +00:00
}
// MARK: -
private extension DiagnosticsView.OpenVPNView {
func presentReportIssue() {
2022-04-12 13:09:14 +00:00
guard MailComposerView.canSendMail() else {
openReportIssueMailTo()
return
}
isReportingIssue = true
}
func openReportIssueMailTo() {
2022-04-12 13:09:14 +00:00
let V = Unlocalized.Issues.self
let body = V.body(V.template, DebugLog(content: "--").decoratedString())
guard let url = URL.mailto(to: V.recipient, subject: V.subject, body: body) else {
return
}
guard URL.open(url) else {
2022-04-12 13:09:14 +00:00
alertType = .emailNotConfigured
isAlertPresented = true
2022-04-12 13:09:14 +00:00
return
}
}
}