add support backup

multistore
Razmig Sarkissian 1 year ago
parent e4dd5077bf
commit f5ee4e72f3
  1. 17
      PadelClub.xcodeproj/project.pbxproj
  2. 6
      PadelClub/PadelClubApp.swift
  3. 10
      PadelClub/Utils/ContactManager.swift
  4. 4
      PadelClub/Views/Navigation/Agenda/ActivityView.swift
  5. 4
      PadelClub/Views/Navigation/Toolbox/ToolboxView.swift
  6. 87
      PadelClub/Views/Shared/SupportButtonView.swift
  7. 17
      PadelClub/Views/Subscription/Guard.swift

@ -170,6 +170,7 @@
FF8F264F2BAE0B9600650388 /* MatchTypeSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF8F264E2BAE0B9600650388 /* MatchTypeSelectionView.swift */; }; FF8F264F2BAE0B9600650388 /* MatchTypeSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF8F264E2BAE0B9600650388 /* MatchTypeSelectionView.swift */; };
FF8F26512BAE0BAD00650388 /* MatchFormatPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF8F26502BAE0BAD00650388 /* MatchFormatPickerView.swift */; }; FF8F26512BAE0BAD00650388 /* MatchFormatPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF8F26502BAE0BAD00650388 /* MatchFormatPickerView.swift */; };
FF8F26542BAE1E4400650388 /* TableStructureView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF8F26532BAE1E4400650388 /* TableStructureView.swift */; }; FF8F26542BAE1E4400650388 /* TableStructureView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF8F26532BAE1E4400650388 /* TableStructureView.swift */; };
FF92660D2C241CE0002361A4 /* Zip in Frameworks */ = {isa = PBXBuildFile; productRef = FF92660C2C241CE0002361A4 /* Zip */; };
FF9267F82BCE78C70080F940 /* CashierView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF9267F72BCE78C70080F940 /* CashierView.swift */; }; FF9267F82BCE78C70080F940 /* CashierView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF9267F72BCE78C70080F940 /* CashierView.swift */; };
FF9267FA2BCE78EC0080F940 /* CashierDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF9267F92BCE78EB0080F940 /* CashierDetailView.swift */; }; FF9267FA2BCE78EC0080F940 /* CashierDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF9267F92BCE78EB0080F940 /* CashierDetailView.swift */; };
FF9267FC2BCE84870080F940 /* PlayerPayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF9267FB2BCE84870080F940 /* PlayerPayView.swift */; }; FF9267FC2BCE84870080F940 /* PlayerPayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF9267FB2BCE84870080F940 /* PlayerPayView.swift */; };
@ -591,6 +592,7 @@
files = ( files = (
FFE2D2D52C216B5000D0C7BE /* FirebaseCrashlytics in Frameworks */, FFE2D2D52C216B5000D0C7BE /* FirebaseCrashlytics in Frameworks */,
FFCFBFFE2BBBE86600B82851 /* Algorithms in Frameworks */, FFCFBFFE2BBBE86600B82851 /* Algorithms in Frameworks */,
FF92660D2C241CE0002361A4 /* Zip in Frameworks */,
C49EF0392BDFF4600077B5AA /* LeStorage.framework in Frameworks */, C49EF0392BDFF4600077B5AA /* LeStorage.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -1340,6 +1342,7 @@
packageProductDependencies = ( packageProductDependencies = (
FFCFBFFD2BBBE86600B82851 /* Algorithms */, FFCFBFFD2BBBE86600B82851 /* Algorithms */,
FFE2D2D42C216B5000D0C7BE /* FirebaseCrashlytics */, FFE2D2D42C216B5000D0C7BE /* FirebaseCrashlytics */,
FF92660C2C241CE0002361A4 /* Zip */,
); );
productName = PadelClub; productName = PadelClub;
productReference = C425D3FD2B6D249D002A7B48 /* PadelClub.app */; productReference = C425D3FD2B6D249D002A7B48 /* PadelClub.app */;
@ -1417,6 +1420,7 @@
packageReferences = ( packageReferences = (
FF4C7F052BBBE6B90031B6A3 /* XCRemoteSwiftPackageReference "swift-algorithms" */, FF4C7F052BBBE6B90031B6A3 /* XCRemoteSwiftPackageReference "swift-algorithms" */,
FFE2D2D32C216B5000D0C7BE /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, FFE2D2D32C216B5000D0C7BE /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
FF92660B2C241CE0002361A4 /* XCRemoteSwiftPackageReference "Zip" */,
); );
productRefGroup = C425D3FE2B6D249D002A7B48 /* Products */; productRefGroup = C425D3FE2B6D249D002A7B48 /* Products */;
projectDirPath = ""; projectDirPath = "";
@ -2096,6 +2100,14 @@
minimumVersion = 1.2.0; minimumVersion = 1.2.0;
}; };
}; };
FF92660B2C241CE0002361A4 /* XCRemoteSwiftPackageReference "Zip" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/marmelroy/Zip";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 2.1.2;
};
};
FFE2D2D32C216B5000D0C7BE /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = { FFE2D2D32C216B5000D0C7BE /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
isa = XCRemoteSwiftPackageReference; isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/firebase/firebase-ios-sdk.git"; repositoryURL = "https://github.com/firebase/firebase-ios-sdk.git";
@ -2107,6 +2119,11 @@
/* End XCRemoteSwiftPackageReference section */ /* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */ /* Begin XCSwiftPackageProductDependency section */
FF92660C2C241CE0002361A4 /* Zip */ = {
isa = XCSwiftPackageProductDependency;
package = FF92660B2C241CE0002361A4 /* XCRemoteSwiftPackageReference "Zip" */;
productName = Zip;
};
FFCFBFFD2BBBE86600B82851 /* Algorithms */ = { FFCFBFFD2BBBE86600B82851 /* Algorithms */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
package = FF4C7F052BBBE6B90031B6A3 /* XCRemoteSwiftPackageReference "swift-algorithms" */; package = FF4C7F052BBBE6B90031B6A3 /* XCRemoteSwiftPackageReference "swift-algorithms" */;

@ -52,12 +52,6 @@ struct PadelClubApp: App {
Logger.log("doc dir = \(docURL.absoluteString)") Logger.log("doc dir = \(docURL.absoluteString)")
UserDefaults.standard.set(false, forKey: "_UIConstraintBasedLayoutLogUnsatisfiable") UserDefaults.standard.set(false, forKey: "_UIConstraintBasedLayoutLogUnsatisfiable")
} }
static func openMail(emailTo: String = "support@padelclub.app", subject: String = "Support Padel Club") {
if let url = URL(string: "mailto:\(emailTo)?subject=\(subject)"), UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}
} }
class AppDelegate: NSObject, UIApplicationDelegate { class AppDelegate: NSObject, UIApplicationDelegate {

@ -151,6 +151,7 @@ struct MailComposeView: UIViewControllerRepresentable {
let bccRecipients: [String]? let bccRecipients: [String]?
let body: String? let body: String?
let subject: String? let subject: String?
var attachmentURL: URL?
let completion: Completion? let completion: Completion?
func makeUIViewController(context: Context) -> UIViewController { func makeUIViewController(context: Context) -> UIViewController {
@ -163,6 +164,15 @@ struct MailComposeView: UIViewControllerRepresentable {
controller.mailComposeDelegate = context.coordinator controller.mailComposeDelegate = context.coordinator
controller.setToRecipients(recipients) controller.setToRecipients(recipients)
controller.setBccRecipients(bccRecipients) controller.setBccRecipients(bccRecipients)
if let attachmentURL {
do {
let attachmentData = try Data(contentsOf: attachmentURL)
controller.addAttachmentData(attachmentData, mimeType: "application/zip", fileName: "backup.zip")
} catch {
print("Could not attach file: \(error)")
}
}
if let body { if let body {
controller.setMessageBody(body, isHTML: false) controller.setMessageBody(body, isHTML: false)
} }

@ -327,9 +327,7 @@ struct ActivityView: View {
} }
} }
FooterButtonView("Besoin d'aide ? Un problème ? Contactez-nous !") { SupportButtonView(contentIsUnavailable: true)
PadelClubApp.openMail()
}
} }
} }

@ -19,9 +19,7 @@ struct ToolboxView: View {
Section { Section {
Text("Version de l'application").badge(PadelClubApp.appVersion) Text("Version de l'application").badge(PadelClubApp.appVersion)
Button("Contactez-nous") { SupportButtonView(contentIsUnavailable: false)
PadelClubApp.openMail()
}
} }
#if DEBUG #if DEBUG

@ -6,18 +6,95 @@
// //
import SwiftUI import SwiftUI
import LeStorage
import Zip
extension URL: Identifiable {
public var id: String {
return self.absoluteString
}
}
struct SupportButtonView: View { struct SupportButtonView: View {
let contentIsUnavailable: Bool
@State private var sentError: ContactManagerError? = nil
@State private var zipFilePath: URL?
@EnvironmentObject var networkMonitor: NetworkMonitor
var messageSentFailed: Binding<Bool> {
Binding {
sentError != nil
} set: { newValue in
if newValue == false {
sentError = nil
}
}
}
var body: some View { var body: some View {
FooterButtonView("Besoin d'aide ? Un problème ? Contactez-nous !") { Group {
openMail() if contentIsUnavailable {
FooterButtonView("Besoin d'aide ? Un problème ? Contactez-nous !") {
_zip()
}
} else {
Button("Signaler un problème") {
_zip()
}
}
}
.alert("Un problème est survenu", isPresented: messageSentFailed) {
Button("OK") {
}
} message: {
let message = [networkMonitor.connected == false ? "L'appareil n'est pas connecté à internet." as String? : nil, sentError == .mailNotSent ? "Le mail est dans la boîte d'envoi de l'app Mail. Vérifiez son état dans l'app Mail avant d'essayer de le renvoyer." as String? : nil, (sentError == .messageFailed || sentError == .messageNotSent) ? "Le SMS n'a pas été envoyé" as String? : nil, sentError == .mailFailed ? "Le mail n'a pas été envoyé" as String? : nil].compacted().joined(separator: "\n")
Text(message)
}
.sheet(item: $zipFilePath) { zipFilePath in
MailComposeView(recipients: ["support@padelclub.app"], bccRecipients: nil, body: nil, subject: _getSubject(), attachmentURL: zipFilePath) { result in
switch result {
case .cancelled, .saved:
self.zipFilePath = nil
case .failed:
self.zipFilePath = nil
self.sentError = .mailFailed
case .sent:
if networkMonitor.connected == false {
self.zipFilePath = nil
self.sentError = .mailNotSent
}
@unknown default:
break
}
}
.tint(.master)
}
}
private func _getSubject() -> String {
let device = UIDevice.current
let iOSVersion = device.systemVersion
return "[\(PadelClubApp.appVersion), \(iOSVersion), \(_getDeviceIdentifier())] Support Padel Club"
}
private func _getDeviceIdentifier() -> String {
var systemInfo = utsname()
uname(&systemInfo)
let machineMirror = Mirror(reflecting: systemInfo.machine)
let identifier = machineMirror.children.reduce("") { identifier, element in
guard let value = element.value as? Int8, value != 0 else { return identifier }
return identifier + String(UnicodeScalar(UInt8(value)))
} }
return identifier
} }
func openMail(emailTo: String = "support@padelclub.app", subject: String = "Support Padel Club") { private func _zip() {
if let url = URL(string: "mailto:\(emailTo)?subject=\(subject)"), UIApplication.shared.canOpenURL(url) { do {
UIApplication.shared.open(url, options: [:], completionHandler: nil) let filePath = try Club.storageDirectoryPath()
self.zipFilePath = try Zip.quickZipFiles([filePath], fileName: "backup") // Zip
} catch {
Logger.error(error)
} }
} }
} }

@ -140,14 +140,15 @@ import LeStorage
} }
var currentPlan: StoreItem? { var currentPlan: StoreItem? {
#if DEBUG return .monthlyUnlimited
return .monthlyUnlimited // #if DEBUG
#else // return .monthlyUnlimited
if let currentBestPlan = self.currentBestPlan, let plan = StoreItem(rawValue: currentBestPlan.productID) { // #else
return plan // if let currentBestPlan = self.currentBestPlan, let plan = StoreItem(rawValue: currentBestPlan.productID) {
} // return plan
return nil // }
#endif // return nil
// #endif
} }
func userFilteredPurchases() -> [StoreKit.Transaction] { func userFilteredPurchases() -> [StoreKit.Transaction] {

Loading…
Cancel
Save