Improve compilation times

multistore
Laurent 1 year ago
parent 8116c0598a
commit 92360d05dd
  1. 8
      PadelClub.xcodeproj/project.pbxproj
  2. 6
      PadelClub/Views/Components/StepperView.swift
  3. 37
      PadelClub/Views/Navigation/Toolbox/DebugSettingsView.swift
  4. 2
      PadelClub/Views/Subscription/Guard.swift
  5. 168
      PadelClub/Views/Subscription/SubscriptionView.swift
  6. 34
      PadelClub/Views/ViewModifiers/LoadingViewModifier.swift

@ -21,6 +21,7 @@
C45BAE3B2BC6DF10002EEC8A /* SyncedProducts.storekit in Resources */ = {isa = PBXBuildFile; fileRef = C45BAE3A2BC6DF10002EEC8A /* SyncedProducts.storekit */; };
C45BAE442BCA753E002EEC8A /* Purchase.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45BAE432BCA753E002EEC8A /* Purchase.swift */; };
C4607A7D2C04DDE2004CB781 /* APICallsListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4607A7C2C04DDE2004CB781 /* APICallsListView.swift */; };
C493B37E2C10AD3600862481 /* LoadingViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = C493B37D2C10AD3600862481 /* LoadingViewModifier.swift */; };
C49EF0192BD694290077B5AA /* PurchaseListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49EF0182BD694290077B5AA /* PurchaseListView.swift */; };
C49EF01B2BD6A1E80077B5AA /* URLs.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49EF01A2BD6A1E80077B5AA /* URLs.swift */; };
C49EF0262BD80AE80077B5AA /* SubscriptionInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49EF0252BD80AE80077B5AA /* SubscriptionInfoView.swift */; };
@ -303,6 +304,7 @@
C45BAE3A2BC6DF10002EEC8A /* SyncedProducts.storekit */ = {isa = PBXFileReference; lastKnownFileType = text; path = SyncedProducts.storekit; sourceTree = "<group>"; };
C45BAE432BCA753E002EEC8A /* Purchase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Purchase.swift; sourceTree = "<group>"; };
C4607A7C2C04DDE2004CB781 /* APICallsListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APICallsListView.swift; sourceTree = "<group>"; };
C493B37D2C10AD3600862481 /* LoadingViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingViewModifier.swift; sourceTree = "<group>"; };
C49EF0182BD694290077B5AA /* PurchaseListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PurchaseListView.swift; sourceTree = "<group>"; };
C49EF01A2BD6A1E80077B5AA /* URLs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLs.swift; sourceTree = "<group>"; };
C49EF0252BD80AE80077B5AA /* SubscriptionInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionInfoView.swift; sourceTree = "<group>"; };
@ -1228,6 +1230,7 @@
FFDDD40B2B93B2BB00C91A49 /* DeferredViewModifier.swift */,
FF5D0D752BB428B2005CB568 /* ListRowViewModifier.swift */,
FF4C7F012BBBD7150031B6A3 /* TabItemModifier.swift */,
C493B37D2C10AD3600862481 /* LoadingViewModifier.swift */,
);
path = ViewModifiers;
sourceTree = "<group>";
@ -1645,6 +1648,7 @@
FFF527D62BC6DDD000FF4EF2 /* MatchScheduleEditorView.swift in Sources */,
FFC91AF92BD6A09100B29808 /* FortuneWheelView.swift in Sources */,
FFF8ACD62B923960008466FA /* URL+Extensions.swift in Sources */,
C493B37E2C10AD3600862481 /* LoadingViewModifier.swift in Sources */,
FF089EBD2BB0287D00F0AEC7 /* PlayerView.swift in Sources */,
FF967D032BAEF0C000A9A3BD /* MatchDetailView.swift in Sources */,
FF967D0F2BAF63B000A9A3BD /* PlayerBlockView.swift in Sources */,
@ -1878,7 +1882,7 @@
);
MARKETING_VERSION = 0.1;
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20";
OTHER_SWIFT_FLAGS = "";
OTHER_SWIFT_FLAGS = "-Xfrontend -warn-long-function-bodies=5 -Xfrontend -warn-long-expression-type-checking=20 -Xfrontend -warn-long-function-bodies=50";
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
@ -1916,7 +1920,7 @@
);
MARKETING_VERSION = 0.1;
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20";
OTHER_SWIFT_FLAGS = "";
OTHER_SWIFT_FLAGS = "-Xfrontend -warn-long-function-bodies=5 -Xfrontend -warn-long-expression-type-checking=20 -Xfrontend -warn-long-function-bodies=50";
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;

@ -7,8 +7,6 @@
import SwiftUI
struct StepperView: View {
var title: String? = nil
@ -17,6 +15,8 @@ struct StepperView: View {
var minimum: Int? = nil
var maximum: Int? = nil
var countChanged: (() -> ())? = nil
var body: some View {
VStack {
HStack(spacing: 8) {
@ -75,6 +75,7 @@ struct StepperView: View {
return
}
self.count += step
self.countChanged?()
}
fileprivate func _subtract() {
@ -82,6 +83,7 @@ struct StepperView: View {
return
}
self.count -= step
self.countChanged?()
}
}

@ -11,15 +11,38 @@ import LeStorage
struct DebugSettingsView: View {
var body: some View {
List {
LabeledContent("UUID", value: Store.main.userId ?? "")
LabeledContent("User Name", value: Store.main.userName() ?? "")
LabeledContent("Token", value: Store.main.token() ?? "")
LabeledContent("Server", value: PListReader.readString(plist: "local", key: "server") ?? "")
LabeledContent("Synchronized", value:
"\(PListReader.readBool(plist: "local", key: "synchronized"))")
LabeledContent("CollectionsCanSynchronize", value: "\(Store.main.collectionsCanSynchronize)")
LabeledContent("UUID", value: self._userId)
LabeledContent("User Name", value: self._userName)
LabeledContent("Token", value: self._token)
LabeledContent("Server", value: self._server)
LabeledContent("Synchronized", value: self._synchronized)
LabeledContent("CollectionsCanSynchronize", value: self._canSynchronize)
}
}
fileprivate var _userId: String {
return Store.main.userId ?? ""
}
fileprivate var _userName: String {
return Store.main.userName() ?? ""
}
fileprivate var _token: String {
return Store.main.token() ?? ""
}
fileprivate var _server: String {
return PListReader.readString(plist: "local", key: "server") ?? ""
}
fileprivate var _synchronized: String {
return "\(PListReader.readBool(plist: "local", key: "synchronized"))"
}
fileprivate var _canSynchronize: String {
return "\(Store.main.collectionsCanSynchronize)"
}
}
#Preview {

@ -141,7 +141,7 @@ import LeStorage
var currentPlan: StoreItem? {
// #if DEBUG
return .monthlyUnlimited
// return .monthlyUnlimited
// #else
if let currentBestPlan = self.currentBestPlan, let plan = StoreItem(rawValue: currentBestPlan.productID) {
return plan

@ -43,12 +43,7 @@ class SubscriptionModel: ObservableObject, StoreDelegate {
self._computePrice()
}
}
@Published var quantity: Int = 1 {
didSet {
self._computePrice()
self.selectedProduct = self.products.first(where: { $0.id == StoreItem.unit.rawValue })
}
}
@Published var quantity: Int = 1
@Published var products: [Product] = []
@Published var totalPrice: String = ""
@ -63,6 +58,10 @@ class SubscriptionModel: ObservableObject, StoreDelegate {
}
}
func isSelected(product: Product) -> Bool {
return self.selectedProduct == product
}
func productsReceived(products: [Product]) {
self.isLoading = false
self.products = products
@ -137,60 +136,22 @@ struct SubscriptionView: View {
if self.showLackOfPlanMessage {
SubscriptionDetailView()
.clipShape(.rect(cornerRadius: 16.0))
.padding()
}
List {
if self.model.products.count > 0 {
Section {
ForEach(self.model.products) { product in
let isSelected = self.model.selectedProduct == product
ProductView(product: product,
quantity: self.$model.quantity,
selected: isSelected)
.foregroundStyle(.white)
.frame(maxWidth: .infinity)
.buttonStyle(.borderedProminent)
.tint(Color.master)
.listRowBackground(Color.clear)
.onTapGesture {
self.model.selectedProduct = product
}
}
} header: {
Text("Sélectionnez une offre")
}
ProductsSectionView(model: self.model)
if let product = self.model.selectedProduct {
Section {
Button {
if Store.main.userId != nil {
self._purchase()
} else {
self.showLoginView = true
}
self._purchaseIfPossible()
} label: {
HStack {
if self.isPurchasing {
Spacer()
ProgressView().tint(.white)
Spacer()
} else {
Text("Acheter")
Spacer()
Text(self.model.totalPrice)
}
}
.padding(8.0)
.fontWeight(.bold)
PurchaseLabelView(price: self.model.totalPrice, isPurchasing: self.isPurchasing)
}
.buttonStyle(.borderedProminent)
.tint(.orange)
@ -205,19 +166,8 @@ struct SubscriptionView: View {
}
} else {
if self.model.isLoading {
ProgressView()
} else {
HStack {
if let plan = Guard.main.currentPlan {
Image(systemName: plan.systemImage)
} else {
Image(systemName: "questionmark.diamond.fill")
}
Text("Il n'y a pas de produits à vous proposer")
}
}
NoProductView()
.isLoading(self.model.isLoading)
}
}
.listStyle(.grouped)
@ -225,13 +175,9 @@ struct SubscriptionView: View {
.background(.logoBackground)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
if self.isRestoring {
ProgressView()
} else {
Button("Restaurer") {
self._restore()
}
}
}.isLoading(self.isRestoring)
}
}
}
@ -241,6 +187,14 @@ struct SubscriptionView: View {
}
fileprivate func _purchaseIfPossible() {
if Store.main.userId != nil {
self._purchase()
} else {
self.showLoginView = true
}
}
fileprivate func _purchase() {
self.isPurchasing = true
@ -280,11 +234,69 @@ struct SubscriptionView: View {
}
fileprivate struct ProductsSectionView: View {
@ObservedObject var model: SubscriptionModel
var body: some View {
Section {
ForEach(self.model.products) { product in
ProductView(product: product,
model: self.model)
.onTapGesture {
self.model.selectedProduct = product
}
}
} header: {
Text("Sélectionnez une offre")
}
}
}
fileprivate struct PurchaseLabelView: View {
var price: String
var isPurchasing: Bool
var body: some View {
HStack(alignment: .center) {
if self.isPurchasing {
Spacer()
ProgressView().tint(Color.white)
Spacer()
} else {
Text("Acheter")
Spacer()
Text(self.price)
}
}
.padding(8.0)
.fontWeight(.bold)
}
}
fileprivate struct NoProductView: View {
var body: some View {
HStack {
if let plan = Guard.main.currentPlan {
Image(systemName: plan.systemImage)
} else {
Image(systemName: "questionmark.diamond.fill")
}
Text("Il n'y a pas de produits à vous proposer")
}
}
}
struct ProductView: View {
var product: Product
@Binding var quantity: Int
var selected: Bool
@ObservedObject var model: SubscriptionModel
// @Binding var quantity: Int
// var selected: Bool
var body: some View {
HStack {
@ -292,22 +304,26 @@ struct ProductView: View {
.font(.system(size: 36.0))
.foregroundColor(.orange)
VStack(alignment: .leading) {
Text(product.displayName)
Text(product.formattedPrice)
Text(self.product.displayName)
Text(self.product.formattedPrice)
.foregroundColor(.accentColor)
if self._isConsumable {
StepperView(count: self.$quantity, minimum: 1)
StepperView(count: self.$model.quantity, minimum: 1, countChanged: { self.model.selectedProduct = self.product })
.font(.callout).foregroundColor(.accentColor)
}
}
Spacer()
if self.selected {
if self.model.isSelected(product: self.product) {
Image(systemName: "checkmark")
.foregroundColor(.accentColor)
}
}
.contentShape(.rect)
.foregroundStyle(.white)
.frame(maxWidth: .infinity)
.buttonStyle(.borderedProminent)
.tint(Color.master)
.listRowBackground(Color.clear)
}
fileprivate var _item: StoreItem? {
@ -328,7 +344,7 @@ struct ProductView: View {
}
struct SubscriptionNoProductView: View {
fileprivate struct SubscriptionNoProductView: View {
@ObservedObject var model: SubscriptionModel
@ -356,14 +372,14 @@ struct SubscriptionNoProductView: View {
}
}
struct SubscriptionFooterView: View {
fileprivate struct SubscriptionFooterView: View {
var body: some View {
Text("Conditions d’utilisations concernant l’abonnement:\n- Le paiement sera facturé sur votre compte Apple.\n- L’abonnement est renouvelé automatiquement chaque mois, à moins d’avoir été désactivé au moins 24 heures avant la fin de la période de l’abonnement.\n- L’abonnement peut être géré par l’utilisateur et désactivé en allant dans les réglages de son compte après s’être abonné.\n- Le compte sera facturé pour le renouvellement de l'abonnement dans les 24 heures précédent la fin de la période d’abonnement.\n- Un abonnement en cours ne peut être annulé.\n- Toute partie inutilisée de l'offre gratuite, si souscrite, sera abandonnée lorsque l'utilisateur s'abonnera, dans les cas applicables.")
.padding(.top)
}
}
struct SubscriptionDetailView: View {
fileprivate struct SubscriptionDetailView: View {
var body: some View {
HStack {
@ -376,6 +392,8 @@ struct SubscriptionDetailView: View {
.padding()
.background(.orange)
.foregroundStyle(.black)
.clipShape(.rect(cornerRadius: 16.0))
.padding()
}
}

@ -0,0 +1,34 @@
//
// LoadingViewModifier.swift
// PadelClub
//
// Created by Laurent Morvillier on 05/06/2024.
//
import Foundation
import SwiftUI
struct LoadingViewModifier: ViewModifier {
let isLoading: Bool
let tintColor: Color?
func body(content: Content) -> some View {
if self.isLoading {
if let tintColor {
ProgressView().tint(tintColor)
} else {
ProgressView()
}
} else {
content
}
}
}
extension View {
func isLoading(_ isLoading: Bool, tintColor: Color? = nil) -> some View {
modifier(LoadingViewModifier(isLoading: isLoading, tintColor: tintColor))
}
}
Loading…
Cancel
Save