Tusker/Tusker/Screens/Crash Reporter/CrashReporterViewController...

134 lines
5.4 KiB
Swift

//
// CrashReporterViewController.swift
// Tusker
//
// Created by Shadowfacts on 6/20/20.
// Copyright © 2020 Shadowfacts. All rights reserved.
//
import UIKit
import CrashReporter
import MessageUI
class CrashReporterViewController: UIViewController {
private let report: PLCrashReport
private var reportText: String!
private var reportFilename: String {
let timestamp = ISO8601DateFormatter().string(from: report.systemInfo.timestamp)
return "Tusker-crash-\(timestamp).crash"
}
@IBOutlet weak var crashReportTextView: UITextView!
@IBOutlet weak var sendReportButton: UIButton!
static func create(report: PLCrashReport) -> UINavigationController {
let nav = UINavigationController(rootViewController: CrashReporterViewController(report: report))
nav.navigationBar.prefersLargeTitles = true
return nav
}
private init(report: PLCrashReport){
self.report = report
super.init(nibName: "CrashReporterViewController", bundle: .main)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = NSLocalizedString("Crash Detected", comment: "crash reporter title")
navigationItem.largeTitleDisplayMode = .always
crashReportTextView.font = .monospacedSystemFont(ofSize: 14, weight: .regular)
reportText = PLCrashReportTextFormatter.stringValue(for: report, with: PLCrashReportTextFormatiOS)!
let info = "Tusker has detected that it crashed the last time it was running. You can email the report to the developer or skip sending and continue to the app. You may review the report below before sending.\n\nIf you choose to send the report, please include any additional details about what you were doing prior to the crash that may be pertinent.\n\n"
let attributed = NSMutableAttributedString()
attributed.append(NSAttributedString(string: info, attributes: [
NSAttributedString.Key.font: UIFont.systemFont(ofSize: 17),
NSAttributedString.Key.foregroundColor: UIColor.label
]))
attributed.append(NSAttributedString(string: reportText, attributes: [
NSAttributedString.Key.font: UIFont.monospacedSystemFont(ofSize: 14, weight: .regular),
NSAttributedString.Key.foregroundColor: UIColor.label
]))
crashReportTextView.attributedText = attributed
sendReportButton.layer.cornerRadius = 12.5
sendReportButton.layer.masksToBounds = true
sendReportButton.addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(sendReportButtonLongPressed)))
}
private func updateSendReportButtonColor(lightened: Bool, animate: Bool) {
let color: UIColor
if lightened {
var hue: CGFloat = 0, saturation: CGFloat = 0, brightness: CGFloat = 0, alpha: CGFloat = 0
UIColor.systemBlue.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha)
color = UIColor(hue: hue, saturation: 0.85 * saturation, brightness: brightness, alpha: alpha)
} else {
color = .systemBlue
}
if animate {
UIView.animate(withDuration: 0.25) {
self.sendReportButton.backgroundColor = color
}
} else {
sendReportButton.backgroundColor = color
}
}
@IBAction func sendReportTouchDown(_ sender: Any) {
updateSendReportButtonColor(lightened: true, animate: false)
}
@IBAction func sendReportButtonTouchDragExit(_ sender: Any) {
updateSendReportButtonColor(lightened: false, animate: true)
}
@IBAction func sendReportButtonTouchDragEnter(_ sender: Any) {
updateSendReportButtonColor(lightened: true, animate: true)
}
@IBAction func sendReportTouchUpInside(_ sender: Any) {
updateSendReportButtonColor(lightened: false, animate: true)
let composeVC = MFMailComposeViewController()
composeVC.mailComposeDelegate = self
composeVC.setToRecipients(["me@shadowfacts.net"])
composeVC.setSubject("Tusker Crash Report")
let data = reportText.data(using: .utf8)!
composeVC.addAttachmentData(data, mimeType: "text/plain", fileName: reportFilename)
self.present(composeVC, animated: true)
}
@objc func sendReportButtonLongPressed() {
let dir = FileManager.default.temporaryDirectory
let url = dir.appendingPathComponent(reportFilename)
try! reportText.data(using: .utf8)!.write(to: url)
let activityController = UIActivityViewController(activityItems: [url], applicationActivities: nil)
present(activityController, animated: true)
}
@IBAction func cancelPressed(_ sender: Any) {
(view.window!.windowScene!.delegate as! SceneDelegate).showAppOrOnboardingUI()
}
}
extension CrashReporterViewController: MFMailComposeViewControllerDelegate {
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
controller.dismiss(animated: true) {
(self.view.window!.windowScene!.delegate as! SceneDelegate).showAppOrOnboardingUI()
}
}
}