diff --git a/Info.plist b/Info.plist new file mode 100644 index 0000000..52e4cf6 --- /dev/null +++ b/Info.plist @@ -0,0 +1,58 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + CFBundleDisplayName + $(PRODUCT_NAME) + LSRequiresIPhoneOS + + NSCameraUsageDescription + SelfieCam needs camera access to display your live selfie preview, apply real-time filters and ring light effects, capture high-quality photos, and enable advanced features like Center Stage auto-framing. + NSMicrophoneUsageDescription + SelfieCam needs microphone access for the camera framework to initialize properly. Audio is not recorded. + NSPhotoLibraryAddUsageDescription + SelfieCam needs photo library access to automatically save your captured photos to your device, making them available in the Photos app and other compatible applications. + UILaunchStoryboardName + LaunchScreen + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + + UIApplicationSupportsIndirectInputEvents + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + RevenueCatAPIKey + $(REVENUECAT_API_KEY) + + diff --git a/SelfieCam.xcodeproj/project.pbxproj b/SelfieCam.xcodeproj/project.pbxproj index 698ad18..10fdf24 100644 --- a/SelfieCam.xcodeproj/project.pbxproj +++ b/SelfieCam.xcodeproj/project.pbxproj @@ -435,20 +435,8 @@ CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)"; ENABLE_PREVIEWS = YES; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_AppClipDomain = "$(APPCLIP_DOMAIN)"; - INFOPLIST_KEY_AppGroupIdentifier = "$(APP_GROUP_IDENTIFIER)"; - INFOPLIST_KEY_CFBundleDisplayName = "$(PRODUCT_NAME)"; - INFOPLIST_KEY_CloudKitContainerIdentifier = "$(CLOUDKIT_CONTAINER_IDENTIFIER)"; - INFOPLIST_KEY_NSCameraUsageDescription = "SelfieCam needs camera access to display your live selfie preview, apply real-time filters and ring light effects, capture high-quality photos, and enable advanced features like Center Stage auto-framing."; - INFOPLIST_KEY_NSMicrophoneUsageDescription = "SelfieCam needs microphone access for the camera framework to initialize properly. Audio is not recorded."; - INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "SelfieCam needs photo library access to automatically save your captured photos to your device, making them available in the Photos app and other compatible applications."; - INFOPLIST_KEY_PublicAppName = "$(PRODUCT_NAME)"; - INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; - INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 18.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -477,20 +465,8 @@ CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)"; ENABLE_PREVIEWS = YES; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_AppClipDomain = "$(APPCLIP_DOMAIN)"; - INFOPLIST_KEY_AppGroupIdentifier = "$(APP_GROUP_IDENTIFIER)"; - INFOPLIST_KEY_CFBundleDisplayName = "$(PRODUCT_NAME)"; - INFOPLIST_KEY_CloudKitContainerIdentifier = "$(CLOUDKIT_CONTAINER_IDENTIFIER)"; - INFOPLIST_KEY_NSCameraUsageDescription = "SelfieCam needs camera access to display your live selfie preview, apply real-time filters and ring light effects, capture high-quality photos, and enable advanced features like Center Stage auto-framing."; - INFOPLIST_KEY_NSMicrophoneUsageDescription = "SelfieCam needs microphone access for the camera framework to initialize properly. Audio is not recorded."; - INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "SelfieCam needs photo library access to automatically save your captured photos to your device, making them available in the Photos app and other compatible applications."; - INFOPLIST_KEY_PublicAppName = "$(PRODUCT_NAME)"; - INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; - INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 18.6; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", diff --git a/SelfieCam/Configuration/Debug.xcconfig b/SelfieCam/Configuration/Debug.xcconfig index 8464628..1ebe5f8 100644 --- a/SelfieCam/Configuration/Debug.xcconfig +++ b/SelfieCam/Configuration/Debug.xcconfig @@ -2,3 +2,4 @@ // Configuration for Debug builds #include "Base.xcconfig" +#include "Secrets.debug.xcconfig" diff --git a/SelfieCam/Configuration/Release.xcconfig b/SelfieCam/Configuration/Release.xcconfig index 28a3a5a..cb6b039 100644 --- a/SelfieCam/Configuration/Release.xcconfig +++ b/SelfieCam/Configuration/Release.xcconfig @@ -2,3 +2,4 @@ // Configuration for Release builds #include "Base.xcconfig" +#include "Secrets.release.xcconfig" diff --git a/SelfieCam/Configuration/Secrets.swift.template b/SelfieCam/Configuration/Secrets.swift.template deleted file mode 100644 index 3bd60b9..0000000 --- a/SelfieCam/Configuration/Secrets.swift.template +++ /dev/null @@ -1,20 +0,0 @@ -// Secrets.swift -// ⚠️ DO NOT COMMIT THE ACTUAL Secrets.swift FILE TO VERSION CONTROL -// -// Copy this file to Secrets.swift and fill in your actual values. -// Secrets.swift is gitignored. - -import Foundation - -enum Secrets { - /// RevenueCat API Key - /// - Debug: Use your test/sandbox API key (starts with "test_") - /// - Release: Use your production API key (starts with "appl_") - static let revenueCatAPIKey: String = { - #if DEBUG - return "test_YOUR_TEST_KEY_HERE" - #else - return "appl_YOUR_PRODUCTION_KEY_HERE" - #endif - }() -} diff --git a/SelfieCam/Configuration/Secrets.xcconfig.template b/SelfieCam/Configuration/Secrets.xcconfig.template deleted file mode 100644 index 1b7b2f4..0000000 --- a/SelfieCam/Configuration/Secrets.xcconfig.template +++ /dev/null @@ -1,22 +0,0 @@ -// Secrets.xcconfig.template -// -// INSTRUCTIONS: -// This project uses separate secrets files for Debug and Release builds: -// -// 1. Copy this file to "Secrets.debug.xcconfig" for development/testing -// - Use your RevenueCat TEST API key (starts with test_) -// - Sandbox purchases, no real money charged -// -// 2. Copy this file to "Secrets.release.xcconfig" for App Store builds -// - Use your RevenueCat PRODUCTION API key (starts with appl_) -// - Real purchases, charges real money -// -// 3. NEVER commit the actual secrets files to version control -// -// The actual Secrets.*.xcconfig files are gitignored for security. - -// RevenueCat API Key -// Get this from: RevenueCat Dashboard > Project Settings > API Keys -// - Test key: Use "Public App-Specific API Key" from test environment -// - Production key: Use "Public App-Specific API Key" from production environment -REVENUECAT_API_KEY = your_revenuecat_api_key_here diff --git a/SelfieCam/Shared/Premium/PremiumManager.swift b/SelfieCam/Shared/Premium/PremiumManager.swift index 1519049..2598d60 100644 --- a/SelfieCam/Shared/Premium/PremiumManager.swift +++ b/SelfieCam/Shared/Premium/PremiumManager.swift @@ -16,10 +16,30 @@ final class PremiumManager: PremiumManaging { /// Reads the RevenueCat API key from the Secrets configuration file private static var apiKey: String { - let key = Secrets.revenueCatAPIKey - guard !key.isEmpty, key != "YOUR_REVENUECAT_API_KEY_HERE" else { + let key = (Bundle.main.object(forInfoDictionaryKey: "RevenueCatAPIKey") as? String) ?? "" + let placeholders = [ + "", + "YOUR_REVENUECAT_API_KEY_HERE", + "test_YOUR_TEST_KEY_HERE", + "appl_YOUR_PRODUCTION_KEY_HERE" + ] + #if DEBUG + let prefix = key.split(separator: "_").first.map(String.init) ?? "missing" + let keyStatus = key.isEmpty ? "empty" : "present" + print("ℹ️ [PremiumManager] RevenueCatAPIKey \(keyStatus), prefix=\(prefix)") + if let infoPath = Bundle.main.path(forResource: "Info", ofType: "plist"), + let infoDict = NSDictionary(contentsOfFile: infoPath) as? [String: Any] { + let rawValue = infoDict["RevenueCatAPIKey"] as? String ?? "" + let rawPrefix = rawValue.split(separator: "_").first.map(String.init) ?? "missing" + let rawStatus = rawValue.isEmpty ? "empty" : "present" + print("ℹ️ [PremiumManager] Info.plist RevenueCatAPIKey \(rawStatus), prefix=\(rawPrefix)") + } else { + print("ℹ️ [PremiumManager] Info.plist not found in bundle") + } + #endif + guard !placeholders.contains(key) else { #if DEBUG - print("⚠️ [PremiumManager] RevenueCat API key not configured. See Configuration/Secrets.swift.template") + print("⚠️ [PremiumManager] RevenueCat API key not configured. Check Secrets.debug.xcconfig / Secrets.release.xcconfig") #endif return "" }