Files
Adobe-Downloader/Adobe Downloader/Views/LogEntryView.swift
X1a0He 8a73709fb1 perf: Rendering performance optimizations
- UI rendering
- App load rendering
- Scroll rendering
2025-03-29 17:41:20 +08:00

128 lines
3.5 KiB
Swift

//
// LogEntryView.swift
// Adobe Downloader
//
// Created by X1a0He on 3/28/25.
//
import SwiftUI
struct LogEntryView: View {
let log: CleanupLog
@State private var showCopyButton = false
private var statusIconName: String {
statusIcon(for: log.status)
}
private var statusColorValue: Color {
statusColor(for: log.status)
}
private var timeFormatted: String {
timeString(from: log.timestamp)
}
private var displayText: String {
#if DEBUG
return log.command
#else
return CleanupLog.getCleanupDescription(for: log.command)
#endif
}
private var errorDisplayText: String? {
if log.status == .error && !log.message.isEmpty {
return truncatedErrorMessage(log.message)
}
return nil
}
var body: some View {
HStack {
Image(systemName: statusIconName)
.foregroundColor(statusColorValue)
Text(timeFormatted)
.font(.system(size: 11))
.foregroundColor(.secondary)
Text(displayText)
.font(.system(size: 11, design: .monospaced))
.lineLimit(1)
.truncationMode(.middle)
Spacer()
if let errorText = errorDisplayText {
HStack(spacing: 4) {
Text(errorText)
.font(.system(size: 11))
.foregroundColor(.secondary)
Button(action: {
copyToClipboard(log.message)
}) {
Image(systemName: "doc.on.doc")
.font(.system(size: 11))
}
.buttonStyle(.plain)
.help("复制完整错误信息")
}
} else {
Text(log.message)
.font(.system(size: 11))
.foregroundColor(.secondary)
}
}
.padding(.vertical, 4)
.padding(.horizontal, 8)
}
private func truncatedErrorMessage(_ message: String) -> String {
if message.hasPrefix("执行失败:") {
let errorMessage = String(message.dropFirst(5))
if errorMessage.count > 30 {
return "执行失败:" + errorMessage.prefix(30) + "..."
}
}
return message
}
private func copyToClipboard(_ message: String) {
NSPasteboard.general.clearContents()
NSPasteboard.general.setString(message, forType: .string)
}
private func statusIcon(for status: CleanupLog.LogStatus) -> String {
switch status {
case .running:
return "arrow.triangle.2.circlepath"
case .success:
return "checkmark.circle.fill"
case .error:
return "exclamationmark.circle.fill"
case .cancelled:
return "xmark.circle.fill"
}
}
private func statusColor(for status: CleanupLog.LogStatus) -> Color {
switch status {
case .running:
return .blue
case .success:
return .green
case .error:
return .red
case .cancelled:
return .orange
}
}
private func timeString(from date: Date) -> String {
let formatter = DateFormatter()
formatter.dateFormat = "HH:mm:ss"
return formatter.string(from: date)
}
}