Files
SideStore/AltStore/Components/VibrantButton.swift
Riley Testut 654f73f4ee Shows detailed source “About” page when adding 3rd-party sources
Allows users to preview sources before adding them to their AltStore.
2024-12-26 21:15:29 +05:30

151 lines
4.5 KiB
Swift

//
// VibrantButton.swift
// AltStore
//
// Created by Riley Testut on 3/22/23.
// Copyright © 2023 Riley Testut. All rights reserved.
//
import UIKit
private let preferredFont = UIFont.boldSystemFont(ofSize: 14)
class VibrantButton: UIButton
{
var title: String? {
didSet {
if #available(iOS 15, *)
{
self.configuration?.title = self.title
}
else
{
self.setTitle(self.title, for: .normal)
}
}
}
var image: UIImage? {
didSet {
if #available(iOS 15, *)
{
self.configuration?.image = self.image
}
else
{
self.setImage(self.image, for: .normal)
}
}
}
var contentInsets: NSDirectionalEdgeInsets = .zero {
didSet {
if #available(iOS 15, *)
{
self.configuration?.contentInsets = self.contentInsets
}
else
{
self.contentEdgeInsets = UIEdgeInsets(top: self.contentInsets.top, left: self.contentInsets.leading, bottom: self.contentInsets.bottom, right: self.contentInsets.trailing)
}
}
}
override var isIndicatingActivity: Bool {
didSet {
guard #available(iOS 15, *) else { return }
self.updateConfiguration()
}
}
private let vibrancyView = UIVisualEffectView(effect: nil)
override init(frame: CGRect)
{
super.init(frame: frame)
self.initialize()
}
required init?(coder: NSCoder)
{
super.init(coder: coder)
self.initialize()
}
private func initialize()
{
let blurEffect = UIBlurEffect(style: .systemThinMaterial)
let vibrancyEffect = UIVibrancyEffect(blurEffect: blurEffect, style: .fill) // .fill is more vibrant than .secondaryLabel
if #available(iOS 15, *)
{
var backgroundConfig = UIBackgroundConfiguration.clear()
backgroundConfig.visualEffect = blurEffect
var config = UIButton.Configuration.plain()
config.cornerStyle = .capsule
config.background = backgroundConfig
config.titleTextAttributesTransformer = UIConfigurationTextAttributesTransformer { [weak self] (attributes) in
var attributes = attributes
attributes.font = preferredFont
if let self, self.isIndicatingActivity
{
// Hide title when indicating activity, but without changing intrinsicContentSize.
attributes.foregroundColor = UIColor.clear
}
return attributes
}
self.configuration = config
}
else
{
self.clipsToBounds = true
self.contentInsets = NSDirectionalEdgeInsets(top: 8, leading: 8, bottom: 8, trailing: 8) // Add padding.
let blurView = UIVisualEffectView(effect: blurEffect)
blurView.isUserInteractionEnabled = false
self.addSubview(blurView, pinningEdgesWith: .zero)
self.insertSubview(blurView, at: 0)
}
self.vibrancyView.effect = vibrancyEffect
self.vibrancyView.isUserInteractionEnabled = false
self.addSubview(self.vibrancyView, pinningEdgesWith: .zero)
}
override func layoutSubviews()
{
super.layoutSubviews()
self.layer.cornerRadius = self.bounds.midY
// Make sure content subviews are inside self.vibrancyView.contentView.
if let titleLabel = self.titleLabel, titleLabel.superview != self.vibrancyView.contentView
{
self.vibrancyView.contentView.addSubview(titleLabel)
}
if let imageView = self.imageView, imageView.superview != self.vibrancyView.contentView
{
self.vibrancyView.contentView.addSubview(imageView)
}
if self.activityIndicatorView.superview != self.vibrancyView.contentView
{
self.vibrancyView.contentView.addSubview(self.activityIndicatorView)
}
if #unavailable(iOS 15)
{
// Update font after init because the original titleLabel is replaced.
self.titleLabel?.font = preferredFont
}
}
}