#104 trace file : no need to enable it in the settings, it is enabled by default. There's a maximum of 15 MB stored, which corresponds to around 6 days (depends on how much logs the specific installation is generating). The files are not deleted anymore but can be sent at any time.

This commit is contained in:
Johan Degraeve 2020-05-21 16:56:49 +02:00
parent b7061730cd
commit 91e17302a9
10 changed files with 248 additions and 238 deletions

View File

@ -118,6 +118,7 @@
F869188C23A044340065B607 /* TextsM5StackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F869188B23A044340065B607 /* TextsM5StackView.swift */; };
F878FA7D2405B3CF00BC6DA6 /* BluetoothPeripheralManager+CGMBubbleTransmitterDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F878FA7C2405B3CF00BC6DA6 /* BluetoothPeripheralManager+CGMBubbleTransmitterDelegate.swift */; };
F889CB6F236D84AC00A81068 /* M5StackView.strings in Resources */ = {isa = PBXBuildFile; fileRef = F889CB71236D84AC00A81068 /* M5StackView.strings */; };
F890E07A247687AE008FB2EC /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = F890E079247687AE008FB2EC /* URL.swift */; };
F897AAF92200F2D200CDDD10 /* CBPeripheralState.swift in Sources */ = {isa = PBXBuildFile; fileRef = F897AAF82200F2D200CDDD10 /* CBPeripheralState.swift */; };
F897AAFB2201018800CDDD10 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = F897AAFA2201018800CDDD10 /* String.swift */; };
F897E24B23FC86CF0075E0E8 /* CGMG5TransmitterDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F897E24A23FC86CF0075E0E8 /* CGMG5TransmitterDelegate.swift */; };
@ -454,6 +455,7 @@
F889CB8E236D89C800A81068 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Main.strings; sourceTree = "<group>"; };
F889CB97236D89C800A81068 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
F889CB9D236D8EEC00A81068 /* xdrip v4.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "xdrip v4.xcdatamodel"; sourceTree = "<group>"; };
F890E079247687AE008FB2EC /* URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URL.swift; sourceTree = "<group>"; };
F897AAF82200F2D200CDDD10 /* CBPeripheralState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CBPeripheralState.swift; sourceTree = "<group>"; };
F897AAFA2201018800CDDD10 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = "<group>"; };
F897E24A23FC86CF0075E0E8 /* CGMG5TransmitterDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGMG5TransmitterDelegate.swift; sourceTree = "<group>"; };
@ -799,6 +801,7 @@
F83098FD23AD3F84005741DF /* UITabBarController.swift */,
F8E51D602448E695001C9E5A /* Bundle.swift */,
F8AF361A245D93ED00B5977B /* Int16.swift */,
F890E079247687AE008FB2EC /* URL.swift */,
);
path = Extensions;
sourceTree = "<group>";
@ -2385,6 +2388,7 @@
F816E0ED2432A55F009EE65B /* BluconBluetoothPeripheralViewModel.swift in Sources */,
F8F9722923A5915900C3F17D /* CGMTransmitter.swift in Sources */,
F8A389ED23342EB10010F405 /* ConstantsNightScout.swift in Sources */,
F890E07A247687AE008FB2EC /* URL.swift in Sources */,
F8B3A856227F28DC004BA588 /* AlertTypeSettingsViewController.swift in Sources */,
F8A1584F22ECB281007F5B5D /* SettingsViewInfoViewModel.swift in Sources */,
F8B3A845227F090E004BA588 /* SettingsViewDexcomSettingsViewModel.swift in Sources */,

View File

@ -5,8 +5,15 @@ enum ConstantsTrace {
/// email address to which to send trace file
static let traceFileDestinationAddress = "xdrip@proximus.be"
/// will be used as filename to store traces on disk, and attachment file name when sending trace via e-mail
static let traceFileName = "xdriptrace.txt"
/// - will be used as filename to store traces on disk, and attachment file name when sending trace via e-mail
/// - filename will be extended with digit, eg xdriptrace.0.log, or xdriptrace.1.log - the actual trace file is always xdriptrace.0.log
static let traceFileName = "xdriptrace"
/// maximum size of one trace file, in MB. If size is larger, files will rotate, ie all trace files will be renamed, from xdriptrace.2.log to xdriptrace.3.log, from xdriptrace.1.log to xdriptrace.2.log, from xdriptrace.0.log to xdriptrace.1.log,
static let maximumFileSizeInMB: UInt64 = 5
/// maximum amount of trace files to hold. When rotating, and if value is 3, then tracefile xdriptrace.2.log will be deleted
static let maximumAmountOfTraceFiles = 3
/// will be used as filename to app info (configured transmitters etc ...)
static let appInfoFileName = "appinfo.txt"

View File

@ -0,0 +1,27 @@
import Foundation
// source : https://stackoverflow.com/questions/28268145/get-file-size-in-swift
extension URL {
var attributes: [FileAttributeKey : Any]? {
do {
return try FileManager.default.attributesOfItem(atPath: path)
} catch let error as NSError {
print("FileAttribute error: \(error)")
}
return nil
}
var fileSize: UInt64 {
return attributes?[.size] as? UInt64 ?? UInt64(0)
}
var fileSizeString: String {
return ByteCountFormatter.string(fromByteCount: Int64(fileSize), countStyle: .file)
}
var creationDate: Date? {
return attributes?[.creationDate] as? Date
}
}

View File

@ -175,9 +175,6 @@ extension UserDefaults {
/// OSLogEnabled enabled or not
case OSLogEnabled = "OSLogEnabled"
/// write trace to file enabled or not
case writeTraceToFile = "writeTraceToFile"
/// to merge from 3.x to 4.x, can be deleted once 3.x is not used anymore
case cgmTransmitterDeviceAddress = "cgmTransmitterDeviceAddress"
@ -828,16 +825,6 @@ extension UserDefaults {
}
}
/// write trace to file enabled or not
var writeTraceToFile: Bool {
get {
return bool(forKey: Key.writeTraceToFile.rawValue)
}
set {
set(newValue, forKey: Key.writeTraceToFile.rawValue)
}
}
/// to merge from 3.x to 4.x, can be deleted once 3.x is not used anymore
var cgmTransmitterDeviceAddress: String? {
get {

View File

@ -71,7 +71,6 @@
"displayDeltaInCalendarEvent" = "Display Delta?";
"infoCalendarAccessDeniedByUser" = "You previously denied access to your Calendar.\n\nTo enable it go to your device settings, privacy, calendars and enable it.";
"infoCalendarAccessRestricted" = "You cannot give authorization to xDrip4iOS to access your calendar. This is possibly due to active restrictions such as parental controls being in place.";
"writeTraceToFile" = "Write Trace to File?";
"sectionTitleTrace" = "Trace";
"sendTraceFile" = "Send Trace File";
"describeProblem" = "Explain why you need to send the trace file with as much detail as possible. If you have already reported your problem in the Facebook support group 'xDrip4iOS', then mention your facebook name in the e-mail";

View File

@ -69,7 +69,6 @@
"displayDeltaInCalendarEvent" = "Mostrar Delta?";
"infoCalendarAccessDeniedByUser" = "Has denegado previamente permiso para acceder al calendario.\n\nPara habilitarlo de nuevo, ir a Configuración en tu iPhone, Privacidad, Calendarios y habilitarlo.";
"infoCalendarAccessRestricted" = "No se puede autorizar a que xDrip4iOS tenga acceso a tu calendario. Podría ser debido a que restricciones tipo Controles Parentales o similares lo están impidiendo.";
"writeTraceToFile" = "Crear Archivo de Rastreo?";
"sectionTitleTrace" = "Rastrear";
"sendTraceFile" = "Enviar Archivo de Rastreo";
"describeProblem" = "Explicar en detalle porqué es necesario enviar este archivo de rastreo. Si ya has reportando previamente este problema en el grupo de Facebook 'xDrip4iOS', confirmar tu Nombre en Facebook dentro del cuerpo del correo";

View File

@ -69,7 +69,6 @@
"displayDeltaInCalendarEvent" = "Mostrar Delta?";
"infoCalendarAccessDeniedByUser" = "Has denegado previamente permiso para acceder al calendario.\n\nPara habilitarlo de nuevo, ir a Configuración en tu iPhone, Privacidad, Calendarios y habilitarlo.";
"infoCalendarAccessRestricted" = "No se puede autorizar a que xDrip4iOS tenga acceso a tu calendario. Podría ser debido a que restricciones tipo Controles Parentales o similares lo están impidiendo.";
"writeTraceToFile" = "Crear Archivo de Rastreo?";
"sectionTitleTrace" = "Rastrear";
"sendTraceFile" = "Enviar Archivo de Rastreo";
"describeProblem" = "Explicar en detalle porqué es necesario enviar este archivo de rastreo. Si usted ya ha reportando previamente este problema en el grupo de Facebook 'xDrip4iOS', confirmar su Nombre en Facebook dentro del cuerpo del correo";

View File

@ -322,10 +322,6 @@ class Texts_SettingsView {
return NSLocalizedString("infoCalendarAccessRestricted", tableName: filename, bundle: Bundle.main, value: "You cannot give authorization to xDrip4iOS to access your calendar. This is possibly due to active restrictions such as parental controls being in place.", comment: "If user is not allowed to give any app access to the Calendar, due to restrictions. And then tries to activate creation of events in calendar, this message will be shown")
}()
static let writeTraceToFile: String = {
return NSLocalizedString("writeTraceToFile", tableName: filename, bundle: Bundle.main, value: "Write Trace to File?", comment: "Should write trace to file be enabled or not")
}()
static let sectionTitleTrace: String = {
return NSLocalizedString("sectionTitleTrace", tableName: filename, bundle: Bundle.main, value: "Trace", comment: "in Settings, section title for Trace")
}()
@ -334,10 +330,6 @@ class Texts_SettingsView {
return NSLocalizedString("sendTraceFile", tableName: filename, bundle: Bundle.main, value: "Send Trace File", comment: "in Settings, row title to send settings")
}()
static let warningWriteTraceToFile: String = {
return NSLocalizedString("warningWriteTraceToFile", tableName: filename, bundle: Bundle.main, value: "Write trace to file is not enabled. Enable this first, perform your tests and then send the trace file", comment: "in Settings, when user clicks send trace to file, but write trace to file is not enabled")
}()
static let describeProblem: String = {
return NSLocalizedString("describeProblem", tableName: filename, bundle: Bundle.main, value: "Explain why you need to send the trace file with as much detail as possible. If you have already reported your problem in the Facebook support group 'xDrip4iOS', then mention your facebook name in the e-mail", comment: "Text in pop up shown when user wants to send the trace file")
}()

View File

@ -26,15 +26,8 @@ fileprivate func getDocumentsDirectory() -> URL {
return paths[0]
}
/// trace file, in case tracing needs to be stored on file
var traceFileName:URL = {
getDocumentsDirectory().appendingPathComponent(ConstantsTrace.traceFileName)
}()
// appinfo filename
var appInfoFileName:URL = {
getDocumentsDirectory().appendingPathComponent(ConstantsTrace.appInfoFileName)
}()
/// trace file currently in use, in case tracing needs to be stored on file
fileprivate var traceFileName:URL?
/// function to be used for logging, takes same parameters as os_log but in a next phase also NSLog can be added, or writing to disk to send later via e-mail ..
/// - message : the text, same format as in os_log with %{private} and %{public} to either keep variables private or public , for NSLog, only 3 String formatters are suppored "@" for String, "d" for Int, "f" for double.
@ -45,6 +38,12 @@ var appInfoFileName:URL = {
/// Example
func trace(_ message: StaticString, log:OSLog, category: String, type: OSLogType, _ args: CVarArg...) {
// initialize traceFileName if needed
if traceFileName == nil {
traceFileName = getDocumentsDirectory().appendingPathComponent(ConstantsTrace.traceFileName + ".0.log")
}
guard let traceFileName = traceFileName else {return}
// if oslog is enabled in settings, then do os_log
if UserDefaults.standard.OSLogEnabled {
@ -79,124 +78,151 @@ func trace(_ message: StaticString, log:OSLog, category: String, type: OSLogType
}
// if nslog or write trace to file is enabled in settings, then calculate first string to log
if UserDefaults.standard.NSLogEnabled || UserDefaults.standard.writeTraceToFile {
// calculate string to log, replacing arguments
var argumentsCounter: Int = 0
var actualMessage = message.description
// try to find the publicMark as long as argumentsCounter is less than the number of arguments
while argumentsCounter < args.count {
var argumentsCounter: Int = 0
// mark to replace
let publicMark = "%{public}"
var actualMessage = message.description
// get array of indexes of location of publicMark
let indexesOfPublicMark = actualMessage.indexes(of: "%{public}")
// try to find the publicMark as long as argumentsCounter is less than the number of arguments
while argumentsCounter < args.count {
if indexesOfPublicMark.count > 0 {
// mark to replace
let publicMark = "%{public}"
// range starts from first character until just before the publicMark
let startOfMessageRange = actualMessage.startIndex..<indexesOfPublicMark[0]
// text as String, until just before the publicMark
let startOfMessage = String(actualMessage[startOfMessageRange])
// get array of indexes of location of publicMark
let indexesOfPublicMark = actualMessage.indexes(of: "%{public}")
// range starts from just after the publicMark till the end
var endOfMessageRange = actualMessage.index(indexesOfPublicMark[0], offsetBy: publicMark.count)..<actualMessage.endIndex
// text as String, from just after the publicMark till the end
var endOfMessage = String(actualMessage[endOfMessageRange])
if indexesOfPublicMark.count > 0 {
// range starts from first character until just before the publicMark
let startOfMessageRange = actualMessage.startIndex..<indexesOfPublicMark[0]
// text as String, until just before the publicMark
let startOfMessage = String(actualMessage[startOfMessageRange])
// range starts from just after the publicMark till the end
var endOfMessageRange = actualMessage.index(indexesOfPublicMark[0], offsetBy: publicMark.count)..<actualMessage.endIndex
// text as String, from just after the publicMark till the end
var endOfMessage = String(actualMessage[endOfMessageRange])
// no start looking for String Format Specifiers
// possible formatting see https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFStrings/formatSpecifiers.html#//apple_ref/doc/uid/TP40004265
// not doing them all
if endOfMessage.starts(with: "@") {
let indexOfAt = endOfMessage.indexes(of: "@")
endOfMessageRange = endOfMessage.index(after: indexOfAt[0])..<endOfMessage.endIndex
endOfMessage = String(endOfMessage[endOfMessageRange])
if let argValue = args[argumentsCounter] as? String {
endOfMessage = argValue + endOfMessage
}
} else if endOfMessage.starts(with: "d") || endOfMessage.starts(with: "D") {
let indexOfAt = endOfMessage.indexes(of: "d", options: [NSString.CompareOptions.caseInsensitive])
endOfMessageRange = endOfMessage.index(after: indexOfAt[0])..<endOfMessage.endIndex
endOfMessage = String(endOfMessage[endOfMessageRange])
if let argValue = args[argumentsCounter] as? Int {
endOfMessage = argValue.description + endOfMessage
}
} else if endOfMessage.starts(with: "f") || endOfMessage.starts(with: "F") {
let indexOfAt = endOfMessage.indexes(of: "f", options: [NSString.CompareOptions.caseInsensitive])
endOfMessageRange = endOfMessage.index(after: indexOfAt[0])..<endOfMessage.endIndex
endOfMessage = String(endOfMessage[endOfMessageRange])
if let argValue = args[argumentsCounter] as? Double {
endOfMessage = argValue.description + endOfMessage
}
// no start looking for String Format Specifiers
// possible formatting see https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFStrings/formatSpecifiers.html#//apple_ref/doc/uid/TP40004265
// not doing them all
if endOfMessage.starts(with: "@") {
let indexOfAt = endOfMessage.indexes(of: "@")
endOfMessageRange = endOfMessage.index(after: indexOfAt[0])..<endOfMessage.endIndex
endOfMessage = String(endOfMessage[endOfMessageRange])
if let argValue = args[argumentsCounter] as? String {
endOfMessage = argValue + endOfMessage
}
} else if endOfMessage.starts(with: "d") || endOfMessage.starts(with: "D") {
let indexOfAt = endOfMessage.indexes(of: "d", options: [NSString.CompareOptions.caseInsensitive])
endOfMessageRange = endOfMessage.index(after: indexOfAt[0])..<endOfMessage.endIndex
endOfMessage = String(endOfMessage[endOfMessageRange])
if let argValue = args[argumentsCounter] as? Int {
endOfMessage = argValue.description + endOfMessage
}
} else if endOfMessage.starts(with: "f") || endOfMessage.starts(with: "F") {
let indexOfAt = endOfMessage.indexes(of: "f", options: [NSString.CompareOptions.caseInsensitive])
endOfMessageRange = endOfMessage.index(after: indexOfAt[0])..<endOfMessage.endIndex
endOfMessage = String(endOfMessage[endOfMessageRange])
if let argValue = args[argumentsCounter] as? Double {
endOfMessage = argValue.description + endOfMessage
}
actualMessage = startOfMessage + endOfMessage
} else {
// there's no more occurrences of the publicMark, no need to continue
break
}
argumentsCounter += 1
actualMessage = startOfMessage + endOfMessage
} else {
// there's no more occurrences of the publicMark, no need to continue
break
}
argumentsCounter += 1
}
// create timeStamp to use in NSLog and tracefile
let timeStamp = dateFormatNSLog.string(from: Date())
// nslog if enabled
if UserDefaults.standard.NSLogEnabled {
NSLog("%@", ConstantsLog.tracePrefix + " " + timeStamp + " " + category + " " + actualMessage)
}
// write trace to file
do {
let textToWrite = timeStamp + " " + category + " " + actualMessage + "\n"
if let fileHandle = FileHandle(forWritingAtPath: traceFileName.path) {
// file already exists, go to end of file and append text
fileHandle.seekToEndOfFile()
fileHandle.write(textToWrite.data(using: .utf8)!)
} else {
// file doesn't exist yet
try textToWrite.write(to: traceFileName, atomically: true, encoding: String.Encoding.utf8)
}
// create timeStamp to use in NSLog and tracefile
let timeStamp = dateFormatNSLog.string(from: Date())
} catch {
NSLog("%@", ConstantsLog.tracePrefix + " " + dateFormatNSLog.string(from: Date()) + " write trace to file failed")
}
// check if tracefile has reached limit size and if yes rotate the files
if traceFileName.fileSize > ConstantsTrace.maximumFileSizeInMB * 1024 * 1024 {
// nslog if enabled
if UserDefaults.standard.NSLogEnabled {
NSLog("%@", ConstantsLog.tracePrefix + " " + timeStamp + " " + category + " " + actualMessage)
}
rotateTraceFiles()
// if trace to file enabled, then write trace to file
if UserDefaults.standard.writeTraceToFile {
do {
let textToWrite = timeStamp + " " + category + " " + actualMessage + "\n"
if let fileHandle = FileHandle(forWritingAtPath: traceFileName.path) {
// file already exists, go to end of file and append text
fileHandle.seekToEndOfFile()
fileHandle.write(textToWrite.data(using: .utf8)!)
} else {
// file doesn't exist yet
try textToWrite.write(to: traceFileName, atomically: true, encoding: String.Encoding.utf8)
}
} catch {
NSLog("%@", ConstantsLog.tracePrefix + " " + dateFormatNSLog.string(from: Date()) + " write trace to file failed")
}
}
}
}
/// deletes the tracefile from disk
func deleteTraceFile() {
fileprivate func rotateTraceFiles() {
// assign fileManager
let fileManager = FileManager.default
do {
let fileManager = FileManager.default
try fileManager.removeItem(at: traceFileName)
} catch {
//
// first check if last trace file exists
let lastFile = getDocumentsDirectory().appendingPathComponent(ConstantsTrace.traceFileName + "." + (ConstantsTrace.maximumAmountOfTraceFiles - 1).description + ".log")
if FileHandle(forWritingAtPath: lastFile.path) != nil {
do {
try fileManager.removeItem(at: lastFile)
} catch {
debuglogging("failed to delete file " + lastFile.absoluteString)
}
}
// now rename trace files if they exist,
for indexFrom0ToMax in 0...(ConstantsTrace.maximumAmountOfTraceFiles - 2) {
let index = (ConstantsTrace.maximumAmountOfTraceFiles - 2) - indexFrom0ToMax
let file = getDocumentsDirectory().appendingPathComponent(ConstantsTrace.traceFileName + "." + index.description + ".log")
let newFile = getDocumentsDirectory().appendingPathComponent(ConstantsTrace.traceFileName + "." + (index + 1).description + ".log")
if FileHandle(forWritingAtPath: file.path) != nil {
do {
try fileManager.moveItem(at: file, to: newFile)
} catch {
debuglogging("failed to rename file " + lastFile.absoluteString)
}
}
}
// now set tracefilename to nil, it will be reassigned to correct name, ie the one with index 0, at next usage
traceFileName = nil
}
class Trace {
@ -221,12 +247,29 @@ class Trace {
// MARK: - public static functions
/// creates file on disk with app info
static func createAppInfoFile() {
/// creates file on disk with app info, and returns the file as Data and the filename
static func getAppInfoFileAsData() -> (Data?, String) {
var traceInfo = ""
// Info from User Defaults
// app version and build
if let dictionary = Bundle.main.infoDictionary {
if let version = dictionary["CFBundleShortVersionString"] as? String {
traceInfo.appendStringAndNewLine("Version " + version)
} else {
traceInfo.appendStringAndNewLine("Version unknown")
}
if let buildnumber = dictionary["CFBundleShortVersionString"] as? String {
traceInfo.appendStringAndNewLine("Build number " + buildnumber)
} else {
traceInfo.appendStringAndNewLine("Build number")
}
}
// Info from UserDefaults
// timestamp app launch
// unwrap timeStampAppLaunch
@ -419,14 +462,38 @@ class Trace {
}
}
do {
return (traceInfo.data(using: .utf8), ConstantsTrace.appInfoFileName)
}
/// returns tuple, first type is an array of Data, each element is a tracefile converted to Data, second type is String, each element is the name of the tracefile
static func getTraceFilesInData() -> ([Data], [String]) {
var traceFilesInData = [Data]()
var traceFileNames = [String]()
for index in 0..<ConstantsTrace.maximumAmountOfTraceFiles {
try traceInfo.write(to: appInfoFileName, atomically: true, encoding: String.Encoding.utf8)
let filename = ConstantsTrace.traceFileName + "." + index.description + ".log"
let file = getDocumentsDirectory().appendingPathComponent(filename)
if FileHandle(forWritingAtPath: file.path) != nil {
do {
// create traceFile info as data
let fileData = try Data(contentsOf: file)
traceFilesInData.append(fileData)
traceFileNames.append(filename)
} catch {
debuglogging("failed to create data from " + filename)
}
} catch {
NSLog("%@", ConstantsLog.tracePrefix + " " + dateFormatNSLog.string(from: Date()) + " write appinfo to file failed")
}
}
return (traceFilesInData, traceFileNames)
}
}

View File

@ -4,11 +4,8 @@ import os
fileprivate enum Setting:Int, CaseIterable {
/// write trace to file enabled or not
case writeTraceToFile = 0
/// to send trace file
case sendTraceFile = 1
case sendTraceFile = 0
}
@ -17,9 +14,6 @@ class SettingsViewTraceSettingsViewModel: NSObject {
/// need to present MFMailComposeViewController
private var uIViewController: UIViewController?
/// to force a row reload
private var rowReloadClosure: ((Int) -> Void)?
/// for logging
private var log = OSLog(subsystem: ConstantsLog.subSystem, category: ConstantsLog.categoryTraceSettingsViewModel)
@ -35,9 +29,7 @@ class SettingsViewTraceSettingsViewModel: NSObject {
extension SettingsViewTraceSettingsViewModel: SettingsViewModelProtocol {
func storeRowReloadClosure(rowReloadClosure: @escaping ((Int) -> Void)) {
self.rowReloadClosure = rowReloadClosure
}
func storeRowReloadClosure(rowReloadClosure: @escaping ((Int) -> Void)) {}
func storeUIViewController(uIViewController: UIViewController) {
self.uIViewController = uIViewController
@ -57,9 +49,6 @@ extension SettingsViewTraceSettingsViewModel: SettingsViewModelProtocol {
switch setting {
case .writeTraceToFile:
return Texts_SettingsView.writeTraceToFile
case .sendTraceFile:
return Texts_SettingsView.sendTraceFile
@ -72,9 +61,6 @@ extension SettingsViewTraceSettingsViewModel: SettingsViewModelProtocol {
switch setting {
case .writeTraceToFile:
return .none
case .sendTraceFile:
return .disclosureIndicator
@ -87,9 +73,6 @@ extension SettingsViewTraceSettingsViewModel: SettingsViewModelProtocol {
switch setting {
case .writeTraceToFile:
return nil
case .sendTraceFile:
return nil
@ -103,31 +86,6 @@ extension SettingsViewTraceSettingsViewModel: SettingsViewModelProtocol {
switch setting {
case .writeTraceToFile:
return UISwitch(isOn: UserDefaults.standard.writeTraceToFile, action: {
(isOn:Bool) in
if isOn {
// set writeTraceToFile to true before logging in trace that it is enabled
UserDefaults.standard.writeTraceToFile = true
trace("Trace to file enabled", log: self.log, category: ConstantsLog.categoryTraceSettingsViewModel, type: .info)
} else {
trace("Trace to file disabled", log: self.log, category: ConstantsLog.categoryTraceSettingsViewModel, type: .info)
// set writeTraceToFile to false after logging in trace that it is enabled
UserDefaults.standard.writeTraceToFile = false
}
})
case .sendTraceFile:
return nil
@ -145,59 +103,40 @@ extension SettingsViewTraceSettingsViewModel: SettingsViewModelProtocol {
switch setting {
case .writeTraceToFile:
return .nothing
case .sendTraceFile:
if !UserDefaults.standard.writeTraceToFile {
return .showInfoText(title: Texts_Common.warning, message: Texts_SettingsView.warningWriteTraceToFile)
} else {
guard let uIViewController = uIViewController else {fatalError("in SettingsViewTraceSettingsViewModel, onRowSelect, uIViewController is nil")}
do {
guard let uIViewController = uIViewController else {fatalError("in SettingsViewTraceSettingsViewModel, onRowSelect, uIViewController is nil")}
// check if iOS device can send email, this depends of an email account is configured
if MFMailComposeViewController.canSendMail() {
// create traceFile info as data
let fileData = try Data(contentsOf: traceFileName)
// create app info as data
Trace.createAppInfoFile()
let appInfoData = try Data(contentsOf: appInfoFileName)
if MFMailComposeViewController.canSendMail() {
return .askConfirmation(title: Texts_HomeView.info, message: Texts_SettingsView.describeProblem, actionHandler: {
return .askConfirmation(title: Texts_HomeView.info, message: Texts_SettingsView.describeProblem, actionHandler: {
let mail = MFMailComposeViewController()
mail.mailComposeDelegate = self
mail.setToRecipients([ConstantsTrace.traceFileDestinationAddress])
mail.setMessageBody(Texts_SettingsView.emailbodyText, isHTML: true)
mail.addAttachmentData(fileData as Data, mimeType: "text/txt", fileName: ConstantsTrace.traceFileName)
mail.addAttachmentData(appInfoData as Data, mimeType: "text/txt", fileName: ConstantsTrace.appInfoFileName)
uIViewController.present(mail, animated: true)
}, cancelHandler: nil)
let mail = MFMailComposeViewController()
mail.mailComposeDelegate = self
mail.setToRecipients([ConstantsTrace.traceFileDestinationAddress])
mail.setMessageBody(Texts_SettingsView.emailbodyText, isHTML: true)
// add all trace files as attachment
let traceFilesInData = Trace.getTraceFilesInData()
for (index, traceFileInData) in traceFilesInData.0.enumerated() {
mail.addAttachmentData(traceFileInData as Data, mimeType: "text/txt", fileName: traceFilesInData.1[index])
}
} else {
return .showInfoText(title: Texts_Common.warning, message: Texts_SettingsView.emailNotConfigured)
if let appInfoAsData = Trace.getAppInfoFileAsData().0 {
mail.addAttachmentData(appInfoAsData as Data, mimeType: "text/txt", fileName: Trace.getAppInfoFileAsData().1)
}
}
} catch {
// should never get here ?
return .showInfoText(title: Texts_Common.warning, message: "Failed to create attachment")
uIViewController.present(mail, animated: true)
}, cancelHandler: nil)
} else {
return .showInfoText(title: Texts_Common.warning, message: Texts_SettingsView.emailNotConfigured)
}
}
}
}
@ -226,18 +165,8 @@ extension SettingsViewTraceSettingsViewModel: MFMailComposeViewControllerDelegat
break
case .sent, .saved:
// delete the file as it's been sent successfully
deleteTraceFile()
break
// disable tracing, to avoid user forgets turning it off
UserDefaults.standard.writeTraceToFile = false
// as setting writeTraceToFile has been changed to false, the row with that setting needs to be reloaded
if let rowReloadClosure = rowReloadClosure {
rowReloadClosure(Setting.writeTraceToFile.rawValue)
}
case .failed:
if let messageHandler = messageHandler {
messageHandler(Texts_Common.warning, Texts_SettingsView.failedToSendEmail)