Fine-grain report attachments

- Debug log
- .ovpn profile (if any)
This commit is contained in:
Davide De Rosa 2018-10-23 10:25:41 +02:00
parent 821393af70
commit dfde9c51e3
6 changed files with 53 additions and 21 deletions

View File

@ -27,6 +27,22 @@ import Foundation
import MessageUI import MessageUI
class IssueReporter: NSObject { class IssueReporter: NSObject {
struct Attachments {
let debugLog: Bool
let configurationURL: URL?
init(debugLog: Bool, configurationURL: URL?) {
self.debugLog = debugLog
self.configurationURL = configurationURL
}
init(debugLog: Bool, profile: ConnectionProfile) {
let url = TransientStore.shared.service.configurationURL(for: profile)
self.init(debugLog: debugLog, configurationURL: url)
}
}
static let shared = IssueReporter() static let shared = IssueReporter()
private weak var viewController: UIViewController? private weak var viewController: UIViewController?
@ -35,7 +51,7 @@ class IssueReporter: NSObject {
super.init() super.init()
} }
func present(in viewController: UIViewController) { func present(in viewController: UIViewController, withAttachments attachments: Attachments) {
guard MFMailComposeViewController.canSendMail() else { guard MFMailComposeViewController.canSendMail() else {
let alert = Macros.alert(L10n.IssueReporter.title, L10n.IssueReporter.Alerts.EmailNotConfigured.message) let alert = Macros.alert(L10n.IssueReporter.title, L10n.IssueReporter.Alerts.EmailNotConfigured.message)
alert.addCancelAction(L10n.Global.ok) alert.addCancelAction(L10n.Global.ok)
@ -45,17 +61,21 @@ class IssueReporter: NSObject {
self.viewController = viewController self.viewController = viewController
let alert = Macros.alert(L10n.IssueReporter.title, L10n.IssueReporter.message) if attachments.debugLog {
alert.addDefaultAction(L10n.IssueReporter.Buttons.accept) { let alert = Macros.alert(L10n.IssueReporter.title, L10n.IssueReporter.message)
VPN.shared.requestDebugLog(fallback: AppConstants.Log.debugSnapshot) { alert.addDefaultAction(L10n.IssueReporter.Buttons.accept) {
self.composeEmail(withDebugLog: $0) VPN.shared.requestDebugLog(fallback: AppConstants.Log.debugSnapshot) {
self.composeEmail(withDebugLog: $0, configurationURL: attachments.configurationURL)
}
} }
alert.addCancelAction(L10n.Global.cancel)
viewController.present(alert, animated: true, completion: nil)
} else {
composeEmail(withDebugLog: nil, configurationURL: attachments.configurationURL)
} }
alert.addCancelAction(L10n.Global.cancel)
viewController.present(alert, animated: true, completion: nil)
} }
private func composeEmail(withDebugLog debugLog: String?) { private func composeEmail(withDebugLog debugLog: String?, configurationURL: URL?) {
let metadata = DebugLog(raw: "--").decoratedString() let metadata = DebugLog(raw: "--").decoratedString()
let vc = MFMailComposeViewController() let vc = MFMailComposeViewController()
@ -64,7 +84,10 @@ class IssueReporter: NSObject {
vc.setMessageBody(L10n.IssueReporter.Email.body(metadata), isHTML: false) vc.setMessageBody(L10n.IssueReporter.Email.body(metadata), isHTML: false)
if let raw = debugLog { if let raw = debugLog {
let attachment = DebugLog(raw: raw).decoratedData() let attachment = DebugLog(raw: raw).decoratedData()
vc.addAttachmentData(attachment, mimeType: AppConstants.IssueReporter.attachmentMIME, fileName: AppConstants.Log.debugFilename) vc.addAttachmentData(attachment, mimeType: AppConstants.IssueReporter.MIME.debugLog, fileName: AppConstants.IssueReporter.Filenames.debugLog)
}
if let cfg = configurationURL, let attachment = try? Data(contentsOf: cfg) {
vc.addAttachmentData(attachment, mimeType: AppConstants.IssueReporter.MIME.configuration, fileName: AppConstants.IssueReporter.Filenames.configuration)
} }
vc.mailComposeDelegate = self vc.mailComposeDelegate = self
vc.apply(Theme.current) vc.apply(Theme.current)

View File

@ -64,7 +64,7 @@ class DebugLogViewController: UIViewController {
} }
let data = DebugLog(raw: raw).decoratedData() let data = DebugLog(raw: raw).decoratedData()
let path = NSTemporaryDirectory().appending(AppConstants.Log.debugFilename) let path = NSTemporaryDirectory().appending(AppConstants.IssueReporter.Filenames.debugLog)
let url = URL(fileURLWithPath: path) let url = URL(fileURLWithPath: path)
do { do {
try data.write(to: url) try data.write(to: url)

View File

@ -361,7 +361,8 @@ class ServiceViewController: UIViewController, TableModelHost {
} }
private func reportConnectivityIssue() { private func reportConnectivityIssue() {
IssueReporter.shared.present(in: self) let attach = IssueReporter.Attachments(debugLog: true, profile: uncheckedProfile)
IssueReporter.shared.present(in: self, withAttachments: attach)
} }
// MARK: Notifications // MARK: Notifications

View File

@ -174,7 +174,7 @@
"issue_reporter.message" = "The debug log of your latest connections is crucial to resolve your connectivity issues and is completely anonymous."; "issue_reporter.message" = "The debug log of your latest connections is crucial to resolve your connectivity issues and is completely anonymous.";
"issue_reporter.buttons.accept" = "I understand"; "issue_reporter.buttons.accept" = "I understand";
"issue_reporter.alerts.email_not_configured.message" = "No e-mail account is configured."; "issue_reporter.alerts.email_not_configured.message" = "No e-mail account is configured.";
"issue_reporter.email.subject" = "%@ - Debug log"; "issue_reporter.email.subject" = "%@ - Report issue";
"issue_reporter.email.body" = "Hi,\n\ndescription of the issue:\n\n%@\n\nRegards"; "issue_reporter.email.body" = "Hi,\n\ndescription of the issue:\n\n%@\n\nRegards";
"about.title" = "About"; "about.title" = "About";

View File

@ -96,13 +96,6 @@ class AppConstants {
static var debugSnapshot: () -> String = { TransientStore.shared.service.vpnLog } static var debugSnapshot: () -> String = { TransientStore.shared.service.vpnLog }
static var debugFilename: String {
let fmt = DateFormatter()
fmt.dateFormat = "yyyyMMdd-HHmmss"
let iso = fmt.string(from: Date())
return "debug-\(iso).txt"
}
static let viewerRefreshInterval: TimeInterval = 3.0 static let viewerRefreshInterval: TimeInterval = 3.0
static func configure() { static func configure() {
@ -116,7 +109,22 @@ class AppConstants {
class IssueReporter { class IssueReporter {
static let recipient = "issues@\(Domain.name)" static let recipient = "issues@\(Domain.name)"
static let attachmentMIME = "text/plain" class Filenames {
static var debugLog: String {
let fmt = DateFormatter()
fmt.dateFormat = "yyyyMMdd-HHmmss"
let iso = fmt.string(from: Date())
return "debug-\(iso).txt"
}
static let configuration = "profile.ovpn"
}
class MIME {
static let debugLog = "text/plain"
static let configuration = "application/x-openvpn-profile"
}
} }
class URLs { class URLs {

View File

@ -324,7 +324,7 @@ internal enum L10n {
internal static func body(_ p1: String) -> String { internal static func body(_ p1: String) -> String {
return L10n.tr("Localizable", "issue_reporter.email.body", p1) return L10n.tr("Localizable", "issue_reporter.email.body", p1)
} }
/// %@ - Debug log /// %@ - Report issue
internal static func subject(_ p1: String) -> String { internal static func subject(_ p1: String) -> String {
return L10n.tr("Localizable", "issue_reporter.email.subject", p1) return L10n.tr("Localizable", "issue_reporter.email.subject", p1)
} }