blob: 48f40be37bca5396be2ddbc8d8538c9d9b4c5a5e (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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)
}
}
}
|