@@ -15,6 +15,13 @@ class GoalCollectionViewCell: UICollectionViewCell {
1515 let todaytaLabel : BSLabel = BSLabel ( )
1616 let thumbnailImageView = GoalImageView ( isThumbnail: true )
1717 let safesumLabel : BSLabel = BSLabel ( )
18+ lazy var dueByDeltasLabel : BSLabel = {
19+ let label = BSLabel ( )
20+ label. textAlignment = NSTextAlignment . center
21+ label. font = UIFont . beeminder. defaultBoldFont. withSize ( 13 )
22+ label. numberOfLines = 0
23+ return label
24+ } ( )
1825 let margin = 8
1926 override init ( frame: CGRect ) {
2027 super. init ( frame: frame)
@@ -23,6 +30,7 @@ class GoalCollectionViewCell: UICollectionViewCell {
2330 self . contentView. addSubview ( self . todaytaLabel)
2431 self . contentView. addSubview ( self . thumbnailImageView)
2532 self . contentView. addSubview ( self . safesumLabel)
33+ self . contentView. addSubview ( self . dueByDeltasLabel)
2634 self . contentView. backgroundColor = . systemBackground
2735
2836 self . slugLabel. font = UIFont . beeminder. defaultFontHeavy
@@ -64,6 +72,11 @@ class GoalCollectionViewCell: UICollectionViewCell {
6472 make. centerY. equalTo ( self . thumbnailImageView. snp. centerY)
6573 make. right. equalTo ( - self . margin)
6674 }
75+ self . dueByDeltasLabel. snp. makeConstraints { make in
76+ make. left. equalTo ( self . thumbnailImageView. snp. right) . offset ( 5 )
77+ make. top. equalTo ( self . safesumLabel. snp. bottom) . offset ( 6 )
78+ make. right. equalTo ( - self . margin)
79+ }
6780 }
6881 required init ? ( coder aDecoder: NSCoder ) { super. init ( coder: aDecoder) }
6982 override func prepareForReuse( ) {
@@ -78,5 +91,33 @@ class GoalCollectionViewCell: UICollectionViewCell {
7891 self . todaytaLabel. text = goal? . todayta == true ? " ✓ " : " "
7992 self . safesumLabel. text = goal? . capitalSafesum ( )
8093 self . safesumLabel. textColor = goal? . countdownColor ?? UIColor . Beeminder. gray
94+ self . dueByDeltasLabel. attributedText = goal? . dueByTableAttributedString
95+ self . dueByDeltasLabel. isHidden = goal == nil || goal? . dueByContainsSpecificAmounts == false
96+ }
97+ }
98+
99+ extension Goal {
100+ fileprivate var dueByContainsSpecificAmounts : Bool {
101+ self . dueBy. values. map { $0. formattedDelta } . joined ( separator: " " ) . contains ( where: { $0. isNumber } )
102+ }
103+ fileprivate var dueByTableAttributedString : NSAttributedString {
104+ let textAndColor : [ ( text: String , color: UIColor ) ] = dueBy. sorted ( using: SortDescriptor ( \. key) ) . compactMap ( {
105+ $0. value. formattedDelta
106+ } ) . map { $0 == " ✔ " ? " ✓ " : $0 } . enumerated ( ) . map { offset, element in
107+ var color : UIColor {
108+ switch offset {
109+ case 0 : return UIColor . Beeminder. SafetyBuffer. orange
110+ case 1 : return UIColor . Beeminder. SafetyBuffer. blue
111+ case 2 : return UIColor . Beeminder. SafetyBuffer. green
112+ default : return . label. withAlphaComponent ( 0.8 )
113+ }
114+ }
115+ return ( text: element, color: color)
116+ }
117+ let attrStr = NSMutableAttributedString ( )
118+ textAndColor. map { ( text: String , color: UIColor ) in
119+ NSAttributedString ( string: text + " " , attributes: [ . foregroundColor: color] )
120+ } . forEach { attrStr. append ( $0) }
121+ return attrStr
81122 }
82123}
0 commit comments