Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/Folium-iOS/Controllers/LibraryControllers/LibraryIssuesController.swift
2 views
//
//  LibraryIssuesController.swift
//  Folium-iOS
//
//  Created by Jarrod Norwell on 16/10/2025.
//

import Foundation
import UIKit

class LibraryIssuesController : UICollectionViewController {
    struct Item : Codable, Hashable, Identifiable, @unchecked Sendable {
        static func < (lhs: Item, rhs: Item) -> Bool {
            lhs.text.localizedCaseInsensitiveCompare(rhs.text) == .orderedAscending
        }
        
        var id: UUID = .init()
        let text: String
    }
    
    var dataSource: UICollectionViewDiffableDataSource<Core, Item>? = nil
    var snapshot: NSDiffableDataSourceSnapshot<Core, Item>? = nil
    
    var applicationModel: ApplicationModel
    var errors: [Core : [AnyError]]
    init(_ applicationModel: ApplicationModel, _ errors: [Core : [AnyError]]) {
        self.applicationModel = applicationModel
        self.errors = errors
        super.init(collectionViewLayout: applicationModel.layoutManager.list)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        if let navigationController {
            navigationController.navigationBar.prefersLargeTitles = true
        }
        navigationItem.setLeftBarButton(.init(image: .init(systemName: "xmark"), primaryAction: .init { _ in
            self.dismiss(animated: true)
        }), animated: true)
        navigationItem.style = .browser
        if #available(iOS 26.0, *) {
            navigationItem.largeTitle = "Issues"
        }
        navigationItem.title = "Issues"
        
        let headerCellRegistration: UICollectionView.SupplementaryRegistration<UICollectionViewListCell> = .init(elementKind: UICollectionView.elementKindSectionHeader) { supplementaryView, elementKind, indexPath in
            var contentConfiguration = UIListContentConfiguration.extraProminentInsetGroupedHeader()
            if let dataSource = self.dataSource, let section = dataSource.sectionIdentifier(for: indexPath.section) {
                contentConfiguration.text = section.string
            }
            supplementaryView.contentConfiguration = contentConfiguration
        }
        
        let cellRegistration: UICollectionView.CellRegistration<UICollectionViewListCell, Item> = .init { cell, indexPath, identifier in
            var contentConfiguration = UIListContentConfiguration.cell()
            contentConfiguration.text = identifier.text
            cell.contentConfiguration = contentConfiguration
        }
        
        dataSource = .init(collectionView: collectionView) { collectionView, indexPath, itemIdentifier in
            collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: itemIdentifier)
        }
        guard let dataSource else {
            return
        }
        
        dataSource.supplementaryViewProvider = { collectionView, elementKind, indexPath in
            collectionView.dequeueConfiguredReusableSupplementary(using: headerCellRegistration, for: indexPath)
        }
        
        snapshot = .init()
        guard var snapshot else {
            return
        }
        snapshot.appendSections(errors.filter { !$0.value.isEmpty }.map(\.key).sorted())
        snapshot.sectionIdentifiers.forEach { core in
            if let errors = errors[core], !errors.isEmpty {
                snapshot.appendItems(errors.map {
                    .init(text: $0.localizedDescription)
                }, toSection: core)
            } else {
                snapshot.appendItems([
                    .init(text: "No issues")
                ], toSection: core)
            }
        }
        
        Task {
            await dataSource.apply(snapshot)
        }
    }
    
    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        collectionView.deselectItem(at: indexPath, animated: true)
    }
}