Ferrite-backup/Ferrite/ViewModels/LoggingManager.swift
kingbri 7202a95bb2 Ferrite: Parallel tasks and logging
Make all tasks run in parallel to increase responsiveness and efficiency
when fetching new data.

However, parallel tasks means that toast errors are no longer feasible.
Instead, add a logging system which has a more detailed view of
app messages and direct the user there if there is an error.

Signed-off-by: kingbri <bdashore3@proton.me>
2023-03-09 18:48:28 -05:00

136 lines
3.2 KiB
Swift

//
// ToastViewModel.swift
// Ferrite
//
// Created by Brian Dashore on 7/19/22.
//
import SwiftUI
@MainActor
class LoggingManager: ObservableObject {
struct Log: Hashable {
let level: LogLevel
let message: String
let timeStamp: Date = .init()
func toMessage() -> String {
"[\(level.rawValue)]: \(message)"
}
}
enum LogLevel: String, Identifiable {
var id: Int {
hashValue
}
case info = "INFO"
case warn = "WARN"
case error = "ERROR"
}
@Published var messageArray: [Log] = []
// Toast variables
@Published var toastDescription: String? = nil {
didSet {
Task {
try? await Task.sleep(seconds: 0.1)
showToast = true
try? await Task.sleep(seconds: 3)
showToast = false
toastType = .error
}
}
}
@Published var showToast: Bool = false
// Default the toast type to error since the majority of toasts are errors
@Published var toastType: Logger.LogLevel = .error
var showErrorToasts: Bool {
UserDefaults.standard.bool(forKey: "Debug.ShowErrorToasts")
}
@Published var indeterminateToastDescription: String? = nil
@Published var indeterminateCancelAction: (() -> Void)? = nil
@Published var showIndeterminateToast: Bool = false
// MARK: - Logging functions
public func info(_ message: String,
description: String? = nil)
{
let log = Log(
level: .info,
message: message
)
if let description {
toastType = .info
toastDescription = description
}
messageArray.append(log)
print("LOG: \(log.toMessage())")
}
public func warn(_ message: String,
description: String? = nil)
{
let log = Log(
level: .warn,
message: message
)
if let description {
toastType = .warn
toastDescription = description
}
messageArray.append(log)
print("LOG: \(log.toMessage())")
}
public func error(_ message: String,
description: String? = nil,
showToast: Bool = true)
{
let log = Log(
level: .error,
message: message
)
// If a task is run in parallel, don't show a toast on error
if showToast && showErrorToasts {
toastDescription = description.map { $0 } ?? "An error was logged"
}
messageArray.append(log)
print("LOG: \(log.toMessage())")
}
// MARK: - Indeterminate functions
public func updateIndeterminateToast(_ description: String, cancelAction: (() -> Void)?) {
indeterminateToastDescription = description
if let cancelAction {
indeterminateCancelAction = cancelAction
}
if !showIndeterminateToast {
showIndeterminateToast = true
}
}
public func hideIndeterminateToast() {
showIndeterminateToast = false
indeterminateToastDescription = ""
indeterminateCancelAction = nil
}
}