Refactor premium settings to use Bedrock PremiumGate utility
- Replace inline premium checks with PremiumGate.get/canSet - Define premium values as static sets for timer options, colors, quality - Cleaner, more consistent premium gating pattern - Values preserved when user unsubscribes (restored on re-subscribe)
This commit is contained in:
parent
459755be98
commit
53170a1de4
@ -133,15 +133,10 @@ final class SettingsViewModel: RingLightConfigurable {
|
||||
var lightColorId: String {
|
||||
get {
|
||||
let storedId = _cachedLightColorId ?? cloudSync.data.lightColorId
|
||||
// Return default free color if not premium and stored color is premium
|
||||
if !isPremiumUnlocked && Self.premiumColorIds.contains(storedId) {
|
||||
return Self.defaultFreeColorId
|
||||
}
|
||||
return storedId
|
||||
return PremiumGate.get(storedId, default: Self.defaultFreeColorId, premiumValues: Self.premiumColorIds, isPremium: isPremiumUnlocked)
|
||||
}
|
||||
set {
|
||||
// Block premium color selection for free users
|
||||
guard isPremiumUnlocked || !Self.premiumColorIds.contains(newValue) else { return }
|
||||
guard PremiumGate.canSet(newValue, premiumValues: Self.premiumColorIds, isPremium: isPremiumUnlocked) else { return }
|
||||
_cachedLightColorId = newValue
|
||||
updateSettings { $0.lightColorId = newValue }
|
||||
}
|
||||
@ -161,8 +156,7 @@ final class SettingsViewModel: RingLightConfigurable {
|
||||
)
|
||||
}
|
||||
set {
|
||||
// Block custom color changes for non-premium users
|
||||
guard isPremiumUnlocked else { return }
|
||||
guard PremiumGate.canSet(isPremium: isPremiumUnlocked) else { return }
|
||||
_cachedCustomColor = newValue
|
||||
let rgb = CustomColorRGB(from: newValue)
|
||||
debouncedSave(key: "customColor") {
|
||||
@ -184,18 +178,18 @@ final class SettingsViewModel: RingLightConfigurable {
|
||||
|
||||
/// Whether the camera preview is flipped to show a true mirror (PREMIUM)
|
||||
var isMirrorFlipped: Bool {
|
||||
get { isPremiumUnlocked ? cloudSync.data.isMirrorFlipped : false }
|
||||
get { PremiumGate.get(cloudSync.data.isMirrorFlipped, default: false, isPremium: isPremiumUnlocked) }
|
||||
set {
|
||||
guard isPremiumUnlocked else { return }
|
||||
guard PremiumGate.canSet(isPremium: isPremiumUnlocked) else { return }
|
||||
updateSettings { $0.isMirrorFlipped = newValue }
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether skin smoothing filter is enabled (PREMIUM)
|
||||
var isSkinSmoothingEnabled: Bool {
|
||||
get { isPremiumUnlocked ? cloudSync.data.isSkinSmoothingEnabled : false }
|
||||
get { PremiumGate.get(cloudSync.data.isSkinSmoothingEnabled, default: false, isPremium: isPremiumUnlocked) }
|
||||
set {
|
||||
guard isPremiumUnlocked else { return }
|
||||
guard PremiumGate.canSet(isPremium: isPremiumUnlocked) else { return }
|
||||
updateSettings { $0.isSkinSmoothingEnabled = newValue }
|
||||
}
|
||||
}
|
||||
@ -223,21 +217,17 @@ final class SettingsViewModel: RingLightConfigurable {
|
||||
/// Convenience property for border width (same as ringSize)
|
||||
var borderWidth: CGFloat { ringSize }
|
||||
|
||||
/// Premium timer options that require subscription
|
||||
private static let premiumTimerOptions: Set<TimerOption> = [.five, .ten]
|
||||
|
||||
/// Selected timer option (5s and 10s are PREMIUM)
|
||||
var selectedTimer: TimerOption {
|
||||
get {
|
||||
let stored = TimerOption(rawValue: cloudSync.data.selectedTimerRaw) ?? .off
|
||||
// Free users limited to off or 3s
|
||||
if !isPremiumUnlocked && (stored == .five || stored == .ten) {
|
||||
return .three
|
||||
}
|
||||
return stored
|
||||
return PremiumGate.get(stored, default: .three, premiumValues: Self.premiumTimerOptions, isPremium: isPremiumUnlocked)
|
||||
}
|
||||
set {
|
||||
// Block premium timer options for free users
|
||||
if !isPremiumUnlocked && (newValue == .five || newValue == .ten) {
|
||||
return
|
||||
}
|
||||
guard PremiumGate.canSet(newValue, premiumValues: Self.premiumTimerOptions, isPremium: isPremiumUnlocked) else { return }
|
||||
updateSettings { $0.selectedTimerRaw = newValue.rawValue }
|
||||
}
|
||||
}
|
||||
@ -256,37 +246,36 @@ final class SettingsViewModel: RingLightConfigurable {
|
||||
|
||||
/// Whether flash is synced with ring light color (PREMIUM)
|
||||
var isFlashSyncedWithRingLight: Bool {
|
||||
get { isPremiumUnlocked ? cloudSync.data.isFlashSyncedWithRingLight : false }
|
||||
get { PremiumGate.get(cloudSync.data.isFlashSyncedWithRingLight, default: false, isPremium: isPremiumUnlocked) }
|
||||
set {
|
||||
guard isPremiumUnlocked else { return }
|
||||
guard PremiumGate.canSet(isPremium: isPremiumUnlocked) else { return }
|
||||
updateSettings { $0.isFlashSyncedWithRingLight = newValue }
|
||||
}
|
||||
}
|
||||
|
||||
/// HDR mode setting (PREMIUM)
|
||||
var hdrMode: CameraHDRMode {
|
||||
get { isPremiumUnlocked ? (CameraHDRMode(rawValue: cloudSync.data.hdrModeRaw) ?? .off) : .off }
|
||||
get {
|
||||
let stored = CameraHDRMode(rawValue: cloudSync.data.hdrModeRaw) ?? .off
|
||||
return PremiumGate.get(stored, default: .off, isPremium: isPremiumUnlocked)
|
||||
}
|
||||
set {
|
||||
guard isPremiumUnlocked else { return }
|
||||
guard PremiumGate.canSet(isPremium: isPremiumUnlocked) else { return }
|
||||
updateSettings { $0.hdrModeRaw = newValue.rawValue }
|
||||
}
|
||||
}
|
||||
|
||||
/// Premium photo quality options that require subscription
|
||||
private static let premiumPhotoQualities: Set<PhotoQuality> = [.high]
|
||||
|
||||
/// Photo quality setting (high is PREMIUM)
|
||||
var photoQuality: PhotoQuality {
|
||||
get {
|
||||
let stored = PhotoQuality(rawValue: cloudSync.data.photoQualityRaw) ?? PhotoQuality.high
|
||||
// Free users limited to medium quality
|
||||
if !isPremiumUnlocked && stored == PhotoQuality.high {
|
||||
return PhotoQuality.medium
|
||||
}
|
||||
return stored
|
||||
return PremiumGate.get(stored, default: .medium, premiumValues: Self.premiumPhotoQualities, isPremium: isPremiumUnlocked)
|
||||
}
|
||||
set {
|
||||
// Block premium quality option for free users
|
||||
if !isPremiumUnlocked && newValue == PhotoQuality.high {
|
||||
return
|
||||
}
|
||||
guard PremiumGate.canSet(newValue, premiumValues: Self.premiumPhotoQualities, isPremium: isPremiumUnlocked) else { return }
|
||||
updateSettings { $0.photoQualityRaw = newValue.rawValue }
|
||||
}
|
||||
}
|
||||
@ -316,9 +305,9 @@ final class SettingsViewModel: RingLightConfigurable {
|
||||
|
||||
/// Whether Center Stage is enabled (PREMIUM)
|
||||
var isCenterStageEnabled: Bool {
|
||||
get { isPremiumUnlocked ? cloudSync.data.isCenterStageEnabled : false }
|
||||
get { PremiumGate.get(cloudSync.data.isCenterStageEnabled, default: false, isPremium: isPremiumUnlocked) }
|
||||
set {
|
||||
guard isPremiumUnlocked else { return }
|
||||
guard PremiumGate.canSet(isPremium: isPremiumUnlocked) else { return }
|
||||
updateSettings { $0.isCenterStageEnabled = newValue }
|
||||
}
|
||||
}
|
||||
@ -348,7 +337,7 @@ final class SettingsViewModel: RingLightConfigurable {
|
||||
|
||||
/// Sets the custom color and selects it (PREMIUM)
|
||||
func selectCustomColor(_ color: Color) {
|
||||
guard isPremiumUnlocked else { return }
|
||||
guard PremiumGate.canSet(isPremium: isPremiumUnlocked) else { return }
|
||||
customColor = color
|
||||
lightColorId = RingLightColor.customId
|
||||
}
|
||||
@ -360,9 +349,9 @@ final class SettingsViewModel: RingLightConfigurable {
|
||||
|
||||
/// Whether iCloud sync is enabled (PREMIUM)
|
||||
var iCloudEnabled: Bool {
|
||||
get { isPremiumUnlocked ? cloudSync.iCloudEnabled : false }
|
||||
get { PremiumGate.get(cloudSync.iCloudEnabled, default: false, isPremium: isPremiumUnlocked) }
|
||||
set {
|
||||
guard isPremiumUnlocked else { return }
|
||||
guard PremiumGate.canSet(isPremium: isPremiumUnlocked) else { return }
|
||||
cloudSync.iCloudEnabled = newValue
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user