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)
}
}