Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
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
            }
        }
    }
}