session-ios/SessionUIKit/Components/SessionButton.swift

198 lines
6 KiB
Swift

// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import UIKit
public final class SessionButton: UIButton {
public enum Style {
case bordered
case borderless
case destructive
case destructiveBorderless
case filled
}
public enum Size {
case small
case medium
case large
}
public struct Info {
public let style: Style
public let title: String
public let isEnabled: Bool
public let onTap: () -> ()
public init(
style: Style,
title: String,
isEnabled: Bool,
onTap: @escaping () -> ()
) {
self.style = style
self.title = title
self.isEnabled = isEnabled
self.onTap = onTap
}
}
private let style: Style
public override var isEnabled: Bool {
didSet {
guard isEnabled else {
setThemeTitleColor(
{
switch style {
case .bordered, .borderless, .destructive,
.destructiveBorderless:
return .disabled
case .filled: return .white
}
}(),
for: .normal
)
setThemeBackgroundColor(
{
switch style {
case .bordered, .borderless, .destructive,
.destructiveBorderless:
return .clear
case .filled: return .disabled
}
}(),
for: .normal
)
setThemeBackgroundColor(nil, for: .highlighted)
themeBorderColor = {
switch style {
case .bordered, .destructive: return .disabled
case .filled, .borderless, .destructiveBorderless: return nil
}
}()
return
}
// If we enable the button they just re-apply the existing style
setup(style: style)
}
}
// MARK: - Initialization
public init(style: Style, size: Size) {
self.style = style
super.init(frame: .zero)
setup(size: size)
setup(style: style)
}
override init(frame: CGRect) {
preconditionFailure("Use init(style:) instead.")
}
required init?(coder: NSCoder) {
preconditionFailure("Use init(style:) instead.")
}
private func setup(size: Size) {
clipsToBounds = true
contentEdgeInsets = UIEdgeInsets(
top: 0,
left: Values.largeSpacing,
bottom: 0,
right: Values.largeSpacing
)
titleLabel?.font = .boldSystemFont(ofSize: (size == .small ?
Values.smallFontSize :
Values.mediumFontSize
))
let height: CGFloat = {
switch size {
case .small: return Values.smallButtonHeight
case .medium: return Values.mediumButtonHeight
case .large: return Values.largeButtonHeight
}
}()
set(.height, to: height)
layer.cornerRadius = {
switch style {
case .borderless, .destructiveBorderless: return 5
default: return (height / 2)
}
}()
}
private func setup(style: Style) {
setThemeTitleColor(
{
switch style {
case .bordered, .borderless: return .sessionButton_text
case .destructive, .destructiveBorderless: return .sessionButton_destructiveText
case .filled: return .sessionButton_filledText
}
}(),
for: .normal
)
setThemeTitleColor(
{
switch style {
case .borderless: return .highlighted(.sessionButton_text)
case .destructiveBorderless: return .highlighted(.sessionButton_destructiveText)
case .bordered, .destructive, .filled: return nil
}
}(),
for: .highlighted
)
setThemeBackgroundColor(
{
switch style {
case .bordered: return .sessionButton_background
case .destructive: return .sessionButton_destructiveBackground
case .borderless, .destructiveBorderless: return .clear
case .filled: return .sessionButton_filledBackground
}
}(),
for: .normal
)
setThemeBackgroundColor(
{
switch style {
case .bordered: return .sessionButton_highlight
case .destructive: return .sessionButton_destructiveHighlight
case .borderless, .destructiveBorderless: return nil
case .filled: return .sessionButton_filledHighlight
}
}(),
for: .highlighted
)
layer.borderWidth = {
switch style {
case .borderless, .destructiveBorderless: return 0
default: return 1
}
}()
themeBorderColor = {
switch style {
case .bordered: return .sessionButton_border
case .destructive: return .sessionButton_destructiveBorder
case .filled, .borderless, .destructiveBorderless: return nil
}
}()
}
// MARK: - Functions
public func setStyle(_ style: Style) {
setup(style: style)
}
}