Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/Folium-iOS/Extensions/UIButton.swift
2 views
//
//  UIButton.swift
//  Folium-iOS
//
//  Created by Jarrod Norwell on 17/11/2025.
//

import ColourKit
import Foundation
import UIKit

typealias Actions = (touchDown: (UIAction) async -> Void, touchUpInside: (UIAction) async -> Void)

extension UIButton {
    static func button(with configuration: Configuration, actions: Actions, _ menu: UIMenu? = nil) -> UIButton {
        let button: UIButton = .init(configuration: configuration)
        button.translatesAutoresizingMaskIntoConstraints = false
        if let menu {
            button.menu = menu
            button.showsMenuAsPrimaryAction = true
        } else {
            button.addAction(.init(handler: { action in
                Task {
                    await actions.touchDown(action)
                }
            }), for: .touchDown)
            button.addAction(.init(handler: { action in
                Task {
                    await actions.touchUpInside(action)
                }
            }), for: .touchUpInside)
        }
        
        if #unavailable(iOS 26) {
            button.layer.shadowColor = UIColour.black.cgColor
            button.layer.shadowOpacity = 1 / 5
            button.layer.shadowRadius = 20
            button.layer.shadowOffset = .init(width: 0, height: 10)
        }
        
        let buttonTransparency: Double = UserDefaults.standard.double(forKey: "folium.v1.38.buttonTransparency")
        if buttonTransparency >= 0 {
            button.alpha = buttonTransparency
        }
        
        return button
    }
}

@available(iOS 26, *)
extension UIButton.Configuration {
    static func glassConfiguration(_ size: Size, _ cornerStyle: CornerStyle,
                                   _ image: UIImage? = nil, _ scale: UIImage.SymbolScale = .large) -> UIButton.Configuration {
        var configuration: UIButton.Configuration = .glass()
        configuration.buttonSize = size
        configuration.cornerStyle = cornerStyle
        configuration.image = image?
            .applyingSymbolConfiguration(.init(scale: scale))?
            .applyingSymbolConfiguration(.init(weight: .bold))
        
        let expandButtonByDouble = UserDefaults.standard.double(forKey: "folium.v1.38.expandButtonsBy")
        let expandButtonBy: CGFloat = size == .medium ? CGFloat(expandButtonByDouble) : CGFloat(expandButtonByDouble * 2)
        if expandButtonBy >  0 {
            configuration.contentInsets = NSDirectionalEdgeInsets(top: expandButtonBy, leading: expandButtonBy,
                                                                  bottom: expandButtonBy, trailing: expandButtonBy)
        }
        
        return configuration
    }
}

extension UIButton.Configuration {
    static func filledConfiguration(_ size: Size, _ cornerStyle: CornerStyle,
                                    _ image: UIImage? = nil, _ scale: UIImage.SymbolScale = .large) -> UIButton.Configuration {
        var configuration: UIButton.Configuration = .filled()
        configuration.baseBackgroundColor = .label
        configuration.baseForegroundColor = .systemBackground
        configuration.buttonSize = size
        configuration.cornerStyle = cornerStyle
        configuration.image = image?
            .applyingSymbolConfiguration(.init(scale: scale))?
            .applyingSymbolConfiguration(.init(weight: .bold))
        
        let expandButtonByDouble = UserDefaults.standard.double(forKey: "folium.v1.38.expandButtonsBy")
        let expandButtonBy: CGFloat = size == .medium ? CGFloat(expandButtonByDouble) : CGFloat(expandButtonByDouble * 2)
        if expandButtonBy >  0 {
            configuration.contentInsets = NSDirectionalEdgeInsets(top: expandButtonBy, leading: expandButtonBy,
                                                                  bottom: expandButtonBy, trailing: expandButtonBy)
        }
        
        return configuration
    }
}

extension UIButton.Configuration {
    static func configuration(_ size: Size, _ cornerStyle: CornerStyle,
                              _ image: UIImage? = nil, _ scale: UIImage.SymbolScale = .large) -> UIButton.Configuration {
        if #available(iOS 26, *) {
            glassConfiguration(size, cornerStyle, image, scale)
        } else {
            filledConfiguration(size, cornerStyle, image, scale)
        }
    }
}