Path: blob/a-new-beginning/Folium-iOS/SceneDelegate.swift
2 views
//
// SceneDelegate.swift
// Folium-iOS
//
// Created by Jarrod Norwell on 12/6/2025.
//
import AVFoundation
import Cherry
import CombinedCores
import Cytrus
import FilesManager
import FirebaseAppCheck
import FirebaseAuth
import FirebaseCore
import Guava
import Kiwi
import Mango
import OnboardingKit
import Plum
import StoreKit
import SwiftUI
import Tomato
import UIKit
fileprivate typealias OnboardingButtonConfiguration = OnboardingController.Onboarding.Button.Configuration
class AppAttestProviderFactory: NSObject, AppCheckProviderFactory {
func createProvider(with app: FirebaseApp) -> AppCheckProvider? {
AppAttestProvider(app: app)
}
}
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow? = nil
let combinedCores: CombinedCores = CombinedCores()
var filesManager: FilesManager = .shared
var layoutManager: LayoutManager = .shared
let cherry: Cherry = Cherry()
let cytrus: Cytrus = Cytrus()
let guava: Guava = Guava()
let kiwi: Kiwi = Kiwi()
let mango: Mango = Mango()
let plum: Plum = Plum()
let tomato: Tomato = Tomato()
func scene(_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
AppCheck.setAppCheckProviderFactory(AppAttestProviderFactory())
FirebaseApp.configure()
let task = Task {
try await filesManager.moveOutdatedCoreDirectories()
try await filesManager.initializeDirectories(for: Core.coresAsStrings)
try AVAudioSession.sharedInstance().setCategory(.playback, options: .mixWithOthers)
try AVAudioSession.sharedInstance().setActive(true)
}
configureDefaultUserDefaults()
let applicationModel: ApplicationModel = ApplicationModel(combinedCores,
filesManager,
layoutManager,
cherry,
cytrus,
guava,
kiwi,
mango,
plum,
tomato)
guard let windowScene = scene as? UIWindowScene else {
return
}
window = UIWindow(windowScene: windowScene)
guard let window else {
return
}
#if targetEnvironment(simulator)
if let url: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
print(url.path(percentEncoded: false))
}
// UserDefaults.standard.removeObject(forKey: "folium.v1.38.filteredCores")
// UserDefaults.standard.removeObject(forKey: "folium.v1.38.onboardingComplete")
#endif
let onboardingModel: OnboardingModel = OnboardingModel(applicationModel: applicationModel)
let buttons: [OnboardingButtonConfiguration] = [
OnboardingButtonConfiguration(text: LocalisedCommon.continue) { button, controller in
await onboardingModel.camera(controller: controller)
}
]
window.rootViewController = if UserDefaults.standard.bool(forKey: "folium.onboardingComplete") {
UINavigationController(rootViewController: LibraryController(applicationModel: applicationModel))
} else {
OnboardingController(configuration: .init(buttons: buttons,
colours: Color.vibrantGreens,
image: UIImage(systemName: "leaf.fill"),
text: LocalisedOnboarding.folium,
secondaryText: LocalisedOnboarding.foliumSecondaryText,
tertiaryText: LocalisedOnboarding.foliumTertiaryText))
}
window.tintColor = .systemGreen
window.makeKeyAndVisible()
let updatesTask = Task(priority: .background) {
for await result in Transaction.updates {
switch result {
case .unverified(let transaction, let error):
print(#line, transaction.productID, error.localizedDescription)
case .verified(let transaction):
print(#line, transaction.productID)
await transaction.finish()
}
}
}
Task {
switch await task.result {
case .success:
break
case .failure(let error):
print(#function, #line, error.localizedDescription)
}
_ = updatesTask
}
}
func sceneDidDisconnect(_ scene: UIScene) {
NotificationCenter.default.post(name: .applicationStateDidChange, object: ApplicationState.disconnected)
}
func sceneDidBecomeActive(_ scene: UIScene) {}
func sceneWillResignActive(_ scene: UIScene) {}
func sceneWillEnterForeground(_ scene: UIScene) {
NotificationCenter.default.post(name: .applicationStateDidChange, object: ApplicationState.foregrounded)
}
func sceneDidEnterBackground(_ scene: UIScene) {
NotificationCenter.default.post(name: .applicationStateDidChange, object: ApplicationState.backgrounded)
}
fileprivate func configureDefaultUserDefaults() {
if #available(iOS 26, *) {
UserDefaults.standard.set(false, forKey: "cytrus.v1.38.cpuJIT")
UserDefaults.standard.set(false, forKey: "cytrus.v1.38.useShaderJIT")
} else {
UserDefaults.standard.set(false, forKey: "cytrus.v1.38.cpuJIT")
UserDefaults.standard.set(true, forKey: "cytrus.v1.38.useShaderJIT")
}
let defaults: [String : [String : Any]] = [
"Cytrus" : [
// Core
"mode" : 0,
"cpuClockPercentage" : 100,
"new3DS" : true,
"lleApplets" : true,
"deterministicAsyncOperations" : false,
"enableRequiredOnlineLLEModules" : false,
// Data Storage
"compressCIAInstalls" : false,
// System
"regionValue" : -1,
"pluginLoader" : false,
"allowPluginLoader" : true,
"stepsPerHour" : 0,
"applyRegionFreePatch" : true,
// Renderer
"spirvShaderGeneration" : true,
"disableSpirvOptimizer" : true,
"useAsyncShaderCompilation" : false,
"useAsyncPresentation" : true,
"useHardwareShaders" : true,
"useDiskShaderCache" : true,
"useShadersAccurateMul" : true,
"useNewVSync" : true,
"resolutionFactor" : 1,
// frame_limit
// turbo_limit
"textureFilter" : 0,
"textureSampling" : 0,
"delayGameRenderThreadUS" : 0,
"layoutOption" : 0,
// swap_screen
// upright_screen
// large_screen_proportion
// screen_gap
// small_screen_position
"customTopX" : 0,
"customTopY" : 0,
"customTopWidth" : 800,
"customTopHeight" : 480,
"customBottomX" : 80,
"customBottomY" : 500,
"customBottomWidth" : 640,
"customBottomHeight" : 480,
"customSecondLayerOpacity" : 100,
"aspectRatio" : 0,
// screen_top_stretch
// screen_top_leftright_padding
// screen_top_topbottom_padding
// screen_bottom_stretch
// screen_bottom_leftright_padding
// screen_bottom_topbottom_padding
// portrait_layout_option
// custom_portrait_top_x
// custom_portrait_top_y
// custom_portrait_top_width
// custom_portrait_top_height
// custom_portrait_bottom_x
// custom_portrait_bottom_y
// custom_portrait_bottom_width
// custom_portrait_bottom_height
// bg_red
// bg_green
// bg_blue
"render3D" : 0,
"factor3D" : 0,
"monoRender" : 0,
// cardboard_screen_size
// cardboard_x_shift
// cardboard_y_shift
"filterMode" : true,
"ppShaderName" : "None (builtin)",
"anaglyphShaderName" : "Dubois (builtin)",
"dumpTextures" : false,
"customTextures" : false,
"preloadTextures" : false,
"asyncCustomLoading" : true,
"disableRightEyeRender" : false,
"audioMuted" : false,
"audioEmulation" : 0,
"audioStretching" : true,
"realtimeAudio" : false,
"volume" : 1,
"outputType" : 6,
"inputType" : 0,
// Miscellaneous
"logLevel" : 2,
"webAPIURL" : "http://88.198.47.46:5000",
"systemLanguage" : 1,
"username" : "Cytrus"
],
"Folium" : [
"buttonTransparency" : 1,
"expandButtonsBy" : 0,
"filteredCores" : Core.cores.filter {
core in !core.isBeta
}.map { core in
core.string
}
],
"Grape" : [
"directBoot" : true,
"dsiMode" : false
],
"Mandarine" : [
"height" : 640,
"widescreen" : false,
"width" : 480
],
"Plum" : [
"region" : 0,
"tvStandard" : 0
]
]
defaults.forEach { core, values in
values.forEach { key, value in
if UserDefaults.standard.value(forKey: "\(core.lowercased()).v1.38.\(key)") == nil {
UserDefaults.standard.set(value, forKey: "\(core.lowercased()).v1.38.\(key)")
}
}
}
}
}