Add insights screenshot export and improve promo video phone frames
- Add ExportableInsightsViews with sample AI insights data - Add InsightsExporter service for light/dark mode screenshots - Add export insights button to Settings debug section - Update ConceptB promo to use insights_light.png in privacy scene - Fix phone frame clipping with overflow hidden and borderRadius 64 - Add timeline voting widget images for promo video Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,8 @@ struct SettingsContentView: View {
|
||||
@State private var votingLayoutExportPath: URL?
|
||||
@State private var isExportingWatchViews = false
|
||||
@State private var watchExportPath: URL?
|
||||
@State private var isExportingInsights = false
|
||||
@State private var insightsExportPath: URL?
|
||||
@State private var isDeletingHealthKitData = false
|
||||
@State private var healthKitDeleteResult: String?
|
||||
@StateObject private var healthService = HealthService.shared
|
||||
@@ -70,6 +72,7 @@ struct SettingsContentView: View {
|
||||
exportWidgetsButton
|
||||
exportVotingLayoutsButton
|
||||
exportWatchViewsButton
|
||||
exportInsightsButton
|
||||
deleteHealthKitDataButton
|
||||
|
||||
clearDataButton
|
||||
@@ -437,10 +440,9 @@ struct SettingsContentView: View {
|
||||
Task {
|
||||
widgetExportPath = await WidgetExporter.exportAllWidgets()
|
||||
isExportingWidgets = false
|
||||
// Open Files app to the export location
|
||||
if let path = widgetExportPath {
|
||||
// Show share sheet or alert with path
|
||||
print("📸 Widgets exported to: \(path.path)")
|
||||
openInFilesApp(path)
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
@@ -494,6 +496,7 @@ struct SettingsContentView: View {
|
||||
isExportingVotingLayouts = false
|
||||
if let path = votingLayoutExportPath {
|
||||
print("📸 Voting layouts exported to: \(path.path)")
|
||||
openInFilesApp(path)
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
@@ -547,6 +550,7 @@ struct SettingsContentView: View {
|
||||
isExportingWatchViews = false
|
||||
if let path = watchExportPath {
|
||||
print("⌚ Watch views exported to: \(path.path)")
|
||||
openInFilesApp(path)
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
@@ -590,6 +594,66 @@ struct SettingsContentView: View {
|
||||
.cornerRadius(Constants.viewsCornerRaidus, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
||||
}
|
||||
|
||||
private var exportInsightsButton: some View {
|
||||
ZStack {
|
||||
theme.currentTheme.secondaryBGColor
|
||||
Button {
|
||||
isExportingInsights = true
|
||||
Task {
|
||||
insightsExportPath = await InsightsExporter.exportInsightsScreenshots()
|
||||
isExportingInsights = false
|
||||
if let path = insightsExportPath {
|
||||
print("✨ Insights exported to: \(path.path)")
|
||||
openInFilesApp(path)
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
HStack(spacing: 12) {
|
||||
if isExportingInsights {
|
||||
ProgressView()
|
||||
.frame(width: 32)
|
||||
} else {
|
||||
Image(systemName: "sparkles")
|
||||
.font(.title2)
|
||||
.foregroundStyle(
|
||||
LinearGradient(
|
||||
colors: [.purple, .blue],
|
||||
startPoint: .leading,
|
||||
endPoint: .trailing
|
||||
)
|
||||
)
|
||||
.frame(width: 32)
|
||||
}
|
||||
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text("Export Insights Screenshots")
|
||||
.foregroundColor(textColor)
|
||||
|
||||
if let path = insightsExportPath {
|
||||
Text("Saved to Documents/InsightsExports")
|
||||
.font(.caption)
|
||||
.foregroundColor(.green)
|
||||
} else {
|
||||
Text("AI insights in light & dark mode")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
Image(systemName: "arrow.down.doc.fill")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.tertiary)
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
.disabled(isExportingInsights)
|
||||
}
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.cornerRadius(Constants.viewsCornerRaidus, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
||||
}
|
||||
|
||||
private var deleteHealthKitDataButton: some View {
|
||||
ZStack {
|
||||
theme.currentTheme.secondaryBGColor
|
||||
@@ -975,6 +1039,21 @@ struct SettingsContentView: View {
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.cornerRadius(Constants.viewsCornerRaidus, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
||||
}
|
||||
|
||||
// MARK: - Helper Functions
|
||||
|
||||
private func openInFilesApp(_ url: URL) {
|
||||
#if targetEnvironment(simulator)
|
||||
// On simulator, copy path to clipboard for easy Finder access (Cmd+Shift+G)
|
||||
UIPasteboard.general.string = url.path
|
||||
#else
|
||||
// On device, open Files app
|
||||
let filesAppURL = URL(string: "shareddocuments://\(url.path)")!
|
||||
if UIApplication.shared.canOpenURL(filesAppURL) {
|
||||
UIApplication.shared.open(filesAppURL)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Reminder Time Picker View
|
||||
|
||||
Reference in New Issue
Block a user