Add Apple platform features and UX improvements
- Add HealthKit State of Mind sync for mood entries - Add Live Activity with streak display and rating time window - Add App Shortcuts/Siri integration for voice mood logging - Add TipKit hints for feature discovery - Add centralized MoodLogger for consistent side effects - Add reminder time setting in Settings with time picker - Fix duplicate notifications when changing reminder time - Fix Live Activity streak showing 0 when not yet rated today - Fix slow tap response in entry detail mood selection - Update widget timeline to refresh at rating time - Sync widgets when reminder time changes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
|
||||
import SwiftUI
|
||||
import StoreKit
|
||||
import TipKit
|
||||
|
||||
// MARK: - Customize Content View (for use in SettingsTabView)
|
||||
struct CustomizeContentView: View {
|
||||
@@ -17,6 +18,10 @@ struct CustomizeContentView: View {
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
VStack(spacing: 24) {
|
||||
// Customize tip
|
||||
TipView(CustomizeLayoutTip())
|
||||
.tipBackground(Color(.secondarySystemBackground))
|
||||
|
||||
// APPEARANCE
|
||||
SettingsSection(title: "Appearance") {
|
||||
VStack(spacing: 16) {
|
||||
@@ -640,16 +645,16 @@ struct PersonalityPackPickerCompact: View {
|
||||
VStack(spacing: 8) {
|
||||
ForEach(PersonalityPack.allCases, id: \.self) { aPack in
|
||||
Button(action: {
|
||||
if aPack.rawValue == PersonalityPack.Rude.rawValue && !showNSFW {
|
||||
showOver18Alert = true
|
||||
EventLogger.log(event: "show_over_18_alert")
|
||||
} else {
|
||||
// if aPack.rawValue == PersonalityPack.Rude.rawValue && !showNSFW {
|
||||
// showOver18Alert = true
|
||||
// EventLogger.log(event: "show_over_18_alert")
|
||||
// } else {
|
||||
let impactMed = UIImpactFeedbackGenerator(style: .medium)
|
||||
impactMed.impactOccurred()
|
||||
personalityPack = aPack
|
||||
EventLogger.log(event: "change_personality_pack", withData: ["pack_title": aPack.title()])
|
||||
LocalNotification.rescheduleNotifiations()
|
||||
}
|
||||
// }
|
||||
}) {
|
||||
HStack {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
@@ -681,7 +686,7 @@ struct PersonalityPackPickerCompact: View {
|
||||
)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.blur(radius: aPack.rawValue == PersonalityPack.Rude.rawValue && !showNSFW ? 4 : 0)
|
||||
// .blur(radius: aPack.rawValue == PersonalityPack.Rude.rawValue && !showNSFW ? 4 : 0)
|
||||
}
|
||||
}
|
||||
.alert(isPresented: $showOver18Alert) {
|
||||
|
||||
@@ -40,18 +40,18 @@ struct PersonalityPackPickerView: View {
|
||||
.padding(5)
|
||||
)
|
||||
.onTapGesture {
|
||||
if aPack.rawValue == PersonalityPack.Rude.rawValue && !showNSFW {
|
||||
showOver18Alert = true
|
||||
EventLogger.log(event: "show_over_18_alert")
|
||||
} else {
|
||||
// if aPack.rawValue == PersonalityPack.Rude.rawValue && !showNSFW {
|
||||
// showOver18Alert = true
|
||||
// EventLogger.log(event: "show_over_18_alert")
|
||||
// } else {
|
||||
let impactMed = UIImpactFeedbackGenerator(style: .heavy)
|
||||
impactMed.impactOccurred()
|
||||
personalityPack = aPack
|
||||
EventLogger.log(event: "change_personality_pack", withData: ["pack_title": aPack.title()])
|
||||
LocalNotification.rescheduleNotifiations()
|
||||
}
|
||||
// }
|
||||
}
|
||||
.blur(radius: aPack.rawValue == PersonalityPack.Rude.rawValue && !showNSFW ? 5 : 0)
|
||||
// .blur(radius: aPack.rawValue == PersonalityPack.Rude.rawValue && !showNSFW ? 5 : 0)
|
||||
.alert(isPresented: $showOver18Alert) {
|
||||
let primaryButton = Alert.Button.default(Text(String(localized: "customize_view_over18alert_ok"))) {
|
||||
showNSFW = true
|
||||
|
||||
Reference in New Issue
Block a user