Skip to content

Commit 3493739

Browse files
committed
Add MotivationalQuoteService
1 parent 2ebfb96 commit 3493739

File tree

7 files changed

+559
-10
lines changed

7 files changed

+559
-10
lines changed

LongevityMaster.xcodeproj/project.pbxproj

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -375,12 +375,13 @@
375375
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
376376
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
377377
CODE_SIGN_STYLE = Automatic;
378-
CURRENT_PROJECT_VERSION = 1.2.0.1;
378+
CURRENT_PROJECT_VERSION = 1.3.0.1;
379379
DEVELOPMENT_ASSET_PATHS = "\"LongevityMaster/Preview Content\"";
380380
DEVELOPMENT_TEAM = F694X76A5X;
381381
ENABLE_PREVIEWS = YES;
382382
GENERATE_INFOPLIST_FILE = YES;
383383
INFOPLIST_FILE = "LongevityMaster/LongevityMaster-Info.plist";
384+
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.healthcare-fitness";
384385
INFOPLIST_KEY_NSUserTrackingUsageDescription = "This identifier will be used to deliver personalized ads to you.";
385386
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
386387
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
@@ -392,7 +393,7 @@
392393
"$(inherited)",
393394
"@executable_path/Frameworks",
394395
);
395-
MARKETING_VERSION = 1.2.0;
396+
MARKETING_VERSION = 1.3.0;
396397
PRODUCT_BUNDLE_IDENTIFIER = com.appsbayarea.longevityMaster;
397398
PRODUCT_NAME = "$(TARGET_NAME)";
398399
SWIFT_EMIT_LOC_STRINGS = YES;
@@ -409,12 +410,13 @@
409410
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
410411
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
411412
CODE_SIGN_STYLE = Automatic;
412-
CURRENT_PROJECT_VERSION = 1.2.0.1;
413+
CURRENT_PROJECT_VERSION = 1.3.0.1;
413414
DEVELOPMENT_ASSET_PATHS = "\"LongevityMaster/Preview Content\"";
414415
DEVELOPMENT_TEAM = F694X76A5X;
415416
ENABLE_PREVIEWS = YES;
416417
GENERATE_INFOPLIST_FILE = YES;
417418
INFOPLIST_FILE = "LongevityMaster/LongevityMaster-Info.plist";
419+
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.healthcare-fitness";
418420
INFOPLIST_KEY_NSUserTrackingUsageDescription = "This identifier will be used to deliver personalized ads to you.";
419421
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
420422
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
@@ -426,7 +428,7 @@
426428
"$(inherited)",
427429
"@executable_path/Frameworks",
428430
);
429-
MARKETING_VERSION = 1.2.0;
431+
MARKETING_VERSION = 1.3.0;
430432
PRODUCT_BUNDLE_IDENTIFIER = com.appsbayarea.longevityMaster;
431433
PRODUCT_NAME = "$(TARGET_NAME)";
432434
SWIFT_EMIT_LOC_STRINGS = YES;
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//
2+
// MotivationalQuoteView.swift
3+
// LongevityMaster
4+
//
5+
// Created by Banghua Zhao on 2025/1/27.
6+
// Copyright Apps Bay Limited. All rights reserved.
7+
//
8+
9+
import SwiftUI
10+
import Dependencies
11+
12+
struct MotivationalQuoteView: View {
13+
let quote: MotivationalQuote
14+
let onDismiss: () -> Void
15+
16+
@Dependency(\.themeManager) var themeManager
17+
18+
var body: some View {
19+
VStack(alignment: .leading, spacing: AppSpacing.small) {
20+
HStack {
21+
Image(systemName: "quote.bubble.fill")
22+
.foregroundColor(themeManager.current.primaryColor)
23+
.font(.title2)
24+
25+
Spacer()
26+
27+
Button(action: onDismiss) {
28+
Image(systemName: "xmark.circle.fill")
29+
.foregroundColor(themeManager.current.textSecondary)
30+
.font(.title3)
31+
}
32+
}
33+
34+
Text(quote.text)
35+
.font(AppFont.body)
36+
.foregroundColor(themeManager.current.textPrimary)
37+
.multilineTextAlignment(.leading)
38+
.fixedSize(horizontal: false, vertical: true)
39+
40+
HStack {
41+
Spacer()
42+
Text("\(quote.author)")
43+
.font(AppFont.caption)
44+
.foregroundColor(themeManager.current.textSecondary)
45+
.italic()
46+
}
47+
}
48+
.padding()
49+
.background(
50+
RoundedRectangle(cornerRadius: AppCornerRadius.card)
51+
.fill(themeManager.current.primaryColor.opacity(0.1))
52+
)
53+
.shadow(color: AppShadow.card.color, radius: AppShadow.card.radius, x: AppShadow.card.x, y: AppShadow.card.y)
54+
}
55+
}
56+
57+
#Preview {
58+
MotivationalQuoteView(
59+
quote: MotivationalQuote(
60+
text: "The greatest wealth is health.",
61+
author: "Ralph Waldo Emerson"
62+
)
63+
) {
64+
print("Dismissed")
65+
}
66+
}

LongevityMaster/Components/Me/SettingView.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@
66
//
77
import SwiftUI
88
import Dependencies
9+
import Sharing
910

1011
struct SettingView: View {
1112
@AppStorage("startWeekOnMonday") private var startWeekOnMonday: Bool = true
1213
@AppStorage("buttonSoundEnabled") private var buttonSoundEnabled: Bool = true
1314
@AppStorage("vibrateEnabled") private var vibrateEnabled: Bool = true
1415
@AppStorage("darkModeEnabled") private var darkModeEnabled: Bool = false
16+
@AppStorage("motivationalQuotesEnabled") private var motivationalQuotesEnabled: Bool = true
17+
@Shared(.appStorage("lastQuoteDismissedDate")) private var lastQuoteDismissedDate: Date? = nil
1518
@Dependency(\.themeManager) var themeManager
1619

1720
var body: some View {
@@ -43,6 +46,26 @@ struct SettingView: View {
4346
}
4447
.toggleStyle(SwitchToggleStyle(tint: themeManager.current.primaryColor))
4548
}
49+
settingsSection(title: "Motivation") {
50+
Toggle(isOn: $motivationalQuotesEnabled) {
51+
Text(String(localized: "Daily Motivational Quotes"))
52+
.font(AppFont.body)
53+
.foregroundColor(themeManager.current.textPrimary)
54+
}
55+
.toggleStyle(SwitchToggleStyle(tint: themeManager.current.primaryColor))
56+
57+
HStack {
58+
Text("Reset Today's Motivation")
59+
Spacer()
60+
61+
Button {
62+
$lastQuoteDismissedDate.withLock { $0 = nil }
63+
} label: {
64+
Text("Reset")
65+
}
66+
.appRectButtonStyle()
67+
}
68+
}
4669
settingsSection(title: "Appearance") {
4770
Toggle(isOn: $darkModeEnabled) {
4871
Text(String(localized: "Dark Mode"))

LongevityMaster/Components/Today/TodayView.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ struct TodayView: View {
1616
NavigationStack {
1717
ScrollView {
1818
VStack(spacing: .zero) {
19+
if viewModel.showMotivationalQuote, let quote = viewModel.currentQuote {
20+
MotivationalQuoteView(quote: quote) {
21+
viewModel.dismissMotivationalQuote()
22+
}
23+
.padding(.bottom, AppSpacing.medium)
24+
.padding(.horizontal, AppSpacing.medium)
25+
}
26+
1927
HStack {
2028
Image(systemName: "calendar")
2129
.font(.headline)
@@ -153,6 +161,9 @@ struct TodayView: View {
153161
}
154162
}
155163
}
164+
.onAppear {
165+
viewModel.updateMotivationalQuote()
166+
}
156167
}
157168
}
158169
}

LongevityMaster/Components/Today/TodayViewModel.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class TodayViewModel {
2828
var route: Route?
2929

3030
var isEditing: Bool = false
31+
var currentQuote: MotivationalQuote?
32+
var showMotivationalQuote: Bool = false
3133

3234
@ObservationIgnored
3335
@FetchAll(
@@ -61,6 +63,8 @@ class TodayViewModel {
6163
@Dependency(\.notificationService) private var notificationService
6264
@ObservationIgnored
6365
@Dependency(\.defaultDatabase) private var database
66+
@ObservationIgnored
67+
@Dependency(\.motivationalQuoteService) private var motivationalQuoteService
6468

6569

6670
var userCalendar: Calendar {
@@ -71,6 +75,24 @@ class TodayViewModel {
7175

7276
private var cancelable = Set<AnyCancellable>()
7377

78+
func updateMotivationalQuote() {
79+
withAnimation {
80+
if motivationalQuoteService.shouldShowQuote() {
81+
currentQuote = motivationalQuoteService.getRandomQuote()
82+
showMotivationalQuote = true
83+
} else {
84+
showMotivationalQuote = false
85+
}
86+
}
87+
}
88+
89+
func dismissMotivationalQuote() {
90+
withAnimation {
91+
motivationalQuoteService.dismissQuoteForToday()
92+
showMotivationalQuote = false
93+
}
94+
}
95+
7496
private func updateTodayHabits() -> [TodayHabit] {
7597
habits
7698
.compactMap { habit -> TodayHabit? in

0 commit comments

Comments
 (0)