Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/Folium-iOS/Actors/Onboarding/OnboardingModel.swift
2 views
//
//  OnboardingModel.swift
//  Folium-iOS
//
//  Created by Jarrod Norwell on 31/8/2025.
//

/*
 MARK: 29/11/2025
 - Cleaned up OnboardingModel actor
 - Changed strings to be clearer
 */

import OnboardingKit
import SwiftUI
import UIKit

fileprivate typealias OnboardingButtonConfiguration = OnboardingController.Onboarding.Button.Configuration

actor OnboardingModel {
    var applicationModel: ApplicationModel
    init(applicationModel: ApplicationModel) {
        self.applicationModel = applicationModel
    }
    
    @MainActor func camera(controller: UIViewController) async {
        let cameraAccess: CameraAccess = CameraAccess()
        await cameraAccess.checkAuthorisationStatus()
        
        let buttons: [OnboardingButtonConfiguration] = [
            OnboardingButtonConfiguration(text: LocalisedCommon.continue) { button, controller in
                let result: Bool = await cameraAccess.authorise()
                print(#file, #function, #line, "Camera Access Authorised: \(result ? "YES" : "NO")")
                await self.microphone(controller: controller)
            }
        ]
        
        let viewController: OnboardingController = .init(configuration: .init(buttons: buttons,
                                                                              colours: Color.vibrantGreens,
                                                                              image: UIImage(systemName: "camera.fill"),
                                                                              text: LocalisedOnboarding.camera,
                                                                              secondaryText: LocalisedOnboarding.cameraSecondaryText,
                                                                              tertiaryText: LocalisedOnboarding.changePermissionLater))
        viewController.modalPresentationStyle = .fullScreen
        controller.present(viewController, animated: true)
    }
    
    @MainActor func microphone(controller: UIViewController) async {
        let MicrophoneAccessProtocolType: MicrophoneAccessProtocol.Type = if #available(iOS 17, *) {
            LatestMicrophoneAccess.self
        } else {
            MicrophoneAccess.self
        }
        
        let microphoneAccess: MicrophoneAccessProtocol = MicrophoneAccessProtocolType.init()
        await microphoneAccess.checkAuthorisationStatus()
        
        let buttons: [OnboardingButtonConfiguration] = [
            OnboardingButtonConfiguration(text: LocalisedCommon.continue) { button, controller in
                let result: Bool = await microphoneAccess.authorise()
                print(#file, #function, #line, "Microphone Access Authorised: \(result ? "YES" : "NO")")
#if os(macOS)
                await self.warning(controller: controller)
#else
                await self.motionAndFitness(controller: controller)
#endif
            }
        ]
        
        let systemName: String = if #available(iOS 18, *) {
            "microphone.and.signal.meter.fill"
        } else {
            "mic.and.signal.meter.fill"
        }
        
        let viewController: MicrophoneController = .init(configuration: .init(buttons: buttons,
                                                                              colours: Color.vibrantOranges,
                                                                              image: UIImage(systemName: systemName),
                                                                              useCustomSymbolEffect: true,
                                                                              text: LocalisedOnboarding.microphone,
                                                                              secondaryText: LocalisedOnboarding.microphoneSecondaryText,
                                                                              tertiaryText: LocalisedOnboarding.changePermissionLater))
        viewController.modalPresentationStyle = .fullScreen
        controller.present(viewController, animated: true)
    }
    
    @MainActor func motionAndFitness(controller: UIViewController) async {
        let motionAndFitnessAccess: MotionAndFitnessAccess = MotionAndFitnessAccess()
        await motionAndFitnessAccess.checkAuthorisationStatus()
        
        let buttons: [OnboardingButtonConfiguration] = [
            OnboardingButtonConfiguration(text: LocalisedCommon.continue) { button, controller in
                let result: Bool = await motionAndFitnessAccess.authorise()
                print(#file, #function, #line, "Motion & Fitness Access Authorised: \(result ? "YES" : "NO")")
                await self.warning(controller: controller)
            }
        ]
        
        let viewController: MotionAndFitnessController = .init(configuration: .init(buttons: buttons,
                                                                                    colours: Color.vibrantGreens,
                                                                                    image: UIImage(systemName: "figure.walk.motion"),
                                                                                    useCustomSymbolEffect: true,
                                                                                    text: LocalisedOnboarding.motionAndFitness,
                                                                                    secondaryText: LocalisedOnboarding.motionAndFitnessSecondaryText,
                                                                                    tertiaryText: LocalisedOnboarding.changePermissionLater))
        viewController.modalPresentationStyle = .fullScreen
        controller.present(viewController, animated: true)
    }
    
    @MainActor func warning(controller: UIViewController) async {
        let buttons: [OnboardingButtonConfiguration] = [
            OnboardingButtonConfiguration(text: LocalisedCommon.continue) { button, controller in
                await self.importGames(controller: controller)
            }
        ]
        
        let viewController: OnboardingController = .init(configuration: .init(buttons: buttons,
                                                                              colours: Color.vibrantReds,
                                                                              image: UIImage(systemName: "exclamationmark.octagon.fill"),
                                                                              text: LocalisedOnboarding.warning,
                                                                              secondaryText: LocalisedOnboarding.warningSecondaryText))
        viewController.modalPresentationStyle = .fullScreen
        controller.present(viewController, animated: true)
    }
    
    @MainActor func importGames(controller: UIViewController) async {
        let buttons: [OnboardingButtonConfiguration] = [
            OnboardingButtonConfiguration(text: LocalisedCommon.continue) { button, controller in
                await self.importSystemFiles(controller: controller)
            }
        ]
        
        var secondaryAttributedText: AttributedString = AttributedString(LocalisedOnboarding.startImportingStart)
        
        let attachment: NSTextAttachment = NSTextAttachment()
        attachment.image = if #available(iOS 18, *) {
            UIImage(systemName: "plus")?
                .applyingSymbolConfiguration(UIImage.SymbolConfiguration(scale: .small))
        } else {
            UIImage(systemName: "plus")?
                .applyingSymbolConfiguration(UIImage.SymbolConfiguration(scale: .small))?
                .withTintColor(.secondaryLabel)
        }
        
        let attributed: NSAttributedString = NSAttributedString(attachment: attachment)
        if let converted: AttributedString = try? AttributedString(attributed, including: \.uiKit) {
            secondaryAttributedText.append(converted)
        }
        
        secondaryAttributedText.append(AttributedString(LocalisedOnboarding.startImportingEnd))
        
        let viewController: OnboardingController = .init(configuration: .init(buttons: buttons,
                                                                              colours: Color.vibrantBlues,
                                                                              image: UIImage(systemName: "gamecontroller.fill"),
                                                                              text: LocalisedOnboarding.importGames,
                                                                              secondaryAttributedText: secondaryAttributedText))
        viewController.modalPresentationStyle = .fullScreen
        controller.present(viewController, animated: true)
    }
    
    @MainActor func importSystemFiles(controller: UIViewController) async {
        let buttons: [OnboardingButtonConfiguration] = [
            OnboardingButtonConfiguration(text: LocalisedCommon.continue) { button, controller in
                await self.onboardingComplete(controller: controller)
            }
        ]
        
        var secondaryAttributedText: AttributedString = AttributedString(LocalisedOnboarding.startImportingStart)
        
        let attachment: NSTextAttachment = NSTextAttachment()
        attachment.image = if #available(iOS 18, *) {
            UIImage(systemName: "plus")?
                .applyingSymbolConfiguration(UIImage.SymbolConfiguration(scale: .small))
        } else {
            UIImage(systemName: "plus")?
                .applyingSymbolConfiguration(UIImage.SymbolConfiguration(scale: .small))?
                .withTintColor(.secondaryLabel)
        }
        
        let attributed: NSAttributedString = NSAttributedString(attachment: attachment)
        if let converted: AttributedString = try? AttributedString(attributed, including: \.uiKit) {
            secondaryAttributedText.append(converted)
        }
        
        secondaryAttributedText.append(AttributedString(LocalisedOnboarding.startImportingEnd))
        
        let systemName: String = if #available(iOS 17, *) {
            "brain.fill"
        } else {
            "doc.badge.gearshape.fill"
        }
        
        let viewController: OnboardingController = .init(configuration: .init(buttons: buttons,
                                                                              colours: Color.vibrantOranges,
                                                                              image: UIImage(systemName: systemName),
                                                                              text: LocalisedOnboarding.importSystemFiles,
                                                                              secondaryAttributedText: secondaryAttributedText))
        viewController.modalPresentationStyle = .fullScreen
        controller.present(viewController, animated: true)
    }
    
    @MainActor func onboardingComplete(controller: UIViewController) async {
        let buttons: [OnboardingButtonConfiguration] = [
            OnboardingButtonConfiguration(image: UIImage(systemName: "square.grid.2x2")) { button, controller in
                UserDefaults.standard.set(true, forKey: "folium.onboardingComplete")
                
                let libraryController: LibraryController = LibraryController(applicationModel: await self.applicationModel)
                let navigationController: UINavigationController = UINavigationController(rootViewController: libraryController)
                navigationController.modalPresentationStyle = .fullScreen
                controller.present(navigationController, animated: true)
            }
        ]
        
        let viewController: OnboardingController = .init(configuration: .init(buttons: buttons,
                                                                              colours: Color.vibrantRainbow,
                                                                              image: .init(systemName: "app.badge.checkmark.fill"),
                                                                              text: LocalisedOnboarding.onboardingComplete,
                                                                              secondaryText: LocalisedOnboarding.onboardingCompleteSecondaryText))
        viewController.modalPresentationStyle = .fullScreen
        controller.present(viewController, animated: true)
    }
}