summaryrefslogtreecommitdiff
path: root/DomainDig/UsageCreditService.swift
diff options
context:
space:
mode:
Diffstat (limited to 'DomainDig/UsageCreditService.swift')
-rw-r--r--DomainDig/UsageCreditService.swift73
1 files changed, 73 insertions, 0 deletions
diff --git a/DomainDig/UsageCreditService.swift b/DomainDig/UsageCreditService.swift
new file mode 100644
index 0000000..48f40be
--- /dev/null
+++ b/DomainDig/UsageCreditService.swift
@@ -0,0 +1,73 @@
+import Foundation
+
+actor UsageCreditService {
+ static let shared = UsageCreditService()
+
+ private struct CreditLedger: Codable {
+ let appVersion: String
+ var remainingByFeature: [UsageCreditFeature: Int]
+ }
+
+ private let storageKey = "usageCredits.ledger"
+ private var ledger: CreditLedger
+
+ init(defaults: UserDefaults = .standard) {
+ if let data = defaults.data(forKey: storageKey),
+ let decoded = try? JSONDecoder().decode(CreditLedger.self, from: data),
+ decoded.appVersion == AppVersion.current {
+ ledger = decoded
+ } else {
+ ledger = Self.makeLedger()
+ if let data = try? JSONEncoder().encode(ledger) {
+ defaults.set(data, forKey: storageKey)
+ }
+ }
+ }
+
+ func status(for feature: UsageCreditFeature) -> UsageCreditStatus {
+ let total = feature.defaultAllowance
+ let remaining = ledger.remainingByFeature[feature] ?? total
+ return UsageCreditStatus(
+ feature: feature,
+ remaining: remaining,
+ total: total,
+ resetContext: "Resets with app version \(ledger.appVersion)"
+ )
+ }
+
+ func allStatuses() -> [UsageCreditStatus] {
+ UsageCreditFeature.allCases.map { status(for: $0) }
+ }
+
+ func canUse(_ feature: UsageCreditFeature) -> Bool {
+ status(for: feature).remaining > 0
+ }
+
+ @discardableResult
+ func consume(_ feature: UsageCreditFeature) -> UsageCreditStatus {
+ let current = ledger.remainingByFeature[feature] ?? feature.defaultAllowance
+ ledger.remainingByFeature[feature] = max(0, current - 1)
+ persist()
+ return status(for: feature)
+ }
+
+ func resetForCurrentVersion() {
+ ledger = Self.makeLedger()
+ persist()
+ }
+
+ private static func makeLedger() -> CreditLedger {
+ CreditLedger(
+ appVersion: AppVersion.current,
+ remainingByFeature: Dictionary(
+ uniqueKeysWithValues: UsageCreditFeature.allCases.map { ($0, $0.defaultAllowance) }
+ )
+ )
+ }
+
+ private func persist(defaults: UserDefaults = .standard) {
+ if let data = try? JSONEncoder().encode(ledger) {
+ defaults.set(data, forKey: storageKey)
+ }
+ }
+}