Add interactive voting to all timeline widgets
- SmallWidgetView now shows VotingView when vote needed - MediumWidgetView now shows VotingView when vote needed - LargeWidgetView now shows LargeVotingView when vote needed - Add new LargeVotingView with larger buttons and mood labels - All voting buttons use VoteMoodIntent for interactive voting 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -337,6 +337,10 @@ struct SmallWidgetView: View {
|
||||
var entry: Provider.Entry
|
||||
var todayView: WatchTimelineView?
|
||||
|
||||
private var showVotingForToday: Bool {
|
||||
entry.hasSubscription && !entry.hasVotedToday
|
||||
}
|
||||
|
||||
private var dayFormatter: DateFormatter {
|
||||
let f = DateFormatter()
|
||||
f.dateFormat = "EEEE"
|
||||
@@ -360,7 +364,10 @@ struct SmallWidgetView: View {
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
if let today = todayView {
|
||||
if showVotingForToday {
|
||||
// Show interactive voting buttons
|
||||
VotingView(family: .systemSmall, promptText: entry.promptText)
|
||||
} else if let today = todayView {
|
||||
VStack(spacing: 0) {
|
||||
Spacer()
|
||||
|
||||
@@ -431,6 +438,10 @@ struct MediumWidgetView: View {
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
if showVotingForToday {
|
||||
// Show interactive voting buttons
|
||||
VotingView(family: .systemMedium, promptText: entry.promptText)
|
||||
} else {
|
||||
GeometryReader { geo in
|
||||
let cellHeight = geo.size.height - 36
|
||||
|
||||
@@ -469,6 +480,7 @@ struct MediumWidgetView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Day Cell for Medium Widget
|
||||
|
||||
@@ -538,6 +550,10 @@ struct LargeWidgetView: View {
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
if showVotingForToday {
|
||||
// Show interactive voting buttons for large widget
|
||||
LargeVotingView(promptText: entry.promptText)
|
||||
} else {
|
||||
GeometryReader { geo in
|
||||
let cellHeight = (geo.size.height - 70) / 2 // Subtract header height, divide by 2 rows
|
||||
|
||||
@@ -592,6 +608,7 @@ struct LargeWidgetView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var headerDateRange: String {
|
||||
guard let first = timeLineView.first, let last = timeLineView.last else { return "" }
|
||||
@@ -646,6 +663,63 @@ struct DayCell: View {
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Large Voting View
|
||||
|
||||
struct LargeVotingView: View {
|
||||
let promptText: String
|
||||
|
||||
private var moodTint: MoodTintable.Type {
|
||||
UserDefaultsStore.moodTintable()
|
||||
}
|
||||
|
||||
private var moodImages: MoodImagable.Type {
|
||||
UserDefaultsStore.moodMoodImagable()
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 24) {
|
||||
Spacer()
|
||||
|
||||
Text(promptText)
|
||||
.font(.title2.weight(.semibold))
|
||||
.foregroundStyle(.primary)
|
||||
.multilineTextAlignment(.center)
|
||||
.lineLimit(2)
|
||||
.minimumScaleFactor(0.8)
|
||||
|
||||
// Large mood buttons in a row
|
||||
HStack(spacing: 20) {
|
||||
ForEach([Mood.great, .good, .average, .bad, .horrible], id: \.rawValue) { mood in
|
||||
Button(intent: VoteMoodIntent(mood: mood)) {
|
||||
VStack(spacing: 8) {
|
||||
moodImages.icon(forMood: mood)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: 56, height: 56)
|
||||
.foregroundColor(moodTint.color(forMood: mood))
|
||||
|
||||
Text(mood.strValue)
|
||||
.font(.caption.weight(.medium))
|
||||
.foregroundColor(moodTint.color(forMood: mood))
|
||||
}
|
||||
.padding(.vertical, 12)
|
||||
.padding(.horizontal, 8)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 16)
|
||||
.fill(moodTint.color(forMood: mood).opacity(0.15))
|
||||
)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************/
|
||||
struct FeelsGraphicWidgetEntryView : View {
|
||||
@Environment(\.sizeCategory) var sizeCategory
|
||||
|
||||
Reference in New Issue
Block a user