Skip to content

Commit edac81e

Browse files
authored
Moving to unified store (#30)
* moving to unified store * readding tests * Update swift.yml * removing github files
1 parent f1dbaf7 commit edac81e

File tree

11 files changed

+97
-99
lines changed

11 files changed

+97
-99
lines changed

.github/FUNDING.yml

Lines changed: 0 additions & 3 deletions
This file was deleted.

.github/workflows/swift.yml

Lines changed: 0 additions & 19 deletions
This file was deleted.

LICENSE

Lines changed: 0 additions & 45 deletions
This file was deleted.

Package.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
// swift-tools-version:5.7
1+
// swift-tools-version:5.9
22
import PackageDescription
33

44
let package = Package(
5-
name: "StoreKitPlus",
5+
name: "Storefront",
66
platforms: [
7-
.iOS(.v15), .macOS(.v12), .tvOS(.v15), .watchOS(.v8)
7+
.iOS(.v17), .macOS(.v14), .tvOS(.v17), .watchOS(.v10)
88
],
99
products: [
10-
.library(name: "StoreKitPlus", targets: ["StoreKitPlus"])
10+
.library(name: "Storefront", targets: ["Storefront"])
1111
],
1212
targets: [
13-
.target(name: "StoreKitPlus"),
14-
.testTarget(name: "StoreKitPlusTests", dependencies: ["StoreKitPlus"])
13+
.target(name: "Storefront"),
14+
.testTarget(name: "StorefrontTests", dependencies: ["Storefront"])
1515
]
1616
)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
## StoreKitPlus
1+
## Storefront
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import StoreKit
2+
import SwiftUI
3+
4+
/// A manager class that handles app review prompts based on user engagement points
5+
@Observable public class ReviewManager {
6+
/// The current engagement points accumulated by the user
7+
private(set) var engagementPoints: Int
8+
9+
/// The thresholds at which review prompts will be triggered
10+
private let thresholds: [Int]
11+
12+
/// UserDefaults keys
13+
private enum Keys {
14+
static let highestThresholdReached = "highestThresholdReached"
15+
static let currentPoints = "currentPoints"
16+
}
17+
18+
/// UserDefaults instance
19+
private let defaults: UserDefaults
20+
21+
/// Initialize the ReviewManager with custom thresholds
22+
init(thresholds: [Int] = [10, 50, 100], defaults: UserDefaults = .standard) {
23+
self.thresholds = thresholds.sorted()
24+
self.defaults = defaults
25+
self.engagementPoints = defaults.integer(forKey: Keys.currentPoints)
26+
}
27+
28+
/// Add engagement points and check if a review should be requested
29+
/// - Parameter points: The number of points to add
30+
/// - Returns: True if a review prompt should be shown
31+
@MainActor
32+
public func add(engagementPoints points: Int) -> Bool {
33+
engagementPoints += points
34+
defaults.set(engagementPoints, forKey: Keys.currentPoints)
35+
36+
let highestThresholdReached = defaults.integer(forKey: Keys.highestThresholdReached)
37+
38+
// Check if we should show a review prompt
39+
if let nextThreshold = thresholds.first(where: { $0 > highestThresholdReached }),
40+
engagementPoints >= nextThreshold {
41+
42+
defaults.set(nextThreshold, forKey: Keys.highestThresholdReached)
43+
return true
44+
}
45+
46+
return false
47+
}
48+
49+
/// Reset the engagement points and review history
50+
public func reset() {
51+
engagementPoints = 0
52+
defaults.set(0, forKey: Keys.currentPoints)
53+
defaults.set(0, forKey: Keys.highestThresholdReached)
54+
}
55+
}
56+
57+
58+
extension EnvironmentValues {
59+
@Entry public var reviewManager = ReviewManager(thresholds: [1, 10, 30], defaults: .standard)
60+
}
Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ public enum StoreError: Error {
99
case failedVerification
1010
}
1111

12-
@MainActor public final class Store: ObservableObject {
12+
@MainActor @Observable
13+
public final class Store {
1314
public enum PurchaseFinishedAction {
1415
case dismissStore
1516
case noAction
@@ -18,19 +19,19 @@ public enum StoreError: Error {
1819

1920
private let productIdentifiers: Set<String>
2021

21-
@Published public private(set) var nonConsumables: [Product]
22-
@Published public private(set) var subscriptions: [Product]
22+
public private(set) var nonConsumables: [Product]
23+
public private(set) var subscriptions: [Product]
2324

24-
@Published public private(set) var purchasedNonConsumables: [Product] = []
25-
@Published public private(set) var purchasedSubscriptions: [Product] = []
25+
public private(set) var purchasedNonConsumables: [Product] = []
26+
public private(set) var purchasedSubscriptions: [Product] = []
2627

27-
@Published public private(set) var purchasedProductIdentifiers: Set<String>
28+
public private(set) var purchasedProductIdentifiers: Set<String>
2829

29-
@Published public private(set) var purchaseError: (any LocalizedError)?
30+
public private(set) var purchaseError: (any LocalizedError)?
3031

31-
///
32-
private var lastLoadError: Error?
32+
public private(set) var purchaseInProgress: Bool
3333

34+
private var lastLoadError: Error?
3435
private var productLoadingTask: Task<Void, Never>?
3536
private var transactionUpdatesTask: Task<Void, Never>?
3637
private var statusUpdatesTask: Task<Void, Never>?
@@ -44,6 +45,8 @@ public enum StoreError: Error {
4445
self.purchasedProductIdentifiers = Set(purchasedProductsArray ?? [])
4546
print("Persisted Purchased Products:", Set(purchasedProductsArray ?? []))
4647

48+
self.purchaseInProgress = false
49+
4750
nonConsumables = []
4851
subscriptions = []
4952

@@ -59,10 +62,12 @@ public enum StoreError: Error {
5962
}
6063

6164
deinit {
62-
productLoadingTask?.cancel()
63-
transactionUpdatesTask?.cancel()
64-
statusUpdatesTask?.cancel()
65-
storefrontUpdatesTask?.cancel()
65+
Task { @MainActor [weak self] in
66+
self?.productLoadingTask?.cancel()
67+
self?.transactionUpdatesTask?.cancel()
68+
self?.statusUpdatesTask?.cancel()
69+
self?.storefrontUpdatesTask?.cancel()
70+
}
6671
}
6772

6873
@MainActor
@@ -112,6 +117,7 @@ public enum StoreError: Error {
112117
}
113118

114119
public func purchase(option product: Product) async -> PurchaseFinishedAction {
120+
purchaseInProgress = true
115121
let action: PurchaseFinishedAction
116122
do {
117123
let result = try await product.purchase()
@@ -144,6 +150,7 @@ public enum StoreError: Error {
144150
print("Purchase failed: \(error)")
145151
action = .noAction
146152
}
153+
purchaseInProgress = false
147154
return action
148155
}
149156

File renamed without changes.

Sources/StoreKitPlus/SubscriptionSavings.swift renamed to Sources/Storefront/SubscriptionSavings.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public struct SubscriptionSavings {
1919
@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
2020
public func formattedPrice(for subscription: Product) -> String {
2121
let currency = granularPrice.formatted(subscription.priceFormatStyle)
22-
let period = granularPricePeriod.formatted(subscription.subscriptionPeriodUnitFormatStyle)
22+
let period = granularPricePeriod.formatted(subscription.subscriptionPeriodUnitFormatStyle).lowercased()
2323
return "\(currency)/\(period)"
2424
}
2525
}

Tests/StoreKitPlusTests/StoreKitPlusTests.swift

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)