Skip to content

Commit 2e676d4

Browse files
authored
Merge pull request #11 from banghuazhao/bz/feat/Refactor-style
Refactor style
2 parents f1c3628 + 1e30317 commit 2e676d4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+5243
-1166
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,6 @@ fastlane/*.env
8484

8585
iOSInjectionProject/
8686

87-
.env
87+
.env
88+
89+
LongevityMaster/Config/Release.xcconfig

LongevityMaster.xcodeproj/project.pbxproj

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@
174174
knownRegions = (
175175
en,
176176
Base,
177+
"zh-Hans",
177178
);
178179
mainGroup = 993A34192DEB1031002CEA39;
179180
minimizedProjectReferenceProxies = 1;
@@ -239,6 +240,8 @@
239240
/* Begin XCBuildConfiguration section */
240241
993A34462DEB1032002CEA39 /* Debug */ = {
241242
isa = XCBuildConfiguration;
243+
baseConfigurationReferenceAnchor = 993A34242DEB1031002CEA39 /* LongevityMaster */;
244+
baseConfigurationReferenceRelativePath = Config/Debug.xcconfig;
242245
buildSettings = {
243246
ALWAYS_SEARCH_USER_PATHS = NO;
244247
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
@@ -296,12 +299,15 @@
296299
ONLY_ACTIVE_ARCH = YES;
297300
SDKROOT = iphoneos;
298301
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
302+
SWIFT_EMIT_LOC_STRINGS = YES;
299303
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
300304
};
301305
name = Debug;
302306
};
303307
993A34472DEB1032002CEA39 /* Release */ = {
304308
isa = XCBuildConfiguration;
309+
baseConfigurationReferenceAnchor = 993A34242DEB1031002CEA39 /* LongevityMaster */;
310+
baseConfigurationReferenceRelativePath = Config/Release.xcconfig;
305311
buildSettings = {
306312
ALWAYS_SEARCH_USER_PATHS = NO;
307313
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
@@ -352,17 +358,20 @@
352358
MTL_FAST_MATH = YES;
353359
SDKROOT = iphoneos;
354360
SWIFT_COMPILATION_MODE = wholemodule;
361+
SWIFT_EMIT_LOC_STRINGS = YES;
355362
VALIDATE_PRODUCT = YES;
356363
};
357364
name = Release;
358365
};
359366
993A34492DEB1032002CEA39 /* Debug */ = {
360367
isa = XCBuildConfiguration;
368+
baseConfigurationReferenceAnchor = 993A34242DEB1031002CEA39 /* LongevityMaster */;
369+
baseConfigurationReferenceRelativePath = Config/Debug.xcconfig;
361370
buildSettings = {
362371
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
363372
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
364373
CODE_SIGN_STYLE = Automatic;
365-
CURRENT_PROJECT_VERSION = 1.0.0.1;
374+
CURRENT_PROJECT_VERSION = 1.0.0.2;
366375
DEVELOPMENT_ASSET_PATHS = "\"LongevityMaster/Preview Content\"";
367376
DEVELOPMENT_TEAM = F694X76A5X;
368377
ENABLE_PREVIEWS = YES;
@@ -374,6 +383,7 @@
374383
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
375384
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
376385
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
386+
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
377387
LD_RUNPATH_SEARCH_PATHS = (
378388
"$(inherited)",
379389
"@executable_path/Frameworks",
@@ -389,11 +399,13 @@
389399
};
390400
993A344A2DEB1032002CEA39 /* Release */ = {
391401
isa = XCBuildConfiguration;
402+
baseConfigurationReferenceAnchor = 993A34242DEB1031002CEA39 /* LongevityMaster */;
403+
baseConfigurationReferenceRelativePath = Config/Release.xcconfig;
392404
buildSettings = {
393405
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
394406
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
395407
CODE_SIGN_STYLE = Automatic;
396-
CURRENT_PROJECT_VERSION = 1.0.0.1;
408+
CURRENT_PROJECT_VERSION = 1.0.0.2;
397409
DEVELOPMENT_ASSET_PATHS = "\"LongevityMaster/Preview Content\"";
398410
DEVELOPMENT_TEAM = F694X76A5X;
399411
ENABLE_PREVIEWS = YES;
@@ -405,6 +417,7 @@
405417
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
406418
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
407419
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
420+
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
408421
LD_RUNPATH_SEARCH_PATHS = (
409422
"$(inherited)",
410423
"@executable_path/Frameworks",

LongevityMaster/App/LongevityMasterApp.swift

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,15 @@ import GoogleMobileAds
1010
@main
1111
struct LongevityMasterApp: App {
1212
@AppStorage("darkModeEnabled") private var darkModeEnabled: Bool = false
13+
@AppStorage("hasCompletedOnboarding") private var hasCompletedOnboarding: Bool = false
1314
@Dependency(\.achievementService) private var achievementService
15+
@Dependency(\.themeManager) private var themeManager
1416
@Dependency(\.purchaseManager) private var purchaseManager
1517
@StateObject private var openAd = OpenAd()
1618
@Environment(\.scenePhase) private var scenePhase
1719
@State private var didShowOpenAd = false
1820

1921
init() {
20-
// let tabBarAppearance = UITabBarAppearance()
21-
// tabBarAppearance.configureWithOpaqueBackground()
22-
// tabBarAppearance.backgroundColor = UIColor.systemBackground
23-
// UITabBar.appearance().standardAppearance = tabBarAppearance
24-
// if #available(iOS 15.0, *) {
25-
// UITabBar.appearance().scrollEdgeAppearance = tabBarAppearance
26-
// }
2722
MobileAds.shared.start(completionHandler: nil)
2823
prepareDependencies {
2924
$0.defaultDatabase = try! appDatabase()
@@ -59,38 +54,49 @@ struct LongevityMasterApp: App {
5954
openAd.appHasEnterBackgroundBefore = true
6055
}
6156
}
62-
.task {
63-
await purchaseManager.checkPurchased()
64-
}
6557
}
6658
}
6759

6860
var tabView: some View {
69-
TabView {
70-
TodayView()
71-
.tabItem {
61+
ZStack {
62+
TabView {
63+
Tab {
64+
TodayView()
65+
.onAppear {
66+
AdManager.requestATTPermission(with: 3)
67+
}
68+
} label: {
7269
Label("Today", systemImage: "calendar")
7370
}
74-
.onAppear {
75-
AdManager.requestATTPermission(with: 1)
76-
}
77-
78-
HabitsListView()
79-
.tabItem {
71+
72+
Tab {
73+
HabitsListView()
74+
} label: {
8075
Label("Habits", systemImage: "list.bullet")
8176
}
82-
83-
RatingView()
84-
.tabItem {
77+
78+
Tab {
79+
RatingView()
80+
} label: {
8581
Label("Rating", systemImage: "star.fill")
8682
}
87-
88-
MeView()
89-
.tabItem {
83+
84+
Tab {
85+
MeView()
86+
.onAppear {
87+
AdManager.requestATTPermission(with: 1)
88+
}
89+
} label: {
9090
Label("Me", systemImage: "person.fill")
9191
}
92-
.onAppear {
93-
AdManager.requestATTPermission(with: 1)
92+
}
93+
.background(themeManager.current.background)
94+
.tint(themeManager.current.primaryColor)
95+
96+
// Onboarding overlay
97+
Color.clear
98+
.fullScreenCover(isPresented: .constant(!hasCompletedOnboarding)) {
99+
OnboardingView()
94100
}
95101
}
96102
}

LongevityMaster/Assets.xcassets/AppIcon.appiconset/Contents.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"images" : [
33
{
4-
"filename" : "ChatGPT Image Jul 3, 2025, 09_15_47 PM.png",
4+
"filename" : "appIcon.png",
55
"idiom" : "universal",
66
"platform" : "ios",
77
"size" : "1024x1024"

LongevityMaster/Components/Achievements/AchievementPopupView.swift

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ struct AchievementPopupView: View {
4343
}
4444

4545
// Achievement title
46-
Text("🎉 Achievement Unlocked! 🎉")
46+
Text(String(localized: "🎉 Achievement Unlocked! 🎉"))
4747
.font(.title2)
4848
.fontWeight(.bold)
4949
.foregroundColor(.primary)
@@ -66,9 +66,36 @@ struct AchievementPopupView: View {
6666
}
6767
.opacity(animationOpacity)
6868

69+
// Share button
70+
ShareLink(
71+
item: createAchievementShareText(achievement),
72+
subject: Text(String(localized: "Achievement Unlocked!")),
73+
message: Text(String(localized: "Check out this achievement I unlocked in LongevityMaster!"))
74+
) {
75+
HStack {
76+
Image(systemName: "square.and.arrow.up")
77+
Text(String(localized: "Share Achievement"))
78+
}
79+
.font(.headline)
80+
.fontWeight(.semibold)
81+
.foregroundColor(.white)
82+
.frame(maxWidth: .infinity)
83+
.padding()
84+
.background(
85+
LinearGradient(
86+
gradient: Gradient(colors: [Color.green, Color.blue]),
87+
startPoint: .leading,
88+
endPoint: .trailing
89+
)
90+
)
91+
.cornerRadius(12)
92+
}
93+
.opacity(animationOpacity)
94+
.padding(.horizontal)
95+
6996
// Continue button
7097
Button(action: dismissPopup) {
71-
Text("Continue")
98+
Text(String(localized: "Continue"))
7299
.font(.headline)
73100
.fontWeight(.semibold)
74101
.foregroundColor(.white)
@@ -108,7 +135,7 @@ struct AchievementPopupView: View {
108135

109136
private func startAnimation() {
110137
// Play haptic feedback
111-
Haptics.vibrateIfEnabled()
138+
Haptics.shared.vibrateIfEnabled()
112139

113140
// Animate popup appearance
114141
withAnimation(.spring(response: 0.6, dampingFraction: 0.8)) {
@@ -134,6 +161,26 @@ struct AchievementPopupView: View {
134161
isPresented = false
135162
}
136163
}
164+
165+
private func createAchievementShareText(_ achievement: Achievement) -> String {
166+
let appName = "LongevityMaster"
167+
let appStoreURL = "https://apps.apple.com/app/id\(Constants.AppID.longevityMasterID)"
168+
169+
var shareText = "🎉 Achievement Unlocked! 🎉\n\n"
170+
shareText += "🏆 \(achievement.title)\n"
171+
shareText += "📝 \(achievement.description)\n\n"
172+
173+
if let unlockDate = achievement.unlockedDate {
174+
let formatter = DateFormatter()
175+
formatter.dateStyle = .medium
176+
shareText += "📅 Unlocked on \(formatter.string(from: unlockDate))\n\n"
177+
}
178+
179+
shareText += "💪 Keep building healthy habits with \(appName)!\n"
180+
shareText += "📱 Download: \(appStoreURL)"
181+
182+
return shareText
183+
}
137184
}
138185

139186
// Confetti effect view
@@ -226,4 +273,4 @@ struct ConfettiParticleView: View {
226273
),
227274
isPresented: .constant(true)
228275
)
229-
}
276+
}

LongevityMaster/Components/Achievements/AchievementsView.swift

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,34 @@ class AchievementsViewModel {
163163

164164
return min(Double(totalCheckIns) / Double(targetCount), 1.0)
165165
}
166+
167+
func createAchievementShareText(_ achievement: Achievement) -> String {
168+
let appName = "LongevityMaster"
169+
let appStoreURL = "https://apps.apple.com/app/id\(Constants.AppID.longevityMasterID)"
170+
171+
var shareText = "🎉 Achievement Unlocked! 🎉\n\n"
172+
shareText += "🏆 \(achievement.title)\n"
173+
shareText += "📝 \(achievement.description)\n\n"
174+
175+
if let unlockDate = achievement.unlockedDate {
176+
let formatter = DateFormatter()
177+
formatter.dateStyle = .medium
178+
shareText += "📅 Unlocked on \(formatter.string(from: unlockDate))\n\n"
179+
}
180+
181+
shareText += "💪 Keep building healthy habits with \(appName)!\n"
182+
shareText += "📱 Download: \(appStoreURL)"
183+
184+
return shareText
185+
}
166186
}
167187

168188
struct AchievementsView: View {
169189
@State private var viewModel = AchievementsViewModel()
170190
@State private var selectedTab = 0
171191

192+
@Dependency(\.themeManager) var themeManager
193+
172194
var body: some View {
173195
NavigationStack {
174196
VStack(spacing: 0) {
@@ -234,13 +256,16 @@ struct AchievementsView: View {
234256
ForEach(achievementsToShow) { achievement in
235257
AchievementRowView(
236258
achievement: achievement,
237-
progress: viewModel.getProgress(for: achievement)
259+
progress: viewModel.getProgress(for: achievement),
260+
shareText: viewModel.createAchievementShareText(achievement)
238261
)
239262
}
240263
}
241264
.padding(.horizontal)
242265
}
243266
}
267+
.appBackground()
268+
.tint(themeManager.current.primaryColor)
244269
.navigationTitle("Achievements")
245270
.navigationBarTitleDisplayMode(.inline)
246271
}
@@ -263,6 +288,7 @@ struct AchievementsView: View {
263288
struct AchievementRowView: View {
264289
let achievement: Achievement
265290
let progress: Double
291+
let shareText: String
266292

267293
var body: some View {
268294
HStack(spacing: 16) {
@@ -299,9 +325,21 @@ struct AchievementRowView: View {
299325
Spacer()
300326

301327
if achievement.isUnlocked {
302-
Image(systemName: "checkmark.circle.fill")
303-
.foregroundColor(.green)
304-
.font(.title3)
328+
HStack(spacing: 8) {
329+
ShareLink(
330+
item: shareText,
331+
subject: Text("Achievement Unlocked!"),
332+
message: Text("Check out this achievement I unlocked in LongevityMaster!")
333+
) {
334+
Image(systemName: "square.and.arrow.up")
335+
.foregroundColor(.blue)
336+
.font(.caption)
337+
}
338+
339+
Image(systemName: "checkmark.circle.fill")
340+
.foregroundColor(.green)
341+
.font(.title3)
342+
}
305343
}
306344
}
307345

0 commit comments

Comments
 (0)