Javier Cicchelli 9bcdaa697b [Setup] Basic project structure (#1)
This PR contains all the work related to setting up this project as required to implement the [Assignment](https://repo.rock-n-code.com/rock-n-code/deep-linking-assignment/wiki/Assignment) on top, as intended.

To summarise this work:
- [x] created a new **Xcode** project;
- [x] cloned the `Wikipedia` app and inserted it into the **Xcode** project;
- [x] created the `Locations` app and also, its `Libraries` package;
- [x] created the `Shared` package to share dependencies between the apps;
- [x] added a `Makefile` file and implemented some **environment** and **help** commands.

Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Reviewed-on: rock-n-code/deep-linking-assignment#1
2023-04-08 18:37:13 +00:00

103 lines
3.3 KiB
Swift

import UIKit
class IconTitleBadge: SizeThatFitsView {
enum Icon {
case sfSymbol(name: String)
case custom(name: String)
}
struct Configuration {
let title: String
let icon: Icon
}
private var iconImageView: UIImageView?
private let titleLabel = UILabel()
private let configuration: Configuration
private var theme: Theme?
init(configuration: Configuration, frame: CGRect) {
self.configuration = configuration
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func sizeThatFits(_ size: CGSize, apply: Bool) -> CGSize {
let padding = UIEdgeInsets(top: 3, left: 5, bottom: 3, right: 5)
let maximumWidth = size.width - padding.left - padding.right
var x = padding.left
var y = padding.top
let imageTitleSpacing: CGFloat = 5
var imageFrame: CGRect?
if let imageView = iconImageView {
let imageOrigin = CGPoint(x: x, y: y)
imageFrame = imageView.wmf_preferredFrame(at: imageOrigin, maximumWidth: maximumWidth, alignedBy: semanticContentAttribute, apply: apply)
x += (imageFrame?.width ?? 0) + imageTitleSpacing
}
let titleOrigin = CGPoint(x: x, y: y)
let titleFrame = titleLabel.wmf_preferredFrame(at: titleOrigin, maximumWidth: maximumWidth, alignedBy: semanticContentAttribute, apply: apply)
x += titleFrame.width + padding.right
y += max(titleFrame.height, imageFrame?.height ?? 0)
y += padding.bottom
return CGSize(width: x, height: y)
}
override func setup() {
super.setup()
titleLabel.text = configuration.title
addSubview(titleLabel)
updateFonts(with: traitCollection)
layer.cornerRadius = 3
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
updateFonts(with: traitCollection)
}
override func updateFonts(with traitCollection: UITraitCollection) {
super.updateFonts(with: traitCollection)
let font = UIFont.wmf_font(.boldSubheadline, compatibleWithTraitCollection: traitCollection)
let icon: UIImage?
switch configuration.icon {
case .sfSymbol(let symbolName):
let configuration = UIImage.SymbolConfiguration(font: font)
icon = UIImage(systemName: symbolName, withConfiguration: configuration)
case .custom(let iconName):
icon = UIImage(named: iconName)
}
titleLabel.font = font
if let icon = icon {
iconImageView?.removeFromSuperview()
let imageView = UIImageView(image: icon)
addSubview(imageView)
iconImageView = imageView
}
}
}
extension IconTitleBadge: Themeable {
func apply(theme: Theme) {
self.theme = theme
iconImageView?.tintColor = theme.colors.secondaryText
titleLabel.textColor = theme.colors.secondaryText
backgroundColor = theme.colors.baseBackground
}
}