/
AccountCell.swift
126 lines (117 loc) · 5.47 KB
/
AccountCell.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import UIKit
private func placeholderImageWithText(_ text: String) -> UIImage {
let image = UIImage(named: "Placeholder")!
UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
image.draw(at: CGPoint.zero)
defer { UIGraphicsEndImageContext() }
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
let fontSize: CGFloat = 36
let attributes: [NSAttributedStringKey: Any] = [
.font: UIFont.systemFont(ofSize: fontSize, weight: UIFont.Weight.ultraLight),
.foregroundColor: UIColor.lightGray,
.paragraphStyle: paragraphStyle,
]
let origin = CGPoint(x: 0, y: (image.size.height - fontSize) / 2 - 0.1 * fontSize)
text.draw(with: CGRect(origin: origin, size: image.size), options: .usesLineFragmentOrigin,
attributes: attributes, context: nil)
return UIGraphicsGetImageFromCurrentImageContext()!
}
private func imageForAccount(_ account: Account) -> UIImage {
switch account.issuer {
case .some("Adobe ID"): return UIImage(named: "Adobe")!
case .some("Amazon"): return UIImage(named: "Amazon")!
case .some("AWS"): return UIImage(named: "AWS")!
case .some("Backblaze"): return UIImage(named: "Backblaze")!
case .some("Bitbucket"): return UIImage(named: "Bitbucket")!
case .some("Coinbase"): return UIImage(named: "Coinbase")!
case .some("DigitalOcean"): return UIImage(named: "DigitalOcean")!
case .some("DNSimple"): return UIImage(named: "DNSimple")!
case .some("Dropbox"): return UIImage(named: "Dropbox")!
case .some("Evernote"): return UIImage(named: "Evernote")!
case .some("Facebook"): return UIImage(named: "Facebook")!
case .some("FastMail"): return UIImage(named: "FastMail")!
case .some("GitHub"): return UIImage(named: "GitHub")!
case .some("Google"): return UIImage(named: "Google")!
case .some("GreenAddress"): return UIImage(named: "GreenAddress")!
case .some("Heroku"): return UIImage(named: "Heroku")!
case .some("Hover"): return UIImage(named: "Hover")!
case .some("IFTTT"): return UIImage(named: "IFTTT")!
case .some("Intercom"): return UIImage(named: "Intercom")!
case .some("Kickstarter"): return UIImage(named: "Kickstarter")!
case .some("LinodeManager"): return UIImage(named: "Linode")!
case .some("LocalBitcoins"): return UIImage(named: "LocalBitcoins")!
case .some("Microsoft"): return UIImage(named: "Microsoft")!
case .some("Name.com"): return UIImage(named: "Name.com")!
case .some("Privacy.com"): return UIImage(named: "Privacy")!
case .some("Slack"): return UIImage(named: "Slack")!
case .some("Stripe"): return UIImage(named: "Stripe")!
case .some("Tumblr"): return UIImage(named: "Tumblr")!
case .some("www.fastmail.com"): return UIImage(named: "FastMail")!
default:
let text = String(account.description.first ?? "?").uppercased()
return placeholderImageWithText(text)
}
}
private func imageWithColor(_ color: UIColor, size: CGSize) -> UIImage {
UIGraphicsBeginImageContext(size)
color.setFill()
UIRectFill(CGRect(x: 0, y: 0, width: size.width, height: size.height))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!;
}
private func formattedValue(_ value: String) -> String {
let length = value.count
let prefix = String(value.prefix(length / 2))
let suffix = String(value.suffix(length - length / 2))
return "\(prefix) \(suffix)"
}
final class AccountCell: UITableViewCell {
@IBOutlet weak var accountImageView: UIImageView!
@IBOutlet weak var valueLabel: UILabel!
@IBOutlet weak var identifierLabel: UILabel!
var delegate: AccountUpdateDelegate?
fileprivate let button = UIButton(type: .custom)
fileprivate let progressView = CircularProgressView()
var account: Account! {
didSet {
accessoryView = account.password.timeBased ? progressView : button
let now = Date()
updateWithDate(now)
}
}
override func awakeFromNib() {
let featureSettings: [[UIFontDescriptor.FeatureKey: Any]] =
[[.featureIdentifier: kNumberSpacingType, .typeIdentifier: kMonospacedNumbersSelector]]
let fontDescriptor = valueLabel.font.fontDescriptor.addingAttributes([.featureSettings: featureSettings])
valueLabel.font = UIFont(descriptor: fontDescriptor, size: 0)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 13)
button.setTitle("NEXT", for: UIControlState())
button.setTitleColor(tintColor, for: UIControlState())
button.setTitleColor(UIColor.white, for: .highlighted)
button.setTitleColor(UIColor.white, for: .selected)
button.layer.borderColor = button.tintColor.cgColor
button.layer.borderWidth = 1
button.layer.cornerRadius = 4
button.contentEdgeInsets = UIEdgeInsets(top: 5, left: 10, bottom: 5, right: 10)
button.sizeToFit()
let image = imageWithColor(tintColor, size: button.bounds.size)
button.setBackgroundImage(image, for: .highlighted)
button.setBackgroundImage(image, for: .selected)
button.clipsToBounds = true
button.addTarget(self, action: #selector(didPressButton(_:)), for: .touchUpInside)
}
@objc func didPressButton(_ sender: UIButton) {
account.password.counter += 1
delegate?.updateAccount(account)
}
func updateWithDate(_ date: Date) {
accountImageView.image = imageForAccount(account)
valueLabel.text = formattedValue(account.password.valueForDate(date))
identifierLabel.text = account.description
progressView.progress = account.password.progressForDate(date)
progressView.tintColor = account.password.timeIntervalRemainingForDate(date) < 5 ?
.red : tintColor
}
}