Path: blob/a-new-beginning/Folium-iOS/Structures/CellManager.swift
2 views
//
// CellManager.swift
// Folium
//
// Created by Jarrod Norwell on 5/12/2025.
//
import Foundation
import SettingsKit
import UIKit
struct CellManager {
struct Settings {
static var boolCell: UICollectionView.CellRegistration<UICollectionViewListCell, BoolSetting> {
UICollectionView.CellRegistration { cell, indexPath, itemIdentifier in
if #available(iOS 26, *) {
var backgroundConfiguration: UIBackgroundConfiguration = .clear()
let effect: UIGlassEffect = UIGlassEffect(style: .regular)
let visualEffectView: UIVisualEffectView = UIVisualEffectView(effect: effect)
visualEffectView.cornerConfiguration = .corners(topLeftRadius: .fixed(cell.effectiveRadius(corner: .topLeft)),
topRightRadius: .fixed(cell.effectiveRadius(corner: .topRight)),
bottomLeftRadius: .fixed(cell.effectiveRadius(corner: .bottomLeft)),
bottomRightRadius: .fixed(cell.effectiveRadius(corner: .bottomRight)))
backgroundConfiguration.customView = visualEffectView
cell.backgroundConfiguration = backgroundConfiguration
}
var contentConfiguration = UIListContentConfiguration.cell()
contentConfiguration.text = itemIdentifier.title
contentConfiguration.secondaryText = itemIdentifier.secondaryTitle
cell.contentConfiguration = contentConfiguration
let toggle = UISwitch(frame: .zero, primaryAction: UIAction { action in
guard let toggle: UISwitch = action.sender as? UISwitch else {
return
}
UserDefaults.standard.set(toggle.isOn, forKey: itemIdentifier.key)
guard let delegate: SettingDelegate = itemIdentifier.delegate else {
return
}
delegate.didChangeSetting(at: indexPath)
})
toggle.isEnabled = itemIdentifier.isEnabled
toggle.isOn = itemIdentifier.value
cell.accessories = [
UICellAccessory.customView(configuration: UICellAccessory.CustomViewConfiguration(customView: toggle,
placement: .trailing()))
]
}
}
static var inputNumberCell: UICollectionView.CellRegistration<UICollectionViewListCell, InputNumberSetting> {
UICollectionView.CellRegistration { cell, indexPath, itemIdentifier in
if #available(iOS 26, *) {
var backgroundConfiguration: UIBackgroundConfiguration = .clear()
let effect: UIGlassEffect = UIGlassEffect(style: .regular)
let visualEffectView: UIVisualEffectView = UIVisualEffectView(effect: effect)
visualEffectView.cornerConfiguration = .corners(topLeftRadius: .fixed(cell.effectiveRadius(corner: .topLeft)),
topRightRadius: .fixed(cell.effectiveRadius(corner: .topRight)),
bottomLeftRadius: .fixed(cell.effectiveRadius(corner: .bottomLeft)),
bottomRightRadius: .fixed(cell.effectiveRadius(corner: .bottomRight)))
backgroundConfiguration.customView = visualEffectView
cell.backgroundConfiguration = backgroundConfiguration
}
var contentConfiguration = UIListContentConfiguration.subtitleCell()
contentConfiguration.text = itemIdentifier.title
contentConfiguration.secondaryText = itemIdentifier.secondaryTitle
contentConfiguration.secondaryTextProperties.color = .secondaryLabel
cell.contentConfiguration = contentConfiguration
cell.accessories = [
UICellAccessory.label(text: "\(Int(itemIdentifier.value))"),
UICellAccessory.disclosureIndicator()
]
}
}
static var inputStringCell: UICollectionView.CellRegistration<UICollectionViewListCell, InputStringSetting> {
UICollectionView.CellRegistration { cell, indexPath, itemIdentifier in
if #available(iOS 26, *) {
var backgroundConfiguration: UIBackgroundConfiguration = .clear()
let effect: UIGlassEffect = UIGlassEffect(style: .regular)
let visualEffectView: UIVisualEffectView = UIVisualEffectView(effect: effect)
visualEffectView.cornerConfiguration = .corners(topLeftRadius: .fixed(cell.effectiveRadius(corner: .topLeft)),
topRightRadius: .fixed(cell.effectiveRadius(corner: .topRight)),
bottomLeftRadius: .fixed(cell.effectiveRadius(corner: .bottomLeft)),
bottomRightRadius: .fixed(cell.effectiveRadius(corner: .bottomRight)))
backgroundConfiguration.customView = visualEffectView
cell.backgroundConfiguration = backgroundConfiguration
}
var contentConfiguration = UIListContentConfiguration.valueCell()
contentConfiguration.text = itemIdentifier.title
contentConfiguration.secondaryText = itemIdentifier.value
contentConfiguration.secondaryTextProperties.color = .secondaryLabel
cell.contentConfiguration = contentConfiguration
cell.accessories = [
.disclosureIndicator()
]
}
}
static func segmentedCell(_ controller: UIViewController) -> UICollectionView.CellRegistration<UICollectionViewListCell, SegmentedSetting> {
UICollectionView.CellRegistration { cell, indexPath, itemIdentifier in
if #available(iOS 26, *) {
var backgroundConfiguration: UIBackgroundConfiguration = .clear()
let effect: UIGlassEffect = UIGlassEffect(style: .regular)
let visualEffectView: UIVisualEffectView = UIVisualEffectView(effect: effect)
visualEffectView.cornerConfiguration = .corners(topLeftRadius: .fixed(cell.effectiveRadius(corner: .topLeft)),
topRightRadius: .fixed(cell.effectiveRadius(corner: .topRight)),
bottomLeftRadius: .fixed(cell.effectiveRadius(corner: .bottomLeft)),
bottomRightRadius: .fixed(cell.effectiveRadius(corner: .bottomRight)))
backgroundConfiguration.customView = visualEffectView
cell.backgroundConfiguration = backgroundConfiguration
}
var contentConfiguration = UIListContentConfiguration.valueCell()
contentConfiguration.text = itemIdentifier.title
cell.contentConfiguration = contentConfiguration
let segmentedControl: UISegmentedControl = UISegmentedControl(frame: .zero, primaryAction: UIAction { action in
guard let segmentedControl: UISegmentedControl = action.sender as? UISegmentedControl else {
return
}
UserDefaults.standard.set(segmentedControl.selectedSegmentIndex, forKey: itemIdentifier.key)
guard let delegate: SettingDelegate = itemIdentifier.delegate else {
return
}
delegate.didChangeSetting(at: indexPath)
itemIdentifier.action(controller)
})
itemIdentifier.values.enumerated().forEach { index, item in
segmentedControl.insertSegment(withTitle: item.key, at: index, animated: true)
}
segmentedControl.selectedSegmentIndex = UserDefaults.standard.integer(forKey: itemIdentifier.key)
cell.accessories = [
UICellAccessory.customView(configuration: UICellAccessory.CustomViewConfiguration(customView: segmentedControl,
placement: .trailing(),
reservedLayoutWidth: .actual))
]
}
}
static var stepperCell: UICollectionView.CellRegistration<UICollectionViewListCell, StepperSetting> {
UICollectionView.CellRegistration { cell, indexPath, itemIdentifier in
if #available(iOS 26, *) {
var backgroundConfiguration: UIBackgroundConfiguration = .clear()
let effect: UIGlassEffect = UIGlassEffect(style: .regular)
let visualEffectView: UIVisualEffectView = UIVisualEffectView(effect: effect)
visualEffectView.cornerConfiguration = .corners(topLeftRadius: .fixed(cell.effectiveRadius(corner: .topLeft)),
topRightRadius: .fixed(cell.effectiveRadius(corner: .topRight)),
bottomLeftRadius: .fixed(cell.effectiveRadius(corner: .bottomLeft)),
bottomRightRadius: .fixed(cell.effectiveRadius(corner: .bottomRight)))
backgroundConfiguration.customView = visualEffectView
cell.backgroundConfiguration = backgroundConfiguration
}
var contentConfiguration = UIListContentConfiguration.subtitleCell()
contentConfiguration.text = itemIdentifier.title
if itemIdentifier.max > 1 {
contentConfiguration.secondaryText = "\(Int(itemIdentifier.value)) out of \(Int(itemIdentifier.max))"
} else {
if itemIdentifier.value < 0.1 {
contentConfiguration.secondaryText = "0 out of \(Int(itemIdentifier.max))"
} else if itemIdentifier.value > 0.9 {
contentConfiguration.secondaryText = "1 out of \(Int(itemIdentifier.max))"
} else {
contentConfiguration.secondaryText = "\(String(format: "%.1f", itemIdentifier.value)) out of \(Int(itemIdentifier.max))"
}
}
contentConfiguration.secondaryTextProperties.color = .secondaryLabel
cell.contentConfiguration = contentConfiguration
let stepper = UIStepper(frame: .zero, primaryAction: UIAction { action in
guard let stepper: UIStepper = action.sender as? UIStepper else {
return
}
UserDefaults.standard.set(stepper.value, forKey: itemIdentifier.key)
guard let delegate: SettingDelegate = itemIdentifier.delegate else {
return
}
delegate.didChangeSetting(at: indexPath)
})
stepper.minimumValue = itemIdentifier.min
stepper.maximumValue = itemIdentifier.max
stepper.stepValue = itemIdentifier.max > 1 ? 1 : 0.1
stepper.value = itemIdentifier.value
cell.accessories = [
UICellAccessory.customView(configuration: UICellAccessory.CustomViewConfiguration(customView: stepper,
placement: .trailing(),
reservedLayoutWidth: .actual))
]
}
}
static var tapCell: UICollectionView.CellRegistration<UICollectionViewListCell, TapSetting> {
UICollectionView.CellRegistration { cell, indexPath, itemIdentifier in
if #available(iOS 26, *) {
var backgroundConfiguration: UIBackgroundConfiguration = .clear()
let effect: UIGlassEffect = UIGlassEffect(style: .regular)
let visualEffectView: UIVisualEffectView = UIVisualEffectView(effect: effect)
visualEffectView.cornerConfiguration = .corners(topLeftRadius: .fixed(cell.effectiveRadius(corner: .topLeft)),
topRightRadius: .fixed(cell.effectiveRadius(corner: .topRight)),
bottomLeftRadius: .fixed(cell.effectiveRadius(corner: .bottomLeft)),
bottomRightRadius: .fixed(cell.effectiveRadius(corner: .bottomRight)))
backgroundConfiguration.customView = visualEffectView
cell.backgroundConfiguration = backgroundConfiguration
}
var contentConfiguration = UIListContentConfiguration.cell()
contentConfiguration.text = itemIdentifier.title
contentConfiguration.textProperties.alignment = .center
contentConfiguration.textProperties.color = itemIdentifier.color
contentConfiguration.textProperties.font = .bold(.body)
cell.contentConfiguration = contentConfiguration
}
}
}
}