// // AppScreenshotCollectionViewCell.swift // AltStore // // Created by Riley Testut on 10/11/23. // Copyright © 2023 Riley Testut. All rights reserved. // import UIKit import AltStoreCore extension AppScreenshotCollectionViewCell { private class ImageView: UIImageView { override func layoutSubviews() { super.layoutSubviews() // Explicitly layout cell to ensure rounded corners are accurate. self.superview?.superview?.setNeedsLayout() } } } class AppScreenshotCollectionViewCell: UICollectionViewCell { let imageView: UIImageView var aspectRatio: CGSize = AppScreenshot.defaultAspectRatio { didSet { self.updateAspectRatio() } } private var isRounded: Bool = false { didSet { self.setNeedsLayout() self.layoutIfNeeded() } } private var aspectRatioConstraint: NSLayoutConstraint? override init(frame: CGRect) { self.imageView = ImageView(frame: .zero) self.imageView.clipsToBounds = true self.imageView.layer.cornerCurve = .continuous self.imageView.layer.borderColor = UIColor.tertiaryLabel.cgColor super.init(frame: frame) self.imageView.translatesAutoresizingMaskIntoConstraints = false self.contentView.addSubview(self.imageView) let widthConstraint = self.imageView.widthAnchor.constraint(equalTo: self.contentView.widthAnchor) widthConstraint.priority = .defaultHigh let heightConstraint = self.imageView.heightAnchor.constraint(equalTo: self.contentView.heightAnchor) heightConstraint.priority = .defaultHigh NSLayoutConstraint.activate([ widthConstraint, heightConstraint, self.imageView.widthAnchor.constraint(lessThanOrEqualTo: self.contentView.widthAnchor), self.imageView.heightAnchor.constraint(lessThanOrEqualTo: self.contentView.heightAnchor), self.imageView.centerXAnchor.constraint(equalTo: self.contentView.centerXAnchor), self.imageView.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor) ]) self.updateAspectRatio() self.updateTraits() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) self.updateTraits() } override func layoutSubviews() { super.layoutSubviews() if self.isRounded { let cornerRadius = self.imageView.bounds.width / 9.0 // Based on iPhone 15 self.imageView.layer.cornerRadius = cornerRadius } else { self.imageView.layer.cornerRadius = 5 } } } extension AppScreenshotCollectionViewCell { func setImage(_ image: UIImage?) { guard var image, let cgImage = image.cgImage else { self.imageView.image = image return } if image.size.width > image.size.height && self.aspectRatio.width < self.aspectRatio.height { // Image is landscape, but cell has portrait aspect ratio, so rotate image to match. image = UIImage(cgImage: cgImage, scale: image.scale, orientation: .right) } self.imageView.image = image } } private extension AppScreenshotCollectionViewCell { func updateAspectRatio() { self.aspectRatioConstraint?.isActive = false self.aspectRatioConstraint = self.imageView.widthAnchor.constraint(equalTo: self.imageView.heightAnchor, multiplier: self.aspectRatio.width / self.aspectRatio.height) self.aspectRatioConstraint?.isActive = true let aspectRatio: Double if self.aspectRatio.width > self.aspectRatio.height { aspectRatio = self.aspectRatio.height / self.aspectRatio.width } else { aspectRatio = self.aspectRatio.width / self.aspectRatio.height } let tolerance = 0.001 as Double let modernAspectRatio = AppScreenshot.defaultAspectRatio.width / AppScreenshot.defaultAspectRatio.height let isRounded = (aspectRatio >= modernAspectRatio - tolerance) && (aspectRatio <= modernAspectRatio + tolerance) self.isRounded = isRounded } func updateTraits() { let displayScale = (self.traitCollection.displayScale == 0.0) ? 1.0 : self.traitCollection.displayScale self.imageView.layer.borderWidth = 1.0 / displayScale } }