Enable CloudKit sync for Watch app and fix WCSession handling

- Watch now uses CloudKit for data persistence (syncs automatically with iPhone)
- Added iCloud/CloudKit entitlements to Watch app (debug and release)
- Fixed WCSession delegate to handle messages with reply handler
- Watch UI now shows "Already Rated" screen after voting
- Invalidate LiveActivityScheduler cache when mood is logged
- WCSession now used only for immediate UI updates, not data persistence

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-01-03 11:01:33 -06:00
parent 406d9ee4fd
commit 00cbd476d4
6 changed files with 147 additions and 66 deletions

View File

@@ -11,33 +11,44 @@ import WatchKit
struct ContentView: View {
@State private var showConfirmation = false
@State private var selectedMood: Mood?
@State private var todaysMood: Mood?
var body: some View {
ZStack {
VStack(spacing: 8) {
Text("How do you feel?")
.font(.system(size: 16, weight: .medium))
.foregroundColor(.secondary)
if let mood = todaysMood ?? selectedMood, showConfirmation || todaysMood != nil {
// Show "already rated" view
AlreadyRatedView(mood: mood)
} else {
// Show voting UI
VStack(spacing: 8) {
Text("How do you feel?")
.font(.system(size: 16, weight: .medium))
.foregroundColor(.secondary)
// Top row: Great, Good, Average
HStack(spacing: 8) {
MoodButton(mood: .great, action: { logMood(.great) })
MoodButton(mood: .good, action: { logMood(.good) })
MoodButton(mood: .average, action: { logMood(.average) })
}
// Top row: Great, Good, Average
HStack(spacing: 8) {
MoodButton(mood: .great, action: { logMood(.great) })
MoodButton(mood: .good, action: { logMood(.good) })
MoodButton(mood: .average, action: { logMood(.average) })
}
// Bottom row: Bad, Horrible
HStack(spacing: 8) {
MoodButton(mood: .bad, action: { logMood(.bad) })
MoodButton(mood: .horrible, action: { logMood(.horrible) })
// Bottom row: Bad, Horrible
HStack(spacing: 8) {
MoodButton(mood: .bad, action: { logMood(.bad) })
MoodButton(mood: .horrible, action: { logMood(.horrible) })
}
}
}
.opacity(showConfirmation ? 0.3 : 1)
}
.onAppear {
checkTodaysEntry()
}
}
// Confirmation overlay
if showConfirmation {
ConfirmationView(mood: selectedMood)
}
private func checkTodaysEntry() {
let entry = ExtensionDataProvider.shared.getTodayEntry()
if let entry = entry, entry.mood != .missing && entry.mood != .placeholder {
todaysMood = entry.mood
}
}
@@ -59,16 +70,27 @@ struct ContentView: View {
_ = WatchConnectivityManager.shared.sendMoodToPhone(mood: mood.rawValue, date: date)
}
// Show confirmation
// Show confirmation and keep it (user already rated)
withAnimation(.easeInOut(duration: 0.2)) {
showConfirmation = true
todaysMood = mood
}
}
}
// Hide confirmation after delay
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
withAnimation(.easeInOut(duration: 0.2)) {
showConfirmation = false
}
// MARK: - Already Rated View
struct AlreadyRatedView: View {
let mood: Mood
var body: some View {
VStack(spacing: 12) {
Text(mood.watchEmoji)
.font(.system(size: 50))
Text("Logged!")
.font(.system(size: 18, weight: .semibold))
.foregroundColor(.secondary)
}
}
}
@@ -92,27 +114,6 @@ struct MoodButton: View {
}
}
// MARK: - Confirmation View
struct ConfirmationView: View {
let mood: Mood?
var body: some View {
VStack(spacing: 8) {
Image(systemName: "checkmark.circle.fill")
.font(.system(size: 40))
.foregroundColor(.green)
Text("Logged!")
.font(.system(size: 18, weight: .semibold))
if let mood = mood {
Text(mood.watchEmoji)
.font(.system(size: 24))
}
}
}
}
// MARK: - Watch Mood Image Provider

View File

@@ -6,5 +6,13 @@
<array>
<string>group.com.tt.feels</string>
</array>
<key>com.apple.developer.icloud-services</key>
<array>
<string>CloudKit</string>
</array>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
<string>iCloud.com.tt.feels</string>
</array>
</dict>
</plist>

View File

@@ -6,5 +6,13 @@
<array>
<string>group.com.tt.feelsDebug</string>
</array>
<key>com.apple.developer.icloud-services</key>
<array>
<string>CloudKit</string>
</array>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
<string>iCloud.com.tt.feelsDebug</string>
</array>
</dict>
</plist>