Add watch view export and update promo video watch display

- Add ExportableWatchViews.swift with exportable versions of watch app views
- Add WatchExporter.swift service to export all watch view variations
- Add export watch screenshots button to Settings (DEBUG)
- Update ConceptB promo: use watch_voting_light.png inside watch frame at 1.2x size

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-01-30 10:50:48 -06:00
parent 3efb07258d
commit 36ceff32ca
5 changed files with 858 additions and 138 deletions

View File

@@ -21,6 +21,10 @@ struct SettingsContentView: View {
@State private var showTrialDatePicker = false
@State private var isExportingWidgets = false
@State private var widgetExportPath: URL?
@State private var isExportingVotingLayouts = false
@State private var votingLayoutExportPath: URL?
@State private var isExportingWatchViews = false
@State private var watchExportPath: URL?
@State private var isDeletingHealthKitData = false
@State private var healthKitDeleteResult: String?
@StateObject private var healthService = HealthService.shared
@@ -64,6 +68,8 @@ struct SettingsContentView: View {
tipsPreviewButton
testNotificationsButton
exportWidgetsButton
exportVotingLayoutsButton
exportWatchViewsButton
deleteHealthKitDataButton
clearDataButton
@@ -478,6 +484,112 @@ struct SettingsContentView: View {
.cornerRadius(Constants.viewsCornerRaidus, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
}
private var exportVotingLayoutsButton: some View {
ZStack {
theme.currentTheme.secondaryBGColor
Button {
isExportingVotingLayouts = true
Task {
votingLayoutExportPath = await WidgetExporter.exportAllVotingLayouts()
isExportingVotingLayouts = false
if let path = votingLayoutExportPath {
print("📸 Voting layouts exported to: \(path.path)")
}
}
} label: {
HStack(spacing: 12) {
if isExportingVotingLayouts {
ProgressView()
.frame(width: 32)
} else {
Image(systemName: "hand.tap.fill")
.font(.title2)
.foregroundColor(.blue)
.frame(width: 32)
}
VStack(alignment: .leading, spacing: 2) {
Text("Export Voting Layouts")
.foregroundColor(textColor)
if let path = votingLayoutExportPath {
Text("Saved to Documents/VotingLayoutExports")
.font(.caption)
.foregroundColor(.green)
} else {
Text("All sizes & theme variations")
.font(.caption)
.foregroundStyle(.secondary)
}
}
Spacer()
Image(systemName: "arrow.down.doc.fill")
.font(.caption)
.foregroundStyle(.tertiary)
}
.padding()
}
.disabled(isExportingVotingLayouts)
}
.fixedSize(horizontal: false, vertical: true)
.cornerRadius(Constants.viewsCornerRaidus, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
}
private var exportWatchViewsButton: some View {
ZStack {
theme.currentTheme.secondaryBGColor
Button {
isExportingWatchViews = true
Task {
watchExportPath = await WatchExporter.exportAllWatchViews()
isExportingWatchViews = false
if let path = watchExportPath {
print("⌚ Watch views exported to: \(path.path)")
}
}
} label: {
HStack(spacing: 12) {
if isExportingWatchViews {
ProgressView()
.frame(width: 32)
} else {
Image(systemName: "applewatch.watchface")
.font(.title2)
.foregroundColor(.cyan)
.frame(width: 32)
}
VStack(alignment: .leading, spacing: 2) {
Text("Export Watch Screenshots")
.foregroundColor(textColor)
if let path = watchExportPath {
Text("Saved to Documents/WatchExports")
.font(.caption)
.foregroundColor(.green)
} else {
Text("All styles & complications")
.font(.caption)
.foregroundStyle(.secondary)
}
}
Spacer()
Image(systemName: "arrow.down.doc.fill")
.font(.caption)
.foregroundStyle(.tertiary)
}
.padding()
}
.disabled(isExportingWatchViews)
}
.fixedSize(horizontal: false, vertical: true)
.cornerRadius(Constants.viewsCornerRaidus, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
}
private var deleteHealthKitDataButton: some View {
ZStack {
theme.currentTheme.secondaryBGColor