@@ -16,6 +16,15 @@ class GoalCollectionViewCell: UICollectionViewCell {
1616 let todaytaLabel : BSLabel = BSLabel ( )
1717 let thumbnailImageView = GoalImageView ( isThumbnail: true )
1818 let safesumLabel : BSLabel = BSLabel ( )
19+
20+ lazy var dueByDeltasLabel : BSLabel = {
21+ let label = BSLabel ( )
22+ label. textAlignment = NSTextAlignment . center
23+ label. font = UIFont . beeminder. defaultBoldFont. withSize ( 13 )
24+ label. numberOfLines = 0
25+ return label
26+ } ( )
27+
1928 let margin = 8
2029
2130 override init ( frame: CGRect ) {
@@ -26,6 +35,7 @@ class GoalCollectionViewCell: UICollectionViewCell {
2635 self . contentView. addSubview ( self . todaytaLabel)
2736 self . contentView. addSubview ( self . thumbnailImageView)
2837 self . contentView. addSubview ( self . safesumLabel)
38+ self . contentView. addSubview ( self . dueByDeltasLabel)
2939 self . contentView. backgroundColor = . systemBackground
3040
3141 self . slugLabel. font = UIFont . beeminder. defaultFontHeavy
@@ -69,6 +79,12 @@ class GoalCollectionViewCell: UICollectionViewCell {
6979 make. centerY. equalTo ( self . thumbnailImageView. snp. centerY)
7080 make. right. equalTo ( - self . margin)
7181 }
82+
83+ self . dueByDeltasLabel. snp. makeConstraints { ( make) -> Void in
84+ make. left. equalTo ( self . thumbnailImageView. snp. right) . offset ( 5 )
85+ make. top. equalTo ( self . safesumLabel. snp. bottom) . offset ( 6 )
86+ make. right. equalTo ( - self . margin)
87+ }
7288 }
7389
7490 required init ? ( coder aDecoder: NSCoder ) {
@@ -89,5 +105,46 @@ class GoalCollectionViewCell: UICollectionViewCell {
89105 self . todaytaLabel. text = goal? . todayta == true ? " ✓ " : " "
90106 self . safesumLabel. text = goal? . capitalSafesum ( )
91107 self . safesumLabel. textColor = goal? . countdownColor ?? UIColor . Beeminder. gray
108+ self . dueByDeltasLabel. attributedText = goal? . dueByTableAttributedString
109+ self . dueByDeltasLabel. isHidden = goal == nil || goal? . dueByContainsSpecificAmounts == false
110+ }
111+ }
112+
113+
114+ private extension Goal {
115+ var dueByContainsSpecificAmounts : Bool {
116+ self . dueBy. values. map { $0. formattedDelta }
117+ . joined ( separator: " " )
118+ . contains ( where: { $0. isNumber } )
119+ }
120+
121+ var dueByTableAttributedString : NSAttributedString {
122+ let textAndColor : [ ( text: String , color: UIColor ) ] = dueBy
123+ . sorted ( using: SortDescriptor ( \. key) )
124+ . compactMap ( { $0. value. formattedDelta } )
125+ . map { $0 == " ✔ " ? " ✓ " : $0 }
126+ . enumerated ( )
127+ . map { offset, element in
128+ var color : UIColor {
129+ switch offset {
130+ case 0 : return UIColor . Beeminder. SafetyBuffer. orange
131+ case 1 : return UIColor . Beeminder. SafetyBuffer. blue
132+ case 2 : return UIColor . Beeminder. SafetyBuffer. green
133+ default : return . label. withAlphaComponent ( 0.8 )
134+ }
135+ }
136+ return ( text: element, color: color)
137+ }
138+
139+ let attrStr = NSMutableAttributedString ( )
140+
141+ textAndColor
142+ . map { ( text: String , color: UIColor ) in
143+ NSAttributedString ( string: text + " " , attributes: [ . foregroundColor: color] )
144+ }
145+ . forEach { attrStr. append ( $0) }
146+
147+ return attrStr
92148 }
93149}
150+
0 commit comments