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. 85
      PadelClub/Views/Shared/SupportButtonView.swift
  7. 15
      PadelClub/Views/Subscription/Guard.swift

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

@ -52,12 +52,6 @@ struct PadelClubApp: App {
Logger.log("doc dir = \(docURL.absoluteString)")
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 {

@ -151,6 +151,7 @@ struct MailComposeView: UIViewControllerRepresentable {
let bccRecipients: [String]?
let body: String?
let subject: String?
var attachmentURL: URL?
let completion: Completion?
func makeUIViewController(context: Context) -> UIViewController {
@ -163,6 +164,15 @@ struct MailComposeView: UIViewControllerRepresentable {
controller.mailComposeDelegate = context.coordinator
controller.setToRecipients(recipients)
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 {
controller.setMessageBody(body, isHTML: false)
}

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

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

@ -6,18 +6,95 @@
//
import SwiftUI
import LeStorage
import Zip
extension URL: Identifiable {
public var id: String {
return self.absoluteString
}
}
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 {
Group {
if contentIsUnavailable {
FooterButtonView("Besoin d'aide ? Un problème ? Contactez-nous !") {
openMail()
_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") {
if let url = URL(string: "mailto:\(emailTo)?subject=\(subject)"), UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
private func _zip() {
do {
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? {
#if DEBUG
return .monthlyUnlimited
#else
if let currentBestPlan = self.currentBestPlan, let plan = StoreItem(rawValue: currentBestPlan.productID) {
return plan
}
return nil
#endif
// #if DEBUG
// return .monthlyUnlimited
// #else
// if let currentBestPlan = self.currentBestPlan, let plan = StoreItem(rawValue: currentBestPlan.productID) {
// return plan
// }
// return nil
// #endif
}
func userFilteredPurchases() -> [StoreKit.Transaction] {

Loading…
Cancel
Save