fix(schedule): use start of day for date range queries
- Fix startDate to use Calendar.startOfDay instead of Date() to include games earlier in the current day - Add SyncLogger for file-based sync logging viewable in Settings - Add "View Sync Logs" button in Settings debug section - Add diagnostics and NBA game logging to ScheduleViewModel - Add dropped game logging to DataProvider.filterRichGames - Use SyncLogger in SportsTimeApp and CloudKitService for sync operations Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,7 @@ struct SettingsView: View {
|
||||
@State private var showOnboardingPaywall = false
|
||||
#if DEBUG
|
||||
@State private var selectedSyncStatus: EntitySyncStatus?
|
||||
@State private var showSyncLogs = false
|
||||
#endif
|
||||
|
||||
var body: some View {
|
||||
@@ -433,6 +434,13 @@ struct SettingsView: View {
|
||||
} label: {
|
||||
Label("Trigger Sync Now", systemImage: "arrow.triangle.2.circlepath")
|
||||
}
|
||||
|
||||
// View sync logs
|
||||
Button {
|
||||
showSyncLogs = true
|
||||
} label: {
|
||||
Label("View Sync Logs", systemImage: "doc.text.magnifyingglass")
|
||||
}
|
||||
} header: {
|
||||
Text("Sync Status")
|
||||
} footer: {
|
||||
@@ -442,6 +450,9 @@ struct SettingsView: View {
|
||||
.sheet(item: $selectedSyncStatus) { status in
|
||||
SyncStatusDetailSheet(status: status)
|
||||
}
|
||||
.sheet(isPresented: $showSyncLogs) {
|
||||
SyncLogViewerSheet()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -666,4 +677,67 @@ private struct DetailRow: View {
|
||||
}
|
||||
}
|
||||
|
||||
/// Sheet to view sync logs
|
||||
struct SyncLogViewerSheet: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@State private var logContent = ""
|
||||
@State private var autoScroll = true
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
ScrollViewReader { proxy in
|
||||
ScrollView {
|
||||
Text(logContent)
|
||||
.font(.system(.caption, design: .monospaced))
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding()
|
||||
.id("logBottom")
|
||||
}
|
||||
.onChange(of: logContent) {
|
||||
if autoScroll {
|
||||
withAnimation {
|
||||
proxy.scrollTo("logBottom", anchor: .bottom)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Sync Logs")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .topBarLeading) {
|
||||
Button("Clear") {
|
||||
SyncLogger.shared.clearLog()
|
||||
logContent = "Log cleared."
|
||||
}
|
||||
}
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
Button("Done") {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
ToolbarItem(placement: .bottomBar) {
|
||||
HStack {
|
||||
Button {
|
||||
logContent = SyncLogger.shared.readLog()
|
||||
} label: {
|
||||
Label("Refresh", systemImage: "arrow.clockwise")
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
Toggle("Auto-scroll", isOn: $autoScroll)
|
||||
.toggleStyle(.switch)
|
||||
.labelsHidden()
|
||||
Text("Auto-scroll")
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
logContent = SyncLogger.shared.readLog()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user