Compare commits
No commits in common. "19e17b7051fcf6064f78d17dde9bd78d29aefb26" and "815b91f6caca4d8fc3f60f07a030570aad2b5207" have entirely different histories.
19e17b7051
...
815b91f6ca
@ -28,7 +28,6 @@ struct ContentView: View {
|
|||||||
EquatableView(content: CameraContainerView(
|
EquatableView(content: CameraContainerView(
|
||||||
settings: settings,
|
settings: settings,
|
||||||
sessionKey: cameraSessionKey,
|
sessionKey: cameraSessionKey,
|
||||||
cameraPosition: settings.cameraPosition,
|
|
||||||
onImageCaptured: { image in
|
onImageCaptured: { image in
|
||||||
handlePhotoCaptured(image)
|
handlePhotoCaptured(image)
|
||||||
}
|
}
|
||||||
@ -80,10 +79,6 @@ struct ContentView: View {
|
|||||||
settings.flashMode = settings.isRingLightEnabled ? .on : .off
|
settings.flashMode = settings.isRingLightEnabled ? .on : .off
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onChange(of: settings.cameraPosition) { _, _ in
|
|
||||||
// Force camera session recreation when camera position changes
|
|
||||||
cameraSessionKey = UUID()
|
|
||||||
}
|
|
||||||
.sheet(isPresented: $showSettings) {
|
.sheet(isPresented: $showSettings) {
|
||||||
SettingsView(viewModel: settings, showPaywall: $showPaywall)
|
SettingsView(viewModel: settings, showPaywall: $showPaywall)
|
||||||
}
|
}
|
||||||
@ -167,7 +162,6 @@ struct ContentView: View {
|
|||||||
struct CameraContainerView: View, Equatable {
|
struct CameraContainerView: View, Equatable {
|
||||||
let settings: SettingsViewModel
|
let settings: SettingsViewModel
|
||||||
let sessionKey: UUID
|
let sessionKey: UUID
|
||||||
let cameraPosition: CameraPosition
|
|
||||||
let onImageCaptured: (UIImage) -> Void
|
let onImageCaptured: (UIImage) -> Void
|
||||||
|
|
||||||
// Only compare sessionKey for equality - ignore settings and callback changes
|
// Only compare sessionKey for equality - ignore settings and callback changes
|
||||||
@ -176,7 +170,7 @@ struct CameraContainerView: View, Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
let _ = Design.debugLog("CameraContainerView body evaluated - sessionKey: \(sessionKey), position: \(cameraPosition)")
|
let _ = Design.debugLog("CameraContainerView body evaluated - sessionKey: \(sessionKey)")
|
||||||
MCamera()
|
MCamera()
|
||||||
.setCameraScreen { cameraManager, namespace, closeAction in
|
.setCameraScreen { cameraManager, namespace, closeAction in
|
||||||
CustomCameraScreen(
|
CustomCameraScreen(
|
||||||
@ -188,7 +182,9 @@ struct CameraContainerView: View, Equatable {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
.setCapturedMediaScreen(nil)
|
.setCapturedMediaScreen(nil)
|
||||||
.setCameraPosition(cameraPosition)
|
// Use front camera as default for selfie app - don't read from settings here
|
||||||
|
// to avoid triggering @Observable tracking which breaks the camera
|
||||||
|
.setCameraPosition(.front)
|
||||||
.startSession()
|
.startSession()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -770,7 +770,10 @@ struct SettingsView: View {
|
|||||||
SettingsToggle(
|
SettingsToggle(
|
||||||
title: "Enable Debug Premium",
|
title: "Enable Debug Premium",
|
||||||
subtitle: "Unlock all premium features for testing",
|
subtitle: "Unlock all premium features for testing",
|
||||||
isOn: $viewModel.isDebugPremiumEnabled
|
isOn: Binding(
|
||||||
|
get: { viewModel.premiumManager.isDebugPremiumToggleEnabled },
|
||||||
|
set: { viewModel.premiumManager.isDebugPremiumToggleEnabled = $0 }
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.tint(Color.Status.warning)
|
.tint(Color.Status.warning)
|
||||||
// Icon Generator
|
// Icon Generator
|
||||||
|
|||||||
@ -85,20 +85,12 @@ final class SettingsViewModel: RingLightConfigurable {
|
|||||||
static let defaultRingSize: CGFloat = 40
|
static let defaultRingSize: CGFloat = 40
|
||||||
|
|
||||||
// MARK: - Premium Manager
|
// MARK: - Premium Manager
|
||||||
|
|
||||||
/// Premium manager for checking subscription status
|
/// Premium manager for checking subscription status
|
||||||
@ObservationIgnored private let premiumManager = PremiumManager()
|
private let premiumManager = PremiumManager()
|
||||||
|
|
||||||
/// Whether the user has premium access (stored property for proper UI updates)
|
/// Whether the user has premium access
|
||||||
private var _isPremiumUnlocked: Bool = false
|
var isPremiumUnlocked: Bool { premiumManager.isPremiumUnlocked }
|
||||||
|
|
||||||
/// Whether the user has premium access (observable for UI updates)
|
|
||||||
var isPremiumUnlocked: Bool {
|
|
||||||
get { _isPremiumUnlocked }
|
|
||||||
set {
|
|
||||||
_isPremiumUnlocked = newValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Cloud Sync Manager
|
// MARK: - Cloud Sync Manager
|
||||||
|
|
||||||
@ -342,71 +334,6 @@ final class SettingsViewModel: RingLightConfigurable {
|
|||||||
var isCustomColorSelected: Bool {
|
var isCustomColorSelected: Bool {
|
||||||
lightColorId == RingLightColor.customId
|
lightColorId == RingLightColor.customId
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Debug Premium Toggle
|
|
||||||
|
|
||||||
/// Debug premium toggle for testing (DEBUG builds only)
|
|
||||||
var isDebugPremiumEnabled: Bool {
|
|
||||||
get { premiumManager.isDebugPremiumToggleEnabled }
|
|
||||||
set {
|
|
||||||
let wasPremium = premiumManager.isDebugPremiumToggleEnabled
|
|
||||||
premiumManager.isDebugPremiumToggleEnabled = newValue
|
|
||||||
|
|
||||||
// Update premium status for UI refresh
|
|
||||||
isPremiumUnlocked = premiumManager.isPremiumUnlocked
|
|
||||||
|
|
||||||
// Reset premium settings when toggling OFF
|
|
||||||
if wasPremium && !newValue {
|
|
||||||
resetPremiumSettingsToDefaults()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reset premium-only settings to their free defaults when debug premium is disabled
|
|
||||||
private func resetPremiumSettingsToDefaults() {
|
|
||||||
// Clear cached values that depend on premium status
|
|
||||||
_cachedRingSize = nil
|
|
||||||
_cachedLightColorId = nil
|
|
||||||
_cachedCustomColor = nil
|
|
||||||
|
|
||||||
// Reset premium settings to defaults (bypass premium gates for direct reset)
|
|
||||||
updateSettings { settings in
|
|
||||||
if settings.lightColorId != Self.defaultFreeColorId {
|
|
||||||
settings.lightColorId = Self.defaultFreeColorId
|
|
||||||
}
|
|
||||||
|
|
||||||
if settings.isMirrorFlipped {
|
|
||||||
settings.isMirrorFlipped = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if settings.isSkinSmoothingEnabled {
|
|
||||||
settings.isSkinSmoothingEnabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if settings.isFlashSyncedWithRingLight {
|
|
||||||
settings.isFlashSyncedWithRingLight = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if settings.hdrModeRaw != CameraHDRMode.off.rawValue {
|
|
||||||
settings.hdrModeRaw = CameraHDRMode.off.rawValue
|
|
||||||
}
|
|
||||||
|
|
||||||
if settings.photoQualityRaw != PhotoQuality.medium.rawValue {
|
|
||||||
settings.photoQualityRaw = PhotoQuality.medium.rawValue
|
|
||||||
}
|
|
||||||
|
|
||||||
if settings.selectedTimerRaw != TimerOption.three.rawValue {
|
|
||||||
settings.selectedTimerRaw = TimerOption.three.rawValue
|
|
||||||
}
|
|
||||||
|
|
||||||
if settings.isCenterStageEnabled {
|
|
||||||
settings.isCenterStageEnabled = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Force sync to ensure changes are saved
|
|
||||||
forceSync()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the custom color and selects it (PREMIUM)
|
/// Sets the custom color and selects it (PREMIUM)
|
||||||
func selectCustomColor(_ color: Color) {
|
func selectCustomColor(_ color: Color) {
|
||||||
@ -436,10 +363,8 @@ final class SettingsViewModel: RingLightConfigurable {
|
|||||||
var hasCompletedInitialSync: Bool { cloudSync.hasCompletedInitialSync }
|
var hasCompletedInitialSync: Bool { cloudSync.hasCompletedInitialSync }
|
||||||
|
|
||||||
// MARK: - Initialization
|
// MARK: - Initialization
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
// Initialize premium status
|
|
||||||
_isPremiumUnlocked = premiumManager.isPremiumUnlocked
|
|
||||||
// CloudSyncManager handles syncing automatically
|
// CloudSyncManager handles syncing automatically
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@ final class PremiumManager: PremiumManaging {
|
|||||||
// MARK: - Debug Override
|
// MARK: - Debug Override
|
||||||
|
|
||||||
/// Debug premium toggle stored in UserDefaults (only available in DEBUG builds)
|
/// Debug premium toggle stored in UserDefaults (only available in DEBUG builds)
|
||||||
@AppStorage("debugPremiumEnabled") @ObservationIgnored private var debugPremiumEnabled = false
|
@AppStorage("debugPremiumEnabled") private var debugPremiumEnabled = false
|
||||||
|
|
||||||
/// Check if debug premium is enabled via UserDefaults toggle or environment variable.
|
/// Check if debug premium is enabled via UserDefaults toggle or environment variable.
|
||||||
/// The toggle in Settings > Debug takes precedence over environment variables.
|
/// The toggle in Settings > Debug takes precedence over environment variables.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user