### Supabase Authentication Client Setup Source: https://docs.shipthat.app/docs/configurations Initializes the Supabase client for authentication services. Requires Supabase URL and Anon Key, which are used to create an instance of SupabaseClient. ```swift let client = SupabaseClient(supabaseURL: URL(string: "https://your-instance.supabase.co")!, supabaseKey: "your-supabase-annon-key") ``` -------------------------------- ### Paywall3View SwiftUI Code Example Source: https://docs.shipthat.app/docs/in-app-purchases A SwiftUI code example demonstrating how Paywall3View interacts with the PurchaseManager to display product information and initiate purchases. ```swift struct Paywall3View: View { @Environment(PurchaseManager.self) private var purchaseManager var body: some View { ForEach(purchaseManager.products, id: \.self) { product in Button(action: { // Initiate the purchase await purchaseManager.purchase(product) }) { // Custom view representing the product Text(product.displayName) } } } } ``` -------------------------------- ### SwiftUI App Initialization Source: https://docs.shipthat.app/index Demonstrates the basic initialization of the ShipThatApp application, including configuring telemetry and revenue cat services. This is the entry point for the application's setup. ```swift struct ShipThatAppApp: App { // MARK: - Initialization init() { configureTelemetry() configureRevenueCat() } // ... } ``` -------------------------------- ### SwiftUI App Configuration Example Source: https://docs.shipthat.app/index Illustrates how to customize the ShipThatApp boilerplate by adding custom configurations within the application's initialization block. This allows for personalization of splash screens, authentication methods, and other services. ```swift // ShipThatAppApp.swift … init() { configureTelemetry() configureRevenueCat() // Add your custom configurations } … ``` -------------------------------- ### Cloning ShipThatApp Repository Source: https://docs.shipthat.app/index Provides the command to clone the ShipThatApp project from its GitHub repository. This is the first step for users to get the boilerplate code into their local environment. ```bash git clone https://github.com/matious89pl/ShipThatApp.git cd ShipThatApp ``` -------------------------------- ### RevenueCat In-App Purchases Configuration Source: https://docs.shipthat.app/docs/configurations Sets up the RevenueCat SDK for managing in-app purchases and subscriptions. An API Key from RevenueCat is required, which must be added to Info.plist and then used to configure the Purchases client. ```APIDOC Info.plist Configuration: RC_API_KEY YOUR_REVENUECAT_API_KEY Swift Initialization: private func configureRevenueCat() { guard let revenueCatApiString = Bundle.main.infoDictionary?["RC_API_KEY"] as? String else { return } Purchases.logLevel = .debug Purchases.configure(withAPIKey: revenueCatApiString) } Usage: Call configureRevenueCat() within the init() of ShipThatAppApp. ``` ```swift private func configureRevenueCat() { guard let revenueCatApiString = Bundle.main.infoDictionary?["RC_API_KEY"] as? String else { return } Purchases.logLevel = .debug Purchases.configure(with: revenueCatApiString) } ``` -------------------------------- ### Swift String Extension: Test Email Validation Source: https://docs.shipthat.app/docs/string-extensions Provides an example of unit testing the `isValidEmail` extension method using XCTest. It asserts the expected boolean output for both valid and invalid email string formats. ```swift func testEmailValidation() { let validEmail = "test@example.com" let invalidEmail = "test_at_example.com" XCTAssertTrue(validEmail.isValidEmail(), "The method should return true for a valid email") XCTAssertFalse(invalidEmail.isValidEmail(), "The method should return false for an invalid email") } ``` -------------------------------- ### Swift Feature Model Definition and Usage Source: https://docs.shipthat.app/docs/feature-model Demonstrates the Swift `Feature` struct, conforming to `Identifiable`, used for onboarding content. Shows its properties (`id`, `title`, `description`, `icon`) and how it's utilized within a SwiftUI `OnboardingView` using `ForEach`. ```swift struct Feature { let id: UUID = UUID() let title: String let description: String let icon: String? } struct OnboardingView: View { let features: [Feature] = [ Feature(title: "Easy to Use", description: "Get started quickly with a user-friendly interface.", icon: "icon-easy-to-use"), Feature(title: "Secure", description: "We use state-of-the-art security measures to protect your information.", icon: "icon-secure") ] var body: some View { TabView { ForEach(features) { feature in FeatureCardView(feature: feature) } } .tabViewStyle(PageTabViewStyle()) } } ``` -------------------------------- ### RevenueCat Configuration for Info.plist Source: https://docs.shipthat.app/docs/in-app-purchases Details the necessary steps to configure RevenueCat by adding the API key to the application's Info.plist file. ```APIDOC RevenueCat Configuration: To configure RevenueCat, an API key from the RevenueCat dashboard must be added to your Info.plist file. Steps: 1. Obtain the RevenueCat API Key from your RevenueCat project dashboard. 2. Add the key to your Info.plist file using the following structure: RC_API_KEY Your_RevenueCat_API_Key 3. Initialize RevenueCat in the app entry point (e.g., ShipThatAppApp.swift) using a function like configureRevenueCat(). ``` -------------------------------- ### AuthManager Initialization Source: https://docs.shipthat.app/docs/authentication Initializes the AuthManager with Supabase client credentials. Requires Supabase URL and Key to connect to the authentication service. ```swift let client = SupabaseClient(supabaseURL: URL(string: "")!, supabaseKey: "") ``` -------------------------------- ### ContentView SwiftUI Structure Source: https://docs.shipthat.app/docs/content-view This conceptual code sample illustrates the structure of ContentView.swift, demonstrating how it uses SwiftUI property wrappers like @AppStorage and @EnvironmentObject to conditionally render different views based on the user's onboarding and authentication status. ```swift struct ContentView: View { @AppStorage("onboarding_complete") var onBoardingComplete: Bool = false @EnvironmentObject var authManager: AuthManager var body: some View { ZStack { if !onBoardingComplete { OnboardingView() } else if !authManager.isUserAuthenticated { SignInView() } else { HomeView() } } } } ``` -------------------------------- ### SplashScreenStateManager API Source: https://docs.shipthat.app/docs/splash-screen-state-manager Documentation for the SplashScreenStateManager class, detailing its purpose in managing splash screen transitions and its key `dismiss` function for controlling the animation progression. ```APIDOC SplashScreenStateManager: File: SplashScreenStateManager.swift Purpose: Manages the state and transition of the splash screen animation and determines when to navigate to the main content of the app. Key Functions: dismiss: Controls the progression of the splash screen through its steps, from start to finish (firstStep, secondStep, finished). Usage: This manager affects the user experience right from the launch of the app. It is used in the SplashScreenView to control the transition of the view states from the initial splash to the app's main content view. ``` -------------------------------- ### SignInViewModel Conceptual Usage in SwiftUI Source: https://docs.shipthat.app/docs/signin-view-model Illustrates how the SignInViewModel can be integrated into a SwiftUI View for handling user input, displaying errors, and triggering authentication actions via buttons. ```swift struct SignInView: View { @StateObject private var signInViewModel = SignInViewModel() @State private var email: String = "" @State private var password: String = "" var body: some View { Form { TextField("Email", text: $email) SecureField("Password", text: $password) if let errorText = signInViewModel.errorText { Text(errorText).foregroundColor(.red) } Button("Sign In") { Task { do { let user = try await signInViewModel.signInWithEmail(email: email, password: password) // Handle successful sign-in, e.g., navigate to home screen } catch { // Update UI with error message from ViewModel signInViewModel.errorText = error.localizedDescription } } } } } } ``` -------------------------------- ### TelemetryDeck Analytics Configuration Source: https://docs.shipthat.app/docs/configurations Configures the TelemetryDeck SDK for app analytics. Requires an App ID from TelemetryDeck, which should be added to Info.plist and then used to initialize the TelemetryManager in the application's entry point. ```APIDOC Info.plist Configuration: TD_APP_ID YOUR_TELEMETRYDECK_APP_ID Swift Initialization: private func configureTelemetry() { guard let telemetryDeckAppID = Bundle.main.infoDictionary?["TD_APP_ID"] as? String else { return } let configuration = TelemetryManagerConfiguration(appID: telemetryDeckAppID) TelemetryManager.initialize(with: configuration) } Usage: Call configureTelemetry() within the init() of ShipThatAppApp. ``` ```swift private func configureTelemetry() { guard let telemetryDeckAppID = Bundle.main.infoDictionary?["TD_APP_ID"] as? String else { return } let configuration = TelemetryManagerConfiguration(appID: telemetryDeckAppID) TelemetryManager.initialize(with: configuration) } ``` -------------------------------- ### AuthManager API Documentation Source: https://docs.shipthat.app/docs/auth-manager Documentation for the AuthManager class, responsible for handling all authentication-related tasks including user session management, registration, sign-in methods, magic link authentication, and sign-out. ```APIDOC AuthManager: Purpose: Handles all the authentication related tasks such as signing in, signing up, sending magic links, managing the current user session, and signing out. File: AuthManager.swift Key Functions: getCurrentSession(): Fetches the current user session if available. getSessionFromUrl(url: URL): Processes a URL callback after a magic link sign-in, extracting the user session. registerNewUserWithEmail(email: String, password: String): Registers a new user using their email and password. signInWithEmail(email: String, password: String): Authenticates a user by their email and password. signInWithApple(idToken: String): Authenticates a user with Sign in with Apple using the provided idToken. sendMagicLink(email: String): Sends a magic link to the user's email for passwordless authentication. signOut(): Signs out the current user. Usage: Wisely employed throughout the app in views where user authentication state changes are relevant, such as the SignInView or the SettingsView. ``` -------------------------------- ### SignInViewModel Swift Implementation Source: https://docs.shipthat.app/docs/signin-view-model Details the SignInViewModel's role in managing user authentication, including form validation, initiating sign-in/registration, and handling magic link requests. It outlines key properties like errorText and isUserAuthenticated, and functions for validation and authentication actions. ```swift class SignInViewModel: ObservableObject { @Published var errorText: String = "" @Published var isUserAuthenticated: Bool = false // Validates email and password format. func isFormValid(email: String, password: String) -> Bool { // Implementation details for email format and password strength checks. // Returns true if valid, false otherwise. return true // Placeholder } // Registers a new user with email and password. func registerNewUserWithEmail(email: String, password: String) async throws -> AppUser { // Calls AuthManager to perform registration. // Returns the AppUser object upon success. // Throws an error on failure. return AppUser() // Placeholder } // Sends a magic link for passwordless authentication. func sendMagicLink(email: String) async throws { // Calls AuthManager to send the magic link. // Throws an error on failure. } // Signs in a user with email and password. func signInWithEmail(email: String, password: String) async throws -> AppUser { // Calls AuthManager to perform sign-in. // Returns the AppUser object upon success. // Throws an error on failure. return AppUser() // Placeholder } } ``` -------------------------------- ### SignInViewModel Methods Source: https://docs.shipthat.app/docs/authentication Handles the UI logic for authentication forms, validating inputs and calling corresponding AuthManager methods. It provides feedback to the user through an errorText property. ```APIDOC SignInViewModel: errorText: String A string to display error messages to the user. isFormValid(email: String, password: String) -> Bool Validates email and password inputs against predefined criteria. email: The email string to validate. password: The password string to validate. Returns: True if the form inputs are valid, false otherwise. registerNewUserWithEmail(email: String, password: String) async throws -> AppUser Delegates user registration to AuthManager.registerNewUserWithEmail. sendMagicLink(email: String) async throws Delegates sending a magic link to AuthManager.sendMagicLink. signInWithEmail(email: String, password: String) async throws -> AppUser Delegates email/password sign-in to AuthManager.signInWithEmail. ``` -------------------------------- ### AuthManager Authentication Methods Source: https://docs.shipthat.app/docs/authentication Provides methods for user authentication, including registration, email/password login, magic link, and Sign in with Apple. These methods interact with the GoTrue authentication service and return AppUser objects on success or throw errors on failure. ```APIDOC AuthManager Service: __init__(client: SupabaseClient) client: The Supabase client instance for authentication. registerNewUserWithEmail(email: String, password: String) async throws -> AppUser email: The user's email address for registration. password: The user's chosen password. Returns: An AppUser object upon successful registration. signInWithEmail(email: String, password: String) async throws -> AppUser email: The user's registered email address. password: The user's password. Returns: An AppUser object upon successful sign-in. Throws: Error if sign-in fails. sendMagicLink(email: String) async throws email: The user's email address to send the magic link to. Throws: Error if the magic link cannot be sent. signInWithApple(idToken: String) async throws -> AppUser idToken: The identity token received from Apple's sign-in process. Returns: An AppUser object upon successful sign-in. getCurrentSession() async throws -> AppUser Fetches the current user session and updates the internal state. Returns: The current AppUser object. getSessionFromUrl(url: URL) async throws -> AppUser Processes a URL callback, typically from a magic link, to retrieve user session details. url: The callback URL. Returns: An AppUser object from the session. updateCurrentSession() async Refreshes the current user session state, often called on app launch. signOut() async throws Invalidates the current user session and logs the user out. ``` -------------------------------- ### Swift Splash Screen Delay Configuration Source: https://docs.shipthat.app/docs/configurations Configures the splash screen delay duration within the `ShipThatAppApp.swift` file. This snippet shows how to use `Task.sleep` to introduce a delay before dismissing the splash screen, allowing customization of the display time. ```swift private func dismissSplashScreenAfterDelay() async { try? await Task.sleep(for: .seconds(1)) // Set your desired time here splashScreenState.dismiss() } ``` -------------------------------- ### PurchaseManager Swift Class Documentation Source: https://docs.shipthat.app/docs/in-app-purchases Documents the PurchaseManager class in Swift, detailing its properties for product management and functions for handling purchases and transaction updates. It relies on RevenueCat and StoreKit for in-app purchase operations. ```APIDOC PurchaseManager.swift Class Documentation: This class is central to the in-app purchase functionality, handling product fetching, purchasing, and transaction state management. Properties: - productIds: Set Identifiers for your products, matching App Store Connect and RevenueCat. - products: [Product] An array of Product objects representing available products. - purchasedProductIDs: Set Keeps track of product IDs purchased by the user. Functions: - loadProducts(): Calls Product.products(for:) to load SKProduct information from the App Store. - purchase(_ product: Product) async: Initiates a purchase transaction for the given Product. - updatePurchasedProducts(): Checks current entitlements to update purchasedProductIDs. Transaction Observer: - observeTransactionUpdates: Observes the StoreKit transaction queue and processes updates, including verification, pending states, and cancellations. ``` -------------------------------- ### Handle Incoming URL for Magic Link Authentication Source: https://docs.shipthat.app/docs/authentication This snippet demonstrates how to handle incoming URLs, typically from a magic link, within a SwiftUI view. It uses the .onOpenURL modifier to capture the URL and pass it to a handler function for processing. ```swift .onOpenURL { incomingURL in handleIncomingURL(incomingURL) } ``` -------------------------------- ### TelemetryDeck API Reference Source: https://docs.shipthat.app/docs/analytics This section provides a reference for key TelemetryDeck functionalities used in the boilerplate. It covers initialization, sending events, and setting debug identifiers. ```apidoc TelemetryManager: initialize(with: TelemetryManagerConfiguration) Initializes the TelemetryManager with the provided configuration. Parameters: configuration: TelemetryManagerConfiguration object containing the appID. TelemetryManagerConfiguration: appID: String The unique identifier for your application on TelemetryDeck. send(event: String, with properties: [String: Any]? = nil) Sends a custom event to TelemetryDeck. Parameters: event: The name of the event to send (e.g., "AppLaunched", "PurchaseAttempt"). properties: An optional dictionary of key-value pairs to associate with the event. setDebugIdentifier(identifier: String) Sets a unique identifier for the current device during development. This helps in filtering development data from production analytics. Parameters: identifier: A string representing the debug identifier (e.g., "Developer_iPhone"). Note: This should only be used in development builds and conditionally excluded from production. ``` -------------------------------- ### PurchaseManager Swift Implementation Source: https://docs.shipthat.app/docs/purchase-manager Details the PurchaseManager class in Swift, responsible for managing the in-app purchase lifecycle. It covers fetching products, initiating purchases, handling transaction results, and observing background updates from StoreKit. ```swift class PurchaseManager { // Purpose: Manages the purchase lifecycle, which includes loading available products, making purchases, restoring purchases, and keeping track of what the user purchased. // Fetches products from the App Store based on given product IDs and makes them available for purchase. func loadProducts(productIDs: [String]) async throws { // ... implementation ... } // Initiates a purchase of a selected product and handles the result, which can be successful, pending, or failed due to user cancellation. func purchase(product: Product) async throws -> PurchaseResult { // ... implementation ... } // Updates the user's purchased products based on completed transactions. func updatePurchasedProducts() async { // ... implementation ... } // A background task that listens for updates from StoreKit regarding transactions and reacts accordingly. func observeTransactionUpdates() { // ... implementation ... } } // Usage: // Mainly used within paywall views (Paywall1View, Paywall2View, Paywall3View) to present the user with purchase options and handle their transaction responses. // It's also used in the SettingsView to give users the option to restore purchases or upgrade their subscription. ``` -------------------------------- ### Custom URL Scheme for Magic Links Source: https://docs.shipthat.app/docs/configurations Configures a custom URL scheme in the application's Info.plist to handle incoming magic links for passwordless authentication. This allows the app to receive and process authentication deep links. ```APIDOC Info.plist Configuration: CFBundleURLTypes CFBundleURLSchemes shipthatapp Note: Replace 'shipthatapp' with your chosen custom URL scheme. The app must also implement logic to handle these incoming URLs. ``` ```xml CFBundleURLTypes CFBundleURLSchemes shipthatapp ``` -------------------------------- ### SwiftUI Splash Screen View Implementation Source: https://docs.shipthat.app/docs/splash-screen The SplashScreenView is a SwiftUI view responsible for displaying the application's splash screen. It utilizes state management to control animations and transitions, providing an engaging user experience during app startup. It binds to an ObservableObject for state updates. ```Swift struct SplashScreenView: View { // Bind to the SplashScreenStateManager @EnvironmentObject private var splashScreenState: SplashScreenStateManager // States for animating the splash screen elements @State private var firstAnimation = false @State private var secondAnimation = false @State private var startFadeoutAnimation = false // Body var body: some View { ZStack { // Background color or image Color(.accent).edgesIgnoringSafeArea(.all) // Content: Can include logo, title, tagline, and animations VStack { Image("Logo") // Animation and transition effects based on splash screen state } // Transitions and animations are triggered by splashScreenState changes } .onReceive(animationTimer) { timerValue in updateAnimation() } } // Defines how animations are triggered based on splash screen state private func updateAnimation() { // ... implementation details ... } } ``` -------------------------------- ### Swift: Manage App Review Request Logic Source: https://docs.shipthat.app/docs/review-request This snippet covers the core logic for managing app review requests. It includes incrementing a user interaction count and conditionally triggering a delayed review prompt based on interaction thresholds and app version. ```swift private func incrementProcessCount() { count += 1 let currentVersion = Bundle.main.object(forInfoDictionaryKey: kCFBundleVersionKey as String) as? String ?? "" if count >= MIN_APP_RUNS_BEFORE_REVIEW_REQ && currentVersion != lastVersionPromptedForReview { requestReviewAfterDelay(for: currentVersion) } } ``` ```swift private func requestReviewAfterDelay(for version: String) { Task { try await Task.sleep(for: .seconds(2)) await requestReview() lastVersionPromptedForReview = version TelemetryManager.send("reviewRequested", with: ["version": version]) } } ``` ```swift @Environment(\.requestReview) private var requestReview ``` -------------------------------- ### Initialize TelemetryDeck in App Entry Source: https://docs.shipthat.app/docs/analytics This Swift code demonstrates how to initialize the TelemetryManager with your TelemetryDeck App ID. It reads the ID from Info.plist and configures the manager upon app launch. ```swift private func configureTelemetry() { guard let telemetryDeckAppID = Bundle.main.infoDictionary?["TD_APP_ID"] as? String else { return } let configuration = TelemetryManagerConfiguration(appID: telemetryDeckAppID) TelemetryManager.initialize(with: configuration) } ```