← All repositories

listless

A simple list app for Apple platforms

git clone https://code.inqk.net/listless.git


ListlessiOS/Views/SyncDiagnosticsView.swift (3684B)

1import SwiftUI
2
3struct SyncDiagnosticsView: View {
4    @ObservedObject var syncMonitor: CloudKitSyncMonitor
5
6    private static let timestampFormatter: DateFormatter = {
7        let formatter = DateFormatter()
8        formatter.dateStyle = .none
9        formatter.timeStyle = .medium
10        return formatter
11    }()
12
13    var body: some View {
14        List {
15            Section("Status") {
16                row("Transient Banner", syncMonitor.transientErrorMessage ?? "None")
17                row("Last Error Domain", syncMonitor.lastCloudKitErrorDomain ?? "None")
18                row(
19                    "Last Error Code",
20                    syncMonitor.lastCloudKitErrorCode.map(String.init) ?? "None"
21                )
22                row("Last Error Description", syncMonitor.lastCloudKitErrorDescription ?? "None")
23                row(
24                    "Last Success",
25                    syncMonitor.lastSuccessfulSyncDate.map(Self.timestampFormatter.string(from:))
26                        ?? "None"
27                )
28            }
29
30            Section("Recent Events") {
31                if syncMonitor.recentDiagnostics.isEmpty {
32                    Text("No events captured yet.")
33                        .foregroundStyle(.secondary)
34                } else {
35                    ForEach(syncMonitor.recentDiagnostics.reversed()) { entry in
36                        VStack(alignment: .leading, spacing: 4) {
37                            Text(
38                                "\(Self.timestampFormatter.string(from: entry.timestamp)) [\(entry.level.uppercased())]"
39                            )
40                            .font(.caption.monospaced())
41                            .foregroundStyle(.secondary)
42
43                            Text(entry.message)
44                                .font(.caption.monospaced())
45                                .textSelection(.enabled)
46                        }
47                        .padding(.vertical, 2)
48                    }
49                }
50            }
51        }
52        .navigationTitle("iCloud Diagnostics")
53        .navigationBarTitleDisplayMode(.inline)
54        .toolbar {
55            ToolbarItem(placement: .topBarTrailing) {
56                Button("Copy") {
57                    UIPasteboard.general.string = diagnosticDump
58                }
59            }
60        }
61    }
62
63    @ViewBuilder
64    private func row(_ title: String, _ value: String) -> some View {
65        VStack(alignment: .leading, spacing: 4) {
66            Text(title)
67                .font(.caption)
68                .foregroundStyle(.secondary)
69            Text(value)
70                .font(.body.monospaced())
71                .textSelection(.enabled)
72        }
73        .padding(.vertical, 2)
74    }
75
76    private var diagnosticDump: String {
77        var lines: [String] = []
78        lines.append("Transient Banner: \(syncMonitor.transientErrorMessage ?? "None")")
79        lines.append("Last Error Domain: \(syncMonitor.lastCloudKitErrorDomain ?? "None")")
80        lines.append("Last Error Code: \(syncMonitor.lastCloudKitErrorCode.map(String.init) ?? "None")")
81        lines.append("Last Error Description: \(syncMonitor.lastCloudKitErrorDescription ?? "None")")
82        lines.append(
83            "Last Success: \(syncMonitor.lastSuccessfulSyncDate.map(Self.timestampFormatter.string(from:)) ?? "None")"
84        )
85        lines.append("")
86        lines.append("Recent Events:")
87        for entry in syncMonitor.recentDiagnostics {
88            lines.append(
89                "\(Self.timestampFormatter.string(from: entry.timestamp)) [\(entry.level.uppercased())] \(entry.message)"
90            )
91        }
92        return lines.joined(separator: "\n")
93    }
94}