mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-10 07:13:28 +01:00
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// InstalledAppsCollectionHeaderView.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 3/9/20.
|
||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
final class InstalledAppsCollectionHeaderView: UICollectionReusableView {
|
||||
let textLabel: UILabel
|
||||
let button: UIButton
|
||||
|
||||
override init(frame: CGRect) {
|
||||
textLabel = UILabel()
|
||||
textLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
textLabel.font = UIFont.systemFont(ofSize: 24, weight: .bold)
|
||||
textLabel.accessibilityTraits.insert(.header)
|
||||
|
||||
button = UIButton(type: .system)
|
||||
button.translatesAutoresizingMaskIntoConstraints = false
|
||||
button.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .medium)
|
||||
|
||||
super.init(frame: frame)
|
||||
|
||||
addSubview(textLabel)
|
||||
addSubview(button)
|
||||
|
||||
NSLayoutConstraint.activate([textLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor),
|
||||
textLabel.bottomAnchor.constraint(equalTo: bottomAnchor)])
|
||||
|
||||
NSLayoutConstraint.activate([button.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor),
|
||||
button.firstBaselineAnchor.constraint(equalTo: textLabel.firstBaselineAnchor)])
|
||||
|
||||
preservesSuperviewLayoutMargins = true
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder _: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
//
|
||||
// MyAppsComponents.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 7/17/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import RoxasUIKit
|
||||
import UIKit
|
||||
|
||||
@objc
|
||||
final class InstalledAppCollectionViewCell: UICollectionViewCell {
|
||||
private(set) var deactivateBadge: UIView?
|
||||
|
||||
@IBOutlet var bannerView: AppBannerView!
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
contentView.preservesSuperviewLayoutMargins = true
|
||||
|
||||
if #available(iOS 13.0, *) {
|
||||
let deactivateBadge = UIView()
|
||||
deactivateBadge.translatesAutoresizingMaskIntoConstraints = false
|
||||
deactivateBadge.isHidden = true
|
||||
self.addSubview(deactivateBadge)
|
||||
|
||||
// Solid background to make the X opaque white.
|
||||
let backgroundView = UIView()
|
||||
backgroundView.translatesAutoresizingMaskIntoConstraints = false
|
||||
backgroundView.backgroundColor = .white
|
||||
deactivateBadge.addSubview(backgroundView)
|
||||
|
||||
let badgeView = UIImageView(image: UIImage(systemName: "xmark.circle.fill"))
|
||||
badgeView.preferredSymbolConfiguration = UIImage.SymbolConfiguration(scale: .large)
|
||||
badgeView.tintColor = .systemRed
|
||||
deactivateBadge.addSubview(badgeView, pinningEdgesWith: .zero)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
deactivateBadge.centerXAnchor.constraint(equalTo: self.bannerView.iconImageView.trailingAnchor),
|
||||
deactivateBadge.centerYAnchor.constraint(equalTo: self.bannerView.iconImageView.topAnchor),
|
||||
|
||||
backgroundView.centerXAnchor.constraint(equalTo: badgeView.centerXAnchor),
|
||||
backgroundView.centerYAnchor.constraint(equalTo: badgeView.centerYAnchor),
|
||||
backgroundView.widthAnchor.constraint(equalTo: badgeView.widthAnchor, multiplier: 0.5),
|
||||
backgroundView.heightAnchor.constraint(equalTo: badgeView.heightAnchor, multiplier: 0.5)
|
||||
])
|
||||
|
||||
self.deactivateBadge = deactivateBadge
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
final class InstalledAppsCollectionFooterView: UICollectionReusableView {
|
||||
@IBOutlet var textLabel: UILabel!
|
||||
@IBOutlet var button: UIButton!
|
||||
}
|
||||
|
||||
@objc
|
||||
final class NoUpdatesCollectionViewCell: UICollectionViewCell {
|
||||
@IBOutlet var blurView: UIVisualEffectView!
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
contentView.preservesSuperviewLayoutMargins = true
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
final class UpdatesCollectionHeaderView: UICollectionReusableView {
|
||||
let button = PillButton(type: .system)
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
button.translatesAutoresizingMaskIntoConstraints = false
|
||||
button.setTitle(">", for: .normal)
|
||||
addSubview(button)
|
||||
|
||||
NSLayoutConstraint.activate([button.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20),
|
||||
button.topAnchor.constraint(equalTo: topAnchor),
|
||||
button.widthAnchor.constraint(equalToConstant: 50),
|
||||
button.heightAnchor.constraint(equalToConstant: 26)])
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder _: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,94 @@
|
||||
//
|
||||
// UpdateCollectionViewCell.swift
|
||||
// AltStore
|
||||
//
|
||||
// Created by Riley Testut on 7/16/19.
|
||||
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
extension UpdateCollectionViewCell {
|
||||
enum Mode {
|
||||
case collapsed
|
||||
case expanded
|
||||
}
|
||||
}
|
||||
|
||||
@objc final class UpdateCollectionViewCell: UICollectionViewCell {
|
||||
var mode: Mode = .expanded {
|
||||
didSet {
|
||||
update()
|
||||
}
|
||||
}
|
||||
|
||||
@IBOutlet var bannerView: AppBannerView!
|
||||
@IBOutlet var versionDescriptionTitleLabel: UILabel!
|
||||
@IBOutlet var versionDescriptionTextView: CollapsingTextView!
|
||||
|
||||
@IBOutlet private var blurView: UIVisualEffectView!
|
||||
|
||||
private var originalTintColor: UIColor?
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
// Prevent temporary unsatisfiable constraint errors due to UIView-Encapsulated-Layout constraints.
|
||||
contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
contentView.preservesSuperviewLayoutMargins = true
|
||||
|
||||
bannerView.backgroundEffectView.isHidden = true
|
||||
bannerView.button.setTitle(NSLocalizedString("UPDATE", comment: ""), for: .normal)
|
||||
|
||||
blurView.layer.cornerRadius = 20
|
||||
blurView.layer.masksToBounds = true
|
||||
|
||||
update()
|
||||
}
|
||||
|
||||
override func tintColorDidChange() {
|
||||
super.tintColorDidChange()
|
||||
|
||||
if tintAdjustmentMode != .dimmed {
|
||||
originalTintColor = tintColor
|
||||
}
|
||||
|
||||
update()
|
||||
}
|
||||
|
||||
override func apply(_: UICollectionViewLayoutAttributes) {
|
||||
// Animates transition to new attributes.
|
||||
let animator = UIViewPropertyAnimator(springTimingParameters: UISpringTimingParameters()) {
|
||||
self.layoutIfNeeded()
|
||||
}
|
||||
animator.startAnimation()
|
||||
}
|
||||
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
let view = super.hitTest(point, with: event)
|
||||
|
||||
if view == versionDescriptionTextView {
|
||||
// Forward touches on the text view (but not on the nested "more" button)
|
||||
// so cell selection works as expected.
|
||||
return self
|
||||
} else {
|
||||
return view
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension UpdateCollectionViewCell {
|
||||
func update() {
|
||||
switch mode {
|
||||
case .collapsed: versionDescriptionTextView.isCollapsed = true
|
||||
case .expanded: versionDescriptionTextView.isCollapsed = false
|
||||
}
|
||||
|
||||
versionDescriptionTitleLabel.textColor = originalTintColor ?? tintColor
|
||||
blurView.backgroundColor = originalTintColor ?? tintColor
|
||||
bannerView.button.progressTintColor = originalTintColor ?? tintColor
|
||||
|
||||
setNeedsLayout()
|
||||
layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user