Add premium features and reorganize Settings tab
Premium Features: - Journal notes and photo attachments for mood entries - Data export (CSV and PDF reports) - Privacy lock with Face ID/Touch ID - Apple Health integration for mood correlation - 4 new personality packs (Motivational Coach, Zen Master, Best Friend, Data Analyst) Settings Tab Reorganization: - Combined Customize and Settings into single tab with segmented control - Added upgrade banner with trial countdown above segment - "Why Upgrade?" sheet showing all premium benefits - Subscribe button opens improved StoreKit 2 subscription view UI Improvements: - Enhanced subscription store with feature highlights - Entry detail view for viewing/editing notes and photos - Removed duplicate subscription banners from tab content 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -30,11 +30,11 @@ struct DayView: View {
|
||||
// MARK: edit row properties
|
||||
@State private var showingSheet = false
|
||||
@State private var selectedEntry: MoodEntryModel?
|
||||
@State private var showEntryDetail = false
|
||||
//
|
||||
|
||||
// MARK: ?? properties
|
||||
@State private var showTodayInput = true
|
||||
@State private var showUpdateEntryAlert = false
|
||||
@StateObject private var onboardingData = OnboardingDataDataManager.shared
|
||||
@StateObject private var filteredDays = DaysFilterClass.shared
|
||||
@EnvironmentObject var iapManager: IAPManager
|
||||
@@ -53,31 +53,25 @@ struct DayView: View {
|
||||
.sheet(isPresented: $showingSheet) {
|
||||
SettingsView()
|
||||
}
|
||||
.alert(DayViewViewModel.updateTitleHeader(forEntry: selectedEntry),
|
||||
isPresented: $showUpdateEntryAlert) {
|
||||
ForEach(Mood.allValues) { mood in
|
||||
Button(mood.strValue, action: {
|
||||
if let selectedEntry = selectedEntry {
|
||||
viewModel.update(entry: selectedEntry, toMood: mood)
|
||||
.onChange(of: selectedEntry) { _, newEntry in
|
||||
if newEntry != nil {
|
||||
showEntryDetail = true
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showEntryDetail, onDismiss: {
|
||||
selectedEntry = nil
|
||||
}) {
|
||||
if let entry = selectedEntry {
|
||||
EntryDetailView(
|
||||
entry: entry,
|
||||
onMoodUpdate: { newMood in
|
||||
viewModel.update(entry: entry, toMood: newMood)
|
||||
},
|
||||
onDelete: {
|
||||
viewModel.update(entry: entry, toMood: .missing)
|
||||
}
|
||||
showUpdateEntryAlert = false
|
||||
selectedEntry = nil
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
if let selectedEntry = selectedEntry,
|
||||
deleteEnabled,
|
||||
selectedEntry.mood != .missing {
|
||||
Button(String(localized: "content_view_delete_entry"), action: {
|
||||
viewModel.update(entry: selectedEntry, toMood: Mood.missing)
|
||||
showUpdateEntryAlert = false
|
||||
})
|
||||
}
|
||||
|
||||
Button(String(localized: "content_view_fill_in_missing_entry_cancel"), role: .cancel, action: {
|
||||
selectedEntry = nil
|
||||
showUpdateEntryAlert = false
|
||||
})
|
||||
}
|
||||
}
|
||||
.padding([.top])
|
||||
@@ -182,10 +176,9 @@ extension DayView {
|
||||
ForEach(filteredEntries, id: \.self) { entry in
|
||||
EntryListView(entry: entry)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture(perform: {
|
||||
.onTapGesture {
|
||||
selectedEntry = entry
|
||||
showUpdateEntryAlert = true
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 12)
|
||||
@@ -196,10 +189,9 @@ extension DayView {
|
||||
ForEach(filteredEntries, id: \.self) { entry in
|
||||
EntryListView(entry: entry)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture(perform: {
|
||||
.onTapGesture {
|
||||
selectedEntry = entry
|
||||
showUpdateEntryAlert = true
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 12)
|
||||
|
||||
Reference in New Issue
Block a user