Add PremiumGate utility for generic freemium settings gating
- Add PremiumGate enum with get/canSet helpers for premium-gated settings - Supports entirely premium settings (returns default for free users) - Supports partial premium (only specific values require premium) - Preserves stored values so re-subscribing restores previous choices
This commit is contained in:
parent
40d1285c38
commit
b5a5c62fa8
108
Sources/Bedrock/Premium/PremiumGate.swift
Normal file
108
Sources/Bedrock/Premium/PremiumGate.swift
Normal file
@ -0,0 +1,108 @@
|
||||
//
|
||||
// PremiumGate.swift
|
||||
// Bedrock
|
||||
//
|
||||
// Utility for premium-gating settings values in freemium apps.
|
||||
// Provides a consistent pattern for handling premium vs free user access.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Utility enum for premium-gating settings values.
|
||||
///
|
||||
/// Use this to create consistent premium/free behavior across your app's settings.
|
||||
/// Values are preserved in storage but defaults are returned for non-premium users,
|
||||
/// so users don't lose their settings if they unsubscribe and later re-subscribe.
|
||||
///
|
||||
/// ## Usage
|
||||
///
|
||||
/// For boolean settings that are entirely premium:
|
||||
/// ```swift
|
||||
/// var isSkinSmoothingEnabled: Bool {
|
||||
/// get { PremiumGate.get(cloudSync.data.isSkinSmoothingEnabled, default: false, isPremium: isPremiumUnlocked) }
|
||||
/// set { guard PremiumGate.canSet(isPremium: isPremiumUnlocked) else { return }
|
||||
/// updateSettings { $0.isSkinSmoothingEnabled = newValue }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// For settings where only some values are premium:
|
||||
/// ```swift
|
||||
/// var selectedTimer: TimerOption {
|
||||
/// get {
|
||||
/// let stored = TimerOption(rawValue: cloudSync.data.selectedTimerRaw) ?? .three
|
||||
/// return PremiumGate.get(stored, default: .three, premiumValues: [.five, .ten], isPremium: isPremiumUnlocked)
|
||||
/// }
|
||||
/// set {
|
||||
/// guard PremiumGate.canSet(newValue, premiumValues: [.five, .ten], isPremium: isPremiumUnlocked) else { return }
|
||||
/// updateSettings { $0.selectedTimerRaw = newValue.rawValue }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
public enum PremiumGate {
|
||||
|
||||
// MARK: - Getters
|
||||
|
||||
/// Returns the stored value if premium, otherwise returns the default.
|
||||
///
|
||||
/// Use for settings that are entirely premium-only (e.g., skin smoothing, mirror flip).
|
||||
/// - Parameters:
|
||||
/// - stored: The value stored in settings
|
||||
/// - defaultValue: The value to return for non-premium users
|
||||
/// - isPremium: Whether the user has premium access
|
||||
/// - Returns: The stored value if premium, otherwise the default
|
||||
public static func get<T>(
|
||||
_ stored: T,
|
||||
default defaultValue: T,
|
||||
isPremium: Bool
|
||||
) -> T {
|
||||
isPremium ? stored : defaultValue
|
||||
}
|
||||
|
||||
/// Returns the stored value if premium or if it's not a premium value, otherwise returns the default.
|
||||
///
|
||||
/// Use for settings where only some values are premium (e.g., timer options, quality levels).
|
||||
/// - Parameters:
|
||||
/// - stored: The value stored in settings
|
||||
/// - defaultValue: The value to return for non-premium users when they have a premium value stored
|
||||
/// - premiumValues: The set of values that require premium access
|
||||
/// - isPremium: Whether the user has premium access
|
||||
/// - Returns: The stored value if premium or not a premium value, otherwise the default
|
||||
public static func get<T: Hashable>(
|
||||
_ stored: T,
|
||||
default defaultValue: T,
|
||||
premiumValues: Set<T>,
|
||||
isPremium: Bool
|
||||
) -> T {
|
||||
if !isPremium && premiumValues.contains(stored) {
|
||||
return defaultValue
|
||||
}
|
||||
return stored
|
||||
}
|
||||
|
||||
// MARK: - Setters
|
||||
|
||||
/// Checks if setting any value should be allowed (for entirely premium settings).
|
||||
///
|
||||
/// - Parameter isPremium: Whether the user has premium access
|
||||
/// - Returns: True if the user can modify this setting
|
||||
public static func canSet(isPremium: Bool) -> Bool {
|
||||
isPremium
|
||||
}
|
||||
|
||||
/// Checks if setting a specific value should be allowed.
|
||||
///
|
||||
/// Use for settings where only some values are premium.
|
||||
/// - Parameters:
|
||||
/// - value: The value the user wants to set
|
||||
/// - premiumValues: The set of values that require premium access
|
||||
/// - isPremium: Whether the user has premium access
|
||||
/// - Returns: True if the user can set this specific value
|
||||
public static func canSet<T: Hashable>(
|
||||
_ value: T,
|
||||
premiumValues: Set<T>,
|
||||
isPremium: Bool
|
||||
) -> Bool {
|
||||
isPremium || !premiumValues.contains(value)
|
||||
}
|
||||
}
|
||||
@ -1 +1,10 @@
|
||||
{"sourceLanguage":"en","strings":{},"version":"1.0"}
|
||||
{
|
||||
"sourceLanguage" : "en",
|
||||
"strings" : {
|
||||
"%lld%%" : {
|
||||
"comment" : "A text label showing the current volume percentage. The argument is the volume as a percentage (0.0 to 1.0).",
|
||||
"isCommentAutoGenerated" : true
|
||||
}
|
||||
},
|
||||
"version" : "1.1"
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user