Files
Kisani/Features/History/HistoryView.swift
Robin Kutesa b96711c535 Initial scaffold — NASBackup iOS app
Full project scaffold: XcodeGen project.yml, Core models/protocols/errors,
SMBService (kishikawakatsumi/SMBClient), SFTPService (Citadel 0.9.2),
PhotoLibraryService, LANMonitor, BackupEngine, BackgroundTaskManager,
all feature UIs (Login, Connect, Browse, Backup, History, Settings),
Shared components and theme. Builds clean with zero errors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 17:05:04 +03:00

98 lines
3.5 KiB
Swift

import SwiftUI
struct HistoryView: View {
@EnvironmentObject var store: ConnectionStore
var body: some View {
ZStack {
Color.white.ignoresSafeArea()
if store.historyEntries.isEmpty {
VStack(spacing: 16) {
Image(systemName: "clock.arrow.circlepath")
.font(.system(size: 48))
.foregroundColor(AppTheme.textTertiary)
Text("No backup history yet")
.font(AppTheme.bodyFont)
.foregroundColor(AppTheme.textSecondary)
}
} else {
List {
ForEach(store.historyEntries) { entry in
HistoryRowView(entry: entry)
.listRowSeparator(.visible)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
}
.onDelete { offsets in
store.removeHistoryEntries(at: offsets)
}
}
.listStyle(.plain)
}
}
.navigationTitle("History")
.toolbar {
if !store.historyEntries.isEmpty {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Clear") { store.clearHistory() }
.foregroundColor(AppTheme.red)
}
}
}
}
}
struct HistoryRowView: View {
let entry: BackupHistoryEntry
var body: some View {
HStack(spacing: 14) {
Circle()
.fill(entry.failedCount == 0 ? AppTheme.green : AppTheme.orange)
.frame(width: 10, height: 10)
VStack(alignment: .leading, spacing: 4) {
HStack {
Text(entry.date, style: .date)
.font(.system(size: 15, weight: .semibold))
.foregroundColor(AppTheme.textPrimary)
if entry.triggeredByLAN {
Text("AUTO")
.font(.system(size: 10, weight: .bold))
.foregroundColor(AppTheme.blue)
.padding(.horizontal, 5)
.padding(.vertical, 2)
.overlay(RoundedRectangle(cornerRadius: 4).stroke(AppTheme.blue, lineWidth: 1))
}
Spacer()
Text(entry.date, style: .time)
.font(AppTheme.captionFont)
.foregroundColor(AppTheme.textTertiary)
}
HStack(spacing: 12) {
statChip("\(entry.uploadedCount) uploaded", color: AppTheme.textSecondary)
if entry.skippedCount > 0 {
statChip("\(entry.skippedCount) skipped", color: AppTheme.textTertiary)
}
if entry.failedCount > 0 {
statChip("\(entry.failedCount) errors", color: AppTheme.red)
}
}
Text(entry.nasHost)
.font(AppTheme.captionFont)
.foregroundColor(AppTheme.textTertiary)
}
}
.padding(.horizontal, 16)
.padding(.vertical, 12)
}
private func statChip(_ text: String, color: Color) -> some View {
Text(text)
.font(AppTheme.captionFont)
.foregroundColor(color)
}
}