commit 15bb996563bf53846b97608b473ba0dc2286ca53
parent ea40cd889a49660810e5763e530259bfb54c15e0
Author: Michael Camilleri <[email protected]>
Date: Thu, 5 Mar 2026 10:37:00 +0900
Rename Sync Diagnostics to iCloud Diagnostics
Diffstat:
4 files changed, 99 insertions(+), 94 deletions(-)
diff --git a/Listless.xcodeproj/project.pbxproj b/Listless.xcodeproj/project.pbxproj
@@ -31,6 +31,7 @@
4DD2030E321567BD25661760 /* SyncDiagnosticsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9288507CE6023425D1DE724 /* SyncDiagnosticsView.swift */; };
4E5A0A02121E02124F80E320 /* TaskListView+SyncUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7BD42B1E3C71333FA24893 /* TaskListView+SyncUI.swift */; };
5035EC4C7518A5FF9AD454CA /* TaskRowDragGesture.swift in Sources */ = {isa = PBXBuildFile; fileRef = F416DD868A4C044F0D64F8D0 /* TaskRowDragGesture.swift */; };
+ 568635BB34CD7EBE24E66A15 /* SyncDiagnosticsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF3374CE58E7D9378C6997D2 /* SyncDiagnosticsView.swift */; };
5761B201BF46FCA9C5C98CEF /* PlatformScrollIndicatorsModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 466F9B0E407DF1F5B4789531 /* PlatformScrollIndicatorsModifier.swift */; };
5B60B409CE4BA668DB30A65D /* Listless.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = C093494053E6C348F245D4EC /* Listless.xcdatamodeld */; };
5D3EE9526DA269EE9EE3AB52 /* AppColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1E998119283F784B9ADEE28 /* AppColors.swift */; };
@@ -141,6 +142,7 @@
C71466C5CD1A5BA984352F8D /* Listless iOS Unit Tests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = "Listless iOS Unit Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
C9B14DC786A336008AAB78EE /* .gitkeep */ = {isa = PBXFileReference; path = .gitkeep; sourceTree = "<group>"; };
CB43816B8E7F083A2AD07F28 /* TaskListView+Toolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TaskListView+Toolbar.swift"; sourceTree = "<group>"; };
+ CF3374CE58E7D9378C6997D2 /* SyncDiagnosticsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncDiagnosticsView.swift; sourceTree = "<group>"; };
D2C018476BD91B73870244B9 /* TaskListViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskListViewProtocol.swift; sourceTree = "<group>"; };
D2D9CDDA8913CD116FB4DA74 /* TaskListView+PullGestures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TaskListView+PullGestures.swift"; sourceTree = "<group>"; };
D3E995954787F0A14CCFF348 /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = "<group>"; };
@@ -296,6 +298,7 @@
D12ECC901ABED96B86CC85B5 /* Views */ = {
isa = PBXGroup;
children = (
+ CF3374CE58E7D9378C6997D2 /* SyncDiagnosticsView.swift */,
632DA39B24C4CF1528A1A24D /* TaskListView.swift */,
E06485DBE35B60868E14202A /* TaskRowView.swift */,
);
@@ -511,6 +514,7 @@
A0AA8FD4C542E9AEB2437BC2 /* PersistenceController.swift in Sources */,
5761B201BF46FCA9C5C98CEF /* PlatformScrollIndicatorsModifier.swift in Sources */,
DEE187A790A4058FE4AFDB2E /* PlatformTextFieldWidthModifier.swift in Sources */,
+ 568635BB34CD7EBE24E66A15 /* SyncDiagnosticsView.swift in Sources */,
C1FE091454864C4BBBBEB077 /* TaskItem.swift in Sources */,
93275BD83342D6CE94272E6A /* TaskListTypes.swift in Sources */,
E5878BAA0EA66A94440E2B0F /* TaskListView+Logic.swift in Sources */,
diff --git a/ListlessMac/ListlessMacApp.swift b/ListlessMac/ListlessMacApp.swift
@@ -164,7 +164,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuItemValidation {
}
let defaultContentSize = NSSize(width: 760, height: 520)
- let rootView = SyncDiagnosticsWindowView(syncMonitor: persistenceController.syncMonitor)
+ let rootView = SyncDiagnosticsView(syncMonitor: persistenceController.syncMonitor)
let window = NSWindow(
contentRect: NSRect(origin: .zero, size: defaultContentSize),
styleMask: [.titled, .closable, .miniaturizable, .resizable],
@@ -172,7 +172,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuItemValidation {
defer: false
)
window.contentViewController = NSHostingController(rootView: rootView)
- window.title = "Sync Diagnostics"
+ window.title = "iCloud Diagnostics"
window.setContentSize(defaultContentSize)
window.minSize = NSSize(width: 480, height: 320)
window.isReleasedWhenClosed = false
@@ -304,7 +304,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuItemValidation {
windowMenu.addItem(withTitle: "Zoom", action: #selector(NSWindow.performZoom(_:)), keyEquivalent: "")
windowMenu.addItem(NSMenuItem.separator())
let syncDiagnosticsItem = NSMenuItem(
- title: "Sync Diagnostics",
+ title: "iCloud Diagnostics",
action: #selector(handleShowSyncDiagnostics),
keyEquivalent: ""
)
@@ -340,93 +340,3 @@ enum ListlessMacMain {
}
}
}
-
-private struct SyncDiagnosticsWindowView: View {
- @ObservedObject var syncMonitor: CloudKitSyncMonitor
-
- private static let timestampFormatter: DateFormatter = {
- let formatter = DateFormatter()
- formatter.dateStyle = .none
- formatter.timeStyle = .medium
- return formatter
- }()
-
- var body: some View {
- List {
- Section("Status") {
- row("Transient Banner", syncMonitor.transientErrorMessage ?? "None")
- row("Last Error Domain", syncMonitor.lastCloudKitErrorDomain ?? "None")
- row("Last Error Code", syncMonitor.lastCloudKitErrorCode.map(String.init) ?? "None")
- row("Last Error Description", syncMonitor.lastCloudKitErrorDescription ?? "None")
- row(
- "Last Success",
- syncMonitor.lastSuccessfulSyncDate.map(Self.timestampFormatter.string(from:)) ?? "None"
- )
- }
-
- Section("Recent Events") {
- if syncMonitor.recentDiagnostics.isEmpty {
- Text("No events captured yet.")
- .foregroundStyle(.secondary)
- } else {
- ForEach(syncMonitor.recentDiagnostics.reversed()) { entry in
- VStack(alignment: .leading, spacing: 4) {
- Text(
- "\(Self.timestampFormatter.string(from: entry.timestamp)) [\(entry.level.uppercased())]"
- )
- .font(.caption.monospaced())
- .foregroundStyle(.secondary)
-
- Text(entry.message)
- .font(.caption.monospaced())
- .textSelection(.enabled)
- }
- .padding(.vertical, 2)
- }
- }
- }
- }
- .textSelection(.enabled)
- .toolbar {
- ToolbarItem {
- Button("Copy") {
- let pasteboard = NSPasteboard.general
- pasteboard.clearContents()
- pasteboard.setString(diagnosticDump, forType: .string)
- }
- }
- }
- }
-
- @ViewBuilder
- private func row(_ title: String, _ value: String) -> some View {
- VStack(alignment: .leading, spacing: 4) {
- Text(title)
- .font(.caption)
- .foregroundStyle(.secondary)
- Text(value)
- .font(.body.monospaced())
- .textSelection(.enabled)
- }
- .padding(.vertical, 2)
- }
-
- private var diagnosticDump: String {
- var lines: [String] = []
- lines.append("Transient Banner: \(syncMonitor.transientErrorMessage ?? "None")")
- lines.append("Last Error Domain: \(syncMonitor.lastCloudKitErrorDomain ?? "None")")
- lines.append("Last Error Code: \(syncMonitor.lastCloudKitErrorCode.map(String.init) ?? "None")")
- lines.append("Last Error Description: \(syncMonitor.lastCloudKitErrorDescription ?? "None")")
- lines.append(
- "Last Success: \(syncMonitor.lastSuccessfulSyncDate.map(Self.timestampFormatter.string(from:)) ?? "None")"
- )
- lines.append("")
- lines.append("Recent Events:")
- for entry in syncMonitor.recentDiagnostics {
- lines.append(
- "\(Self.timestampFormatter.string(from: entry.timestamp)) [\(entry.level.uppercased())] \(entry.message)"
- )
- }
- return lines.joined(separator: "\n")
- }
-}
diff --git a/ListlessMac/Views/SyncDiagnosticsView.swift b/ListlessMac/Views/SyncDiagnosticsView.swift
@@ -0,0 +1,91 @@
+import SwiftUI
+
+struct SyncDiagnosticsView: View {
+ @ObservedObject var syncMonitor: CloudKitSyncMonitor
+
+ private static let timestampFormatter: DateFormatter = {
+ let formatter = DateFormatter()
+ formatter.dateStyle = .none
+ formatter.timeStyle = .medium
+ return formatter
+ }()
+
+ var body: some View {
+ List {
+ Section("Status") {
+ row("Transient Banner", syncMonitor.transientErrorMessage ?? "None")
+ row("Last Error Domain", syncMonitor.lastCloudKitErrorDomain ?? "None")
+ row("Last Error Code", syncMonitor.lastCloudKitErrorCode.map(String.init) ?? "None")
+ row("Last Error Description", syncMonitor.lastCloudKitErrorDescription ?? "None")
+ row(
+ "Last Success",
+ syncMonitor.lastSuccessfulSyncDate.map(Self.timestampFormatter.string(from:)) ?? "None"
+ )
+ }
+
+ Section("Recent Events") {
+ if syncMonitor.recentDiagnostics.isEmpty {
+ Text("No events captured yet.")
+ .foregroundStyle(.secondary)
+ } else {
+ ForEach(syncMonitor.recentDiagnostics.reversed()) { entry in
+ VStack(alignment: .leading, spacing: 4) {
+ Text(
+ "\(Self.timestampFormatter.string(from: entry.timestamp)) [\(entry.level.uppercased())]"
+ )
+ .font(.caption.monospaced())
+ .foregroundStyle(.secondary)
+
+ Text(entry.message)
+ .font(.caption.monospaced())
+ .textSelection(.enabled)
+ }
+ .padding(.vertical, 2)
+ }
+ }
+ }
+ }
+ .textSelection(.enabled)
+ .toolbar {
+ ToolbarItem {
+ Button("Copy") {
+ let pasteboard = NSPasteboard.general
+ pasteboard.clearContents()
+ pasteboard.setString(diagnosticDump, forType: .string)
+ }
+ }
+ }
+ }
+
+ @ViewBuilder
+ private func row(_ title: String, _ value: String) -> some View {
+ VStack(alignment: .leading, spacing: 4) {
+ Text(title)
+ .font(.caption)
+ .foregroundStyle(.secondary)
+ Text(value)
+ .font(.body.monospaced())
+ .textSelection(.enabled)
+ }
+ .padding(.vertical, 2)
+ }
+
+ private var diagnosticDump: String {
+ var lines: [String] = []
+ lines.append("Transient Banner: \(syncMonitor.transientErrorMessage ?? "None")")
+ lines.append("Last Error Domain: \(syncMonitor.lastCloudKitErrorDomain ?? "None")")
+ lines.append("Last Error Code: \(syncMonitor.lastCloudKitErrorCode.map(String.init) ?? "None")")
+ lines.append("Last Error Description: \(syncMonitor.lastCloudKitErrorDescription ?? "None")")
+ lines.append(
+ "Last Success: \(syncMonitor.lastSuccessfulSyncDate.map(Self.timestampFormatter.string(from:)) ?? "None")"
+ )
+ lines.append("")
+ lines.append("Recent Events:")
+ for entry in syncMonitor.recentDiagnostics {
+ lines.append(
+ "\(Self.timestampFormatter.string(from: entry.timestamp)) [\(entry.level.uppercased())] \(entry.message)"
+ )
+ }
+ return lines.joined(separator: "\n")
+ }
+}
diff --git a/ListlessiOS/Views/SyncDiagnosticsView.swift b/ListlessiOS/Views/SyncDiagnosticsView.swift
@@ -49,7 +49,7 @@ struct SyncDiagnosticsView: View {
}
}
}
- .navigationTitle("Sync Diagnostics")
+ .navigationTitle("iCloud Diagnostics")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .topBarTrailing) {