Files
sing-box-for-apple/ApplicationLibrary/Views/Setting/ServiceLogViewModel.swift
T
2026-02-05 02:37:02 +08:00

78 lines
2.7 KiB
Swift

import Foundation
import Library
import SwiftUI
@MainActor
final class ServiceLogViewModel: BaseViewModel {
@Published var content = ""
override init() {
super.init()
isLoading = true
}
var isEmpty: Bool {
content.isEmpty
}
nonisolated func loadContent() async {
let primaryLogURL = FilePath.cacheDirectory.appendingPathComponent("stderr.log")
let secondaryLogURL = FilePath.cacheDirectory.appendingPathComponent("stderr.log.old")
var content = await BlockingIO.run {
if let primaryContent = try? String(contentsOf: primaryLogURL), !primaryContent.isEmpty {
return primaryContent
}
return (try? String(contentsOf: secondaryLogURL)) ?? ""
}
#if DEBUG
if content.isEmpty {
content = "Empty content"
}
#endif
if !content.isEmpty {
var systemInfo = utsname()
uname(&systemInfo)
let machineMirror = Mirror(reflecting: systemInfo.machine)
let machineName = machineMirror.children.reduce("") { identifier, element in
guard let value = element.value as? Int8, value != 0 else { return identifier }
return identifier + String(UnicodeScalar(UInt8(value)))
}
var deviceInfo = String("Machine: ") + machineName + "\n"
#if os(iOS)
await deviceInfo += String("System: ") + (UIDevice.current.systemName) + " " + (UIDevice.current.systemVersion) + "\n"
#elseif os(macOS)
deviceInfo += String("System: ") + "macOS " + ProcessInfo().operatingSystemVersionString + "\n"
#endif
content = deviceInfo + "\n" + content
}
await MainActor.run { [content] in
self.content = content
isLoading = false
}
}
nonisolated func deleteContent(dismiss: DismissAction) async {
let primaryLogURL = FilePath.cacheDirectory.appendingPathComponent("stderr.log")
let secondaryLogURL = FilePath.cacheDirectory.appendingPathComponent("stderr.log.old")
await BlockingIO.run {
try? FileManager.default.removeItem(at: primaryLogURL)
try? FileManager.default.removeItem(at: secondaryLogURL)
}
await MainActor.run {
dismiss()
isLoading = true
}
}
func generateShareFile() throws -> URL {
try content.generateShareFile(name: "service.log")
}
func generateShareFileAsync() async throws -> URL {
let content = content
return try await BlockingIO.run {
try content.generateShareFile(name: "service.log")
}
}
}