Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
signalapp
GitHub Repository: signalapp/Signal-iOS
Path: blob/main/Signal/src/View Supplements/ContextualActionBuilder.swift
1 views
//
// Copyright 2025 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//

import SignalServiceKit
import UIKit

enum ContextualActionBuilder {
    typealias Handler = (_ completion: @escaping (_ success: Bool) -> Void) -> Void

    static func makeContextualAction(
        style: UIContextualAction.Style,
        color: UIColor,
        imageName: String,
        title: String,
        handler: @escaping Handler,
    ) -> UIContextualAction {
        return makeContextualAction(
            style: style,
            color: color,
            image: UIImage(named: imageName),
            title: title,
            handler: handler,
        )
    }

    static func makeContextualAction(
        style: UIContextualAction.Style,
        color: UIColor,
        image: UIImage?,
        title: String,
        handler: @escaping Handler,
    ) -> UIContextualAction {
        // We want to always show a title with the icon. iOS 26 does this by
        // default, but previous iOS versions only does when the cell's
        // height > 91, so we generate an image with the text below it.
        if #available(iOS 26, *) {
            let action = UIContextualAction(
                style: style,
                title: title,
            ) { _, _, completion in
                handler(completion)
            }
            action.backgroundColor = color
            action.image = image
            return action
        } else {
            let action = UIContextualAction(
                style: style,
                title: nil,
            ) { _, _, completion in
                handler(completion)
            }
            action.accessibilityLabel = title
            action.backgroundColor = color
            action.image = image?.withTitle(
                title,
                font: .dynamicTypeFootnote.medium(),
                color: .ows_white,
                maxTitleWidth: 68,
                minimumScaleFactor: CGFloat(8) / CGFloat(13),
                spacing: 4,
            )?.withRenderingMode(.alwaysTemplate)

            return action
        }
    }
}