Remove #if DEBUG guards for TestFlight, polish weekly digest and insights UX

- Remove #if DEBUG from all debug settings, exporters, and IAP bypass so
  debug options are available in TestFlight builds
- Weekly digest card: replace dismiss X with collapsible chevron caret
- Weekly digest: generate on-demand when opening Insights tab if no cached
  digest exists (BGTask + notification kept as bonus path)
- Fix digest intention text color (was .secondary, now uses theme textColor)
- Add "Generate Weekly Digest" debug button in Settings
- Add generating overlay on Insights tab with pulsing sparkles icon that
  stays visible until all sections finish loading (content at 0.2 opacity)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-04-04 11:15:23 -05:00
parent ab8d8fbdc0
commit 329fb7c671
16 changed files with 232 additions and 117 deletions

View File

@@ -68,7 +68,6 @@ struct SettingsContentView: View {
privacyButton
analyticsToggle
#if DEBUG
// Debug section
debugSectionHeader
addTestDataButton
@@ -83,9 +82,9 @@ struct SettingsContentView: View {
exportInsightsButton
generateAndExportButton
deleteHealthKitDataButton
generateWeeklyDigestButton
clearDataButton
#endif
Spacer()
.frame(height: 20)
@@ -207,7 +206,6 @@ struct SettingsContentView: View {
// MARK: - Debug Section
#if DEBUG
private var debugSectionHeader: some View {
HStack {
Text("Debug")
@@ -759,6 +757,63 @@ struct SettingsContentView: View {
.cornerRadius(Constants.viewsCornerRaidus, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
}
@State private var isGeneratingDigest = false
@State private var digestResult: String?
private var generateWeeklyDigestButton: some View {
Button {
isGeneratingDigest = true
digestResult = nil
Task {
if #available(iOS 26, *) {
do {
let digest = try await FoundationModelsDigestService.shared.generateWeeklyDigest()
digestResult = "\(digest.headline)"
} catch {
digestResult = "\(error.localizedDescription)"
}
} else {
digestResult = "✗ Requires iOS 26+"
}
isGeneratingDigest = false
}
} label: {
HStack(spacing: 12) {
if isGeneratingDigest {
ProgressView()
.frame(width: 32)
} else {
Image(systemName: "sparkles.rectangle.stack")
.font(.title2)
.foregroundColor(.purple)
.frame(width: 32)
}
VStack(alignment: .leading, spacing: 2) {
Text("Generate Weekly Digest")
.foregroundColor(textColor)
if let result = digestResult {
Text(result)
.font(.caption)
.foregroundColor(result.contains("") ? .green : .red)
} else {
Text("Create AI digest now (shows in Insights tab)")
.font(.caption)
.foregroundStyle(.secondary)
}
}
Spacer()
}
.padding()
}
.disabled(isGeneratingDigest)
.background(theme.currentTheme.secondaryBGColor)
.fixedSize(horizontal: false, vertical: true)
.cornerRadius(Constants.viewsCornerRaidus, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
}
private var clearDataButton: some View {
Button {
MoodLogger.shared.deleteAllData()
@@ -787,7 +842,6 @@ struct SettingsContentView: View {
.fixedSize(horizontal: false, vertical: true)
.cornerRadius(Constants.viewsCornerRaidus, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
}
#endif
// MARK: - Privacy Lock Toggle
@@ -1394,7 +1448,6 @@ struct SettingsView: View {
// specialThanksCell
}
#if DEBUG
Group {
Divider()
Text("Test builds only")
@@ -1410,7 +1463,6 @@ struct SettingsView: View {
Divider()
}
Spacer()
#endif
Text("\(Bundle.main.appName) v \(Bundle.main.versionNumber) (Build \(Bundle.main.buildNumber))")
.font(.body)
}