Skip to content

Commit

Permalink
feat: fetch product ids in advance
Browse files Browse the repository at this point in the history
  • Loading branch information
ha1f committed Jul 4, 2024
1 parent ba416ca commit 209dc6a
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,6 @@
}
}
}
},
"Restore a purchase" : {

},
"Status" : {
"localizations" : {
Expand Down
1 change: 1 addition & 0 deletions Packages/MatchCore/Sources/APIClient/Client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public struct APIClient: Sendable {
public var directMessageListContent: @Sendable (_ after: String?) -> AsyncThrowingStream<API.DirectMessageListContentQuery.Data, Error> = { _ in .finished() }
public var unsentDirectMessageListContent: @Sendable (_ after: String?) -> AsyncThrowingStream<API.UnsentDirectMessageListContentQuery.Data, Error> = { _ in .finished() }
public var profileExplorerPreview: @Sendable (_ targetUserId: String) -> AsyncThrowingStream<API.ProfileExplorerPreviewQuery.Data, Error> = { _ in .finished() }
public var productList: @Sendable () -> AsyncThrowingStream<API.ProductListQuery.Data, Error> = { .finished() }

public var recentMatch: @Sendable () -> AsyncThrowingStream<API.RecentMatchQuery.Data, Error> = { .finished() }
public var recentMatchContent: @Sendable (_ after: String?) -> AsyncThrowingStream<API.RecentMatchContentQuery.Data, Error> = { _ in .finished() }
Expand Down
4 changes: 4 additions & 0 deletions Packages/MatchCore/Sources/APIClient/LiveKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,10 @@ public extension APIClient {
let query = API.ProfileExplorerPreviewQuery(targetUserId: targetUserId)
return apolloClient.watch(query: query)
},
productList: {
let query = API.ProductListQuery()
return apolloClient.watch(query: query)
},
recentMatch: {
let query = API.RecentMatchQuery(first: 50)
return apolloClient.watch(query: query)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import API
import Foundation
import StoreKit

public struct MembershipProduct: Equatable {
public let appleProduct: StoreKit.Product

public var id: String {
appleProduct.id
}

let isRecommended: Bool
let isMostPopular: Bool

init(appleProduct: StoreKit.Product, data: API.ProductListQuery.Data.ProductList.MembershipProduct?) {
self.appleProduct = appleProduct
self.isRecommended = data?.isRecommended ?? false
self.isMostPopular = data?.isMostPopular ?? false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ public struct ProductPurchaseLogic {
public enum Action {
case onTask
case closeButtonTapped
case productsResponse(Result<[Product], Error>, Result<API.CurrentUserQuery.Data, Error>)
case productListResponse(Result<API.ProductListQuery.Data, Error>)
case productsResponse(Result<[MembershipProduct], Error>, Result<API.CurrentUserQuery.Data, Error>)
case content(ProductPurchaseContentLogic.Action)
case delegate(Delegate)

Expand All @@ -44,13 +45,32 @@ public struct ProductPurchaseLogic {
case .onTask:
analytics.logScreen(screenName: "ProductPurchase", of: self)

let ids = build.infoDictionary("PRODUCTS", for: [String].self)!
return .run { send in
for try await productList in api.productList() {
await send(.productListResponse(Result {
productList
}))
}
} catch: { error, send in
await send(.productListResponse(.failure(error)))
}
.cancellable(id: Cancel.products, cancelInFlight: true)

case let .productListResponse(.success(data)):
return .run { send in
for try await data in api.currentUser() {
let ids = data.productList.membershipProducts.map(\.id)
let mapping = data.productList.membershipProducts.reduce(
into: [String: API.ProductListQuery.Data.ProductList.MembershipProduct]()
) { dict, productData in
dict[productData.id] = productData
}
for try await userData in api.currentUser() {
await send(.productsResponse(Result {
try await store.products(ids)
}, .success(data)))
let products = try await store.products(ids)
return products.compactMap { product in
return MembershipProduct(appleProduct: product, data: mapping[product.id])
}
}, .success(userData)))
}
} catch: { error, send in
await send(.productsResponse(.success([]), .failure(error)))
Expand All @@ -74,7 +94,8 @@ public struct ProductPurchaseLogic {
state = .content(contentState)
return .none

case .productsResponse(.success, .failure),
case .productListResponse(.failure),
.productsResponse(.success, .failure),
.productsResponse(.failure, .success),
.productsResponse(.failure, .failure):
return .send(.delegate(.dismiss))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ public struct ProductPurchaseContentLogic {
public init() {}

public struct State: Equatable {
var selectProductID: String
var selectProductID: String?
let appAccountToken: UUID
public let products: [Product]
public let products: [MembershipProduct]
public var isActivityIndicatorVisible = false

public var rows: IdentifiedArrayOf<ProductPurchaseContentRowLogic.State> = []
Expand All @@ -22,18 +22,11 @@ public struct ProductPurchaseContentLogic {

public init(
appAccountToken: UUID,
products: [Product]
products: [MembershipProduct]
) {
self.appAccountToken = appAccountToken
self.products = products

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy/MM/dd"
let date = dateFormatter.date(from: "2024/06/23")!

let popularFlagProductId = Date.now >= date ? "6month" : "3month"

selectProductID = products.first(where: { $0.id.contains(popularFlagProductId) })!.id
selectProductID = products.first(where: { $0.isRecommended })?.appleProduct.id ?? products.first?.appleProduct.id
}
}

Expand Down Expand Up @@ -69,14 +62,15 @@ public struct ProductPurchaseContentLogic {

case .updateRows:
let uniqueElements = state.products
.sorted(by: { $0.price < $1.price })
.sorted(by: { $0.appleProduct.price < $1.appleProduct.price })
.map {
ProductPurchaseContentRowLogic.State(
id: $0.id,
price: $0.price,
currencyCode: $0.priceFormatStyle.currencyCode,
displayPrice: $0.id.contains("1week") ? nil : $0.displayPrice,
isSelected: $0.id == state.selectProductID
isSelected: $0.id == state.selectProductID,
isMostPopular: $0.isMostPopular
)
}
state.rows = IdentifiedArrayOf(uniqueElements: uniqueElements)
Expand All @@ -90,7 +84,7 @@ public struct ProductPurchaseContentLogic {
}

case .purchaseButtonTapped:
guard let product = state.products.first(where: { $0.id == state.selectProductID })
guard let product = state.products.first(where: { $0.appleProduct.id == state.selectProductID })
else { return .none }

state.isActivityIndicatorVisible = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,16 @@ public struct ProductPurchaseContentRowLogic {
price: Decimal,
currencyCode: String,
displayPrice: String?,
isSelected: Bool
isSelected: Bool,
isMostPopular: Bool
) {
self.id = id
period = Period.fromProductIdentifier(id: id)
self.price = price
self.currencyCode = currencyCode
self.displayPrice = displayPrice
self.isSelected = isSelected

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy/MM/dd"
let date = dateFormatter.date(from: "2024/06/23")!

let popularFlagProductId = Date.now >= date ? "6month" : "3month"

isMostPopularFlag = isSelected && id.contains(popularFlagProductId)
isMostPopularFlag = isSelected && isMostPopular
}
}

Expand Down

0 comments on commit 209dc6a

Please sign in to comment.