Tusker/Tusker/Screens/Fast Account Switcher/FastSwitchingAccountView.swift

174 lines
6.5 KiB
Swift
Raw Normal View History

2020-11-10 00:39:42 +00:00
//
// FastSwitchingAccountView.swift
// Tusker
//
// Created by Shadowfacts on 11/4/20.
// Copyright © 2020 Shadowfacts. All rights reserved.
//
import UIKit
import UserAccounts
import WebURL
2020-11-10 00:39:42 +00:00
class FastSwitchingAccountView: UIView {
private lazy var selectedColor = UIColor { [unowned self] (traits) in
var hue: CGFloat = 0
var saturation: CGFloat = 0
var brightness: CGFloat = 0
var alpha: CGFloat = 0
self.tintColor.resolvedColor(with: traits).getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha)
brightness = min(1, brightness + 0.4)
saturation = max(0, saturation - 0.3)
return UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: alpha)
2020-11-10 00:39:42 +00:00
}
private lazy var currentColor = UIColor { [unowned self] (traits) in
var hue: CGFloat = 0
var saturation: CGFloat = 0
var brightness: CGFloat = 0
var alpha: CGFloat = 0
self.tintColor.resolvedColor(with: traits).getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha)
brightness = min(1, brightness + 0.3)
saturation = max(0, saturation - 0.2)
return UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: alpha)
2020-11-10 00:39:42 +00:00
}
var isSelected = false {
didSet {
updateLabelColors()
}
}
var isCurrent = false {
didSet {
updateLabelColors()
}
}
2022-05-01 15:53:12 +00:00
private let orientation: FastAccountSwitcherViewController.ItemOrientation
2020-11-10 00:39:42 +00:00
private let usernameLabel = UILabel()
private let instanceLabel = UILabel()
private let avatarImageView = UIImageView()
2020-11-10 00:39:42 +00:00
private var avatarRequest: ImageCache.Request?
init(account: UserAccountInfo, orientation: FastAccountSwitcherViewController.ItemOrientation) {
2022-05-01 15:53:12 +00:00
self.orientation = orientation
2020-11-10 00:39:42 +00:00
super.init(frame: .zero)
commonInit()
setupAccount(account: account)
}
2022-05-01 15:53:12 +00:00
init(orientation: FastAccountSwitcherViewController.ItemOrientation) {
self.orientation = orientation
super.init(frame: .zero)
commonInit()
setupPlaceholder()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func commonInit() {
2020-11-10 00:39:42 +00:00
usernameLabel.textColor = .white
usernameLabel.font = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: .headline), size: 0)
instanceLabel.textColor = .white
instanceLabel.font = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: .subheadline), size: 0)
let stackView = UIStackView(arrangedSubviews: [
usernameLabel,
instanceLabel
])
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
addSubview(stackView)
avatarImageView.translatesAutoresizingMaskIntoConstraints = false
avatarImageView.layer.masksToBounds = true
avatarImageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadiusFraction * 40
avatarImageView.layer.cornerCurve = .continuous
2020-11-10 00:39:42 +00:00
avatarImageView.image = UIImage(systemName: Preferences.shared.avatarStyle == .circle ? "person.crop.circle" : "person.crop.square")
// todo: this should really be fit, but somehow the image view ends up being 37pt tall?
avatarImageView.contentMode = .scaleAspectFill
2020-11-10 00:39:42 +00:00
addSubview(avatarImageView)
NSLayoutConstraint.activate([
avatarImageView.topAnchor.constraint(equalTo: topAnchor, constant: 8),
avatarImageView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8),
avatarImageView.widthAnchor.constraint(equalToConstant: 40),
avatarImageView.heightAnchor.constraint(equalTo: avatarImageView.widthAnchor),
stackView.centerYAnchor.constraint(equalTo: avatarImageView.centerYAnchor),
])
2022-05-01 15:53:12 +00:00
switch orientation {
case .iconsLeading:
stackView.alignment = .leading
NSLayoutConstraint.activate([
avatarImageView.leadingAnchor.constraint(equalTo: leadingAnchor),
stackView.leadingAnchor.constraint(equalTo: avatarImageView.trailingAnchor, constant: 8),
stackView.trailingAnchor.constraint(equalTo: trailingAnchor),
])
case .iconsTrailing:
stackView.alignment = .trailing
NSLayoutConstraint.activate([
avatarImageView.trailingAnchor.constraint(equalTo: trailingAnchor),
stackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 8),
stackView.trailingAnchor.constraint(equalTo: avatarImageView.leadingAnchor, constant: -8),
])
}
updateLabelColors()
isAccessibilityElement = true
}
private func setupAccount(account: UserAccountInfo) {
usernameLabel.text = account.username
if let domain = WebURL.Domain(account.instanceURL.host!) {
instanceLabel.text = domain.render(.uncheckedUnicodeString)
} else {
instanceLabel.text = account.instanceURL.host!
}
2020-11-10 00:39:42 +00:00
let controller = MastodonController.getForAccount(account)
controller.getOwnAccount { [weak self] (result) in
guard let self = self,
case let .success(account) = result,
let avatar = account.avatar else { return }
self.avatarRequest = ImageCache.avatars.get(avatar) { [weak self] (_, image) in
guard let self = self, let image = image else { return }
2020-11-10 00:39:42 +00:00
DispatchQueue.main.async {
self.avatarImageView.image = image
2020-11-10 00:39:42 +00:00
}
}
}
accessibilityLabel = "\(account.username!)@\(instanceLabel.text!)"
2020-11-10 00:39:42 +00:00
}
private func setupPlaceholder() {
usernameLabel.text = "Add Account"
instanceLabel.isHidden = true
avatarImageView.image = UIImage(systemName: "plus")
accessibilityLabel = "Add Account"
2020-11-10 00:39:42 +00:00
}
private func updateLabelColors() {
let color: UIColor
if isSelected {
color = selectedColor
2020-11-10 00:39:42 +00:00
} else if isCurrent {
color = currentColor
2020-11-10 00:39:42 +00:00
} else {
color = .white
}
usernameLabel.textColor = color
instanceLabel.textColor = color
avatarImageView.tintColor = color
2020-11-10 00:39:42 +00:00
}
}