v1.1 polish: accessibility, error logging, localization, and code quality sweep
- Wrap 30+ production print() statements in #if DEBUG guards across 18 files - Add VoiceOver labels, hints, and traits to Watch app, Live Activities, widgets - Add .accessibilityAddTraits(.isButton) to 15+ onTapGesture views - Add text alternatives for color-only indicators (progress dots, mood circles) - Localize raw string literals in NoteEditorView, EntryDetailView, widgets - Replace 25+ silent try? with do/catch + AppLogger error logging - Replace hardcoded font sizes with semantic Dynamic Type fonts - Fix FIXME in IconPickerView (log icon change errors) - Extract magic animation delays to named constants across 8 files - Add widget empty state "Log your first mood!" messaging - Hide decorative images from VoiceOver, add labels to ColorPickers - Remove stale TODO in Color+Codable (alpha change deferred for migration) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -324,7 +324,9 @@ struct LiveActivityRecordingView: View {
|
||||
try? FileManager.default.createDirectory(at: outputDir, withIntermediateDirectories: true)
|
||||
|
||||
exportPath = outputDir.path
|
||||
#if DEBUG
|
||||
print("📁 Exporting frames to: \(exportPath)")
|
||||
#endif
|
||||
|
||||
let target = targetStreak
|
||||
let outDir = outputDir
|
||||
@@ -359,7 +361,9 @@ struct LiveActivityRecordingView: View {
|
||||
|
||||
await MainActor.run {
|
||||
exportComplete = true
|
||||
#if DEBUG
|
||||
print("✅ Export complete! \(target) frames saved to: \(outPath)")
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,10 @@ import SwiftUI
|
||||
import UniformTypeIdentifiers
|
||||
import StoreKit
|
||||
|
||||
private enum SettingsAnimationConstants {
|
||||
static let locationPermissionCheckDelay: TimeInterval = 1.0
|
||||
}
|
||||
|
||||
// MARK: - Settings Content View (for use in SettingsTabView)
|
||||
struct SettingsContentView: View {
|
||||
@EnvironmentObject var authManager: BiometricAuthManager
|
||||
@@ -437,7 +441,9 @@ struct SettingsContentView: View {
|
||||
widgetExportPath = await WidgetExporter.exportAllWidgets()
|
||||
isExportingWidgets = false
|
||||
if let path = widgetExportPath {
|
||||
#if DEBUG
|
||||
print("📸 Widgets exported to: \(path.path)")
|
||||
#endif
|
||||
openInFilesApp(path)
|
||||
}
|
||||
}
|
||||
@@ -490,7 +496,9 @@ struct SettingsContentView: View {
|
||||
votingLayoutExportPath = await WidgetExporter.exportAllVotingLayouts()
|
||||
isExportingVotingLayouts = false
|
||||
if let path = votingLayoutExportPath {
|
||||
#if DEBUG
|
||||
print("📸 Voting layouts exported to: \(path.path)")
|
||||
#endif
|
||||
openInFilesApp(path)
|
||||
}
|
||||
}
|
||||
@@ -543,7 +551,9 @@ struct SettingsContentView: View {
|
||||
watchExportPath = await WatchExporter.exportAllWatchViews()
|
||||
isExportingWatchViews = false
|
||||
if let path = watchExportPath {
|
||||
#if DEBUG
|
||||
print("⌚ Watch views exported to: \(path.path)")
|
||||
#endif
|
||||
openInFilesApp(path)
|
||||
}
|
||||
}
|
||||
@@ -596,7 +606,9 @@ struct SettingsContentView: View {
|
||||
insightsExportPath = await InsightsExporter.exportInsightsScreenshots()
|
||||
isExportingInsights = false
|
||||
if let path = insightsExportPath {
|
||||
#if DEBUG
|
||||
print("✨ Insights exported to: \(path.path)")
|
||||
#endif
|
||||
openInFilesApp(path)
|
||||
}
|
||||
}
|
||||
@@ -656,7 +668,9 @@ struct SettingsContentView: View {
|
||||
sharingExportPath = await SharingScreenshotExporter.exportAllSharingScreenshots()
|
||||
isGeneratingScreenshots = false
|
||||
if let path = sharingExportPath {
|
||||
#if DEBUG
|
||||
print("📸 Sharing screenshots exported to: \(path.path)")
|
||||
#endif
|
||||
openInFilesApp(path)
|
||||
}
|
||||
}
|
||||
@@ -916,7 +930,9 @@ struct SettingsContentView: View {
|
||||
AnalyticsManager.shared.track(.healthKitNotAuthorized)
|
||||
}
|
||||
} catch {
|
||||
#if DEBUG
|
||||
print("HealthKit authorization failed: \(error)")
|
||||
#endif
|
||||
AnalyticsManager.shared.track(.healthKitEnableFailed)
|
||||
}
|
||||
}
|
||||
@@ -1014,7 +1030,7 @@ struct SettingsContentView: View {
|
||||
LocationManager.shared.requestAuthorization()
|
||||
// Check if permission was denied after a brief delay
|
||||
Task {
|
||||
try? await Task.sleep(for: .seconds(1))
|
||||
try? await Task.sleep(for: .seconds(SettingsAnimationConstants.locationPermissionCheckDelay))
|
||||
let status = LocationManager.shared.authorizationStatus
|
||||
if status == .denied || status == .restricted {
|
||||
weatherEnabled = false
|
||||
@@ -1445,9 +1461,13 @@ struct SettingsView: View {
|
||||
switch result {
|
||||
case .success(let url):
|
||||
AnalyticsManager.shared.track(.dataExported(format: "file", count: 0))
|
||||
#if DEBUG
|
||||
print("Saved to \(url)")
|
||||
#endif
|
||||
case .failure(let error):
|
||||
#if DEBUG
|
||||
print(error.localizedDescription)
|
||||
#endif
|
||||
}
|
||||
})
|
||||
.fileImporter(isPresented: $showingImporter, allowedContentTypes: [.text],
|
||||
@@ -1488,8 +1508,10 @@ struct SettingsView: View {
|
||||
} catch {
|
||||
// Handle failure.
|
||||
AnalyticsManager.shared.track(.importFailed(error: error.localizedDescription))
|
||||
#if DEBUG
|
||||
print("Unable to read file contents")
|
||||
print(error.localizedDescription)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1629,7 +1651,9 @@ struct SettingsView: View {
|
||||
AnalyticsManager.shared.track(.healthKitNotAuthorized)
|
||||
}
|
||||
} catch {
|
||||
#if DEBUG
|
||||
print("HealthKit authorization failed: \(error)")
|
||||
#endif
|
||||
AnalyticsManager.shared.track(.healthKitEnableFailed)
|
||||
}
|
||||
}
|
||||
@@ -1719,7 +1743,7 @@ struct SettingsView: View {
|
||||
LocationManager.shared.requestAuthorization()
|
||||
// Check if permission was denied after a brief delay
|
||||
Task {
|
||||
try? await Task.sleep(for: .seconds(1))
|
||||
try? await Task.sleep(for: .seconds(SettingsAnimationConstants.locationPermissionCheckDelay))
|
||||
let status = LocationManager.shared.authorizationStatus
|
||||
if status == .denied || status == .restricted {
|
||||
weatherEnabled = false
|
||||
@@ -2280,9 +2304,13 @@ struct SettingsView: View {
|
||||
let url = URL(fileURLWithPath: path)
|
||||
do {
|
||||
try image.jpegData(compressionQuality: 1.0)?.write(to: url, options: .atomic)
|
||||
#if DEBUG
|
||||
print(url)
|
||||
#endif
|
||||
} catch {
|
||||
#if DEBUG
|
||||
print(error.localizedDescription)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user