From e38728e9858b4159a343a6378a5df09a94e0dac4 Mon Sep 17 00:00:00 2001 From: krugerk <4656811+krugerk@users.noreply.github.com> Date: Tue, 10 Dec 2024 23:34:57 +0100 Subject: [PATCH 1/2] showing due by deltas on the gallery in the goal cells related to #209 --- BeeSwift/Cells/GoalCollectionViewCell.swift | 41 +++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/BeeSwift/Cells/GoalCollectionViewCell.swift b/BeeSwift/Cells/GoalCollectionViewCell.swift index 8546baffa..2f1c312b9 100644 --- a/BeeSwift/Cells/GoalCollectionViewCell.swift +++ b/BeeSwift/Cells/GoalCollectionViewCell.swift @@ -15,6 +15,13 @@ class GoalCollectionViewCell: UICollectionViewCell { let todaytaLabel: BSLabel = BSLabel() let thumbnailImageView = GoalImageView(isThumbnail: true) let safesumLabel: BSLabel = BSLabel() + lazy var dueByDeltasLabel: BSLabel = { + let label = BSLabel() + label.textAlignment = NSTextAlignment.center + label.font = UIFont.beeminder.defaultBoldFont.withSize(13) + label.numberOfLines = 0 + return label + }() let margin = 8 override init(frame: CGRect) { super.init(frame: frame) @@ -23,6 +30,7 @@ class GoalCollectionViewCell: UICollectionViewCell { self.contentView.addSubview(self.todaytaLabel) self.contentView.addSubview(self.thumbnailImageView) self.contentView.addSubview(self.safesumLabel) + self.contentView.addSubview(self.dueByDeltasLabel) self.contentView.backgroundColor = .systemBackground self.slugLabel.font = UIFont.beeminder.defaultFontHeavy @@ -64,6 +72,11 @@ class GoalCollectionViewCell: UICollectionViewCell { make.centerY.equalTo(self.thumbnailImageView.snp.centerY) make.right.equalTo(-self.margin) } + self.dueByDeltasLabel.snp.makeConstraints { make in + make.left.equalTo(self.thumbnailImageView.snp.right).offset(5) + make.top.equalTo(self.safesumLabel.snp.bottom).offset(6) + make.right.equalTo(-self.margin) + } } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override func prepareForReuse() { @@ -78,5 +91,33 @@ class GoalCollectionViewCell: UICollectionViewCell { self.todaytaLabel.text = goal?.todayta == true ? "✓" : "" self.safesumLabel.text = goal?.capitalSafesum() self.safesumLabel.textColor = goal?.countdownColor ?? UIColor.Beeminder.gray + self.dueByDeltasLabel.attributedText = goal?.dueByTableAttributedString + self.dueByDeltasLabel.isHidden = goal == nil || goal?.dueByContainsSpecificAmounts == false + } +} + +extension Goal { + fileprivate var dueByContainsSpecificAmounts: Bool { + self.dueBy.values.map { $0.formattedDelta }.joined(separator: " ").contains(where: { $0.isNumber }) + } + fileprivate var dueByTableAttributedString: NSAttributedString { + let textAndColor: [(text: String, color: UIColor)] = dueBy.sorted(using: SortDescriptor(\.key)).compactMap({ + $0.value.formattedDelta + }).map { $0 == "✔" ? "✓" : $0 }.enumerated().map { offset, element in + var color: UIColor { + switch offset { + case 0: return UIColor.Beeminder.SafetyBuffer.orange + case 1: return UIColor.Beeminder.SafetyBuffer.blue + case 2: return UIColor.Beeminder.SafetyBuffer.green + default: return .label.withAlphaComponent(0.8) + } + } + return (text: element, color: color) + } + let attrStr = NSMutableAttributedString() + textAndColor.map { (text: String, color: UIColor) in + NSAttributedString(string: text + " ", attributes: [.foregroundColor: color]) + }.forEach { attrStr.append($0) } + return attrStr } } From 59b3fa12de33334983c06c362ce467f4c57ccbfe Mon Sep 17 00:00:00 2001 From: krugerk <4656811+krugerk@users.noreply.github.com> Date: Sat, 21 Feb 2026 21:27:38 +0100 Subject: [PATCH 2/2] DRY --- BeeSwift/Cells/GoalCollectionViewCell.swift | 20 ----------------- BeeSwift/GoalExtensions.swift | 23 ++++++++++++++++++- BeeSwift/GoalView/GoalViewController.swift | 25 +-------------------- 3 files changed, 23 insertions(+), 45 deletions(-) diff --git a/BeeSwift/Cells/GoalCollectionViewCell.swift b/BeeSwift/Cells/GoalCollectionViewCell.swift index 2f1c312b9..84473080f 100644 --- a/BeeSwift/Cells/GoalCollectionViewCell.swift +++ b/BeeSwift/Cells/GoalCollectionViewCell.swift @@ -100,24 +100,4 @@ extension Goal { fileprivate var dueByContainsSpecificAmounts: Bool { self.dueBy.values.map { $0.formattedDelta }.joined(separator: " ").contains(where: { $0.isNumber }) } - fileprivate var dueByTableAttributedString: NSAttributedString { - let textAndColor: [(text: String, color: UIColor)] = dueBy.sorted(using: SortDescriptor(\.key)).compactMap({ - $0.value.formattedDelta - }).map { $0 == "✔" ? "✓" : $0 }.enumerated().map { offset, element in - var color: UIColor { - switch offset { - case 0: return UIColor.Beeminder.SafetyBuffer.orange - case 1: return UIColor.Beeminder.SafetyBuffer.blue - case 2: return UIColor.Beeminder.SafetyBuffer.green - default: return .label.withAlphaComponent(0.8) - } - } - return (text: element, color: color) - } - let attrStr = NSMutableAttributedString() - textAndColor.map { (text: String, color: UIColor) in - NSAttributedString(string: text + " ", attributes: [.foregroundColor: color]) - }.forEach { attrStr.append($0) } - return attrStr - } } diff --git a/BeeSwift/GoalExtensions.swift b/BeeSwift/GoalExtensions.swift index 881821122..4dd899291 100755 --- a/BeeSwift/GoalExtensions.swift +++ b/BeeSwift/GoalExtensions.swift @@ -2,6 +2,27 @@ import BeeKit +extension Goal { var countdownColor: UIColor { return UIColor.Beeminder.SafetyBuffer.color(for: self.colorkey) } } + extension Goal { - public var countdownColor: UIColor { return UIColor.Beeminder.SafetyBuffer.color(for: self.colorkey) } + var dueByTableAttributedString: NSAttributedString { + let textAndColor: [(text: String, color: UIColor)] = dueBy.sorted(using: SortDescriptor(\.key)).compactMap { + $0.value.formattedDelta + }.map { $0 == "✔" ? "✓" : $0 }.enumerated().map { offset, element in + var color: UIColor { + switch offset { + case 0: return UIColor.Beeminder.SafetyBuffer.orange + case 1: return UIColor.Beeminder.SafetyBuffer.blue + case 2: return UIColor.Beeminder.SafetyBuffer.green + default: return .label.withAlphaComponent(0.8) + } + } + return (text: element, color: color) + } + let attrStr = NSMutableAttributedString() + textAndColor.map { (text: String, color: UIColor) in + NSAttributedString(string: text + " ", attributes: [.foregroundColor: color]) + }.forEach { attrStr.append($0) } + return attrStr + } } diff --git a/BeeSwift/GoalView/GoalViewController.swift b/BeeSwift/GoalView/GoalViewController.swift index b722b29b6..39cf8e40e 100644 --- a/BeeSwift/GoalView/GoalViewController.swift +++ b/BeeSwift/GoalView/GoalViewController.swift @@ -537,7 +537,7 @@ class GoalViewController: UIViewController, UIScrollViewDelegate, DatapointTable self.datapointTableController.hhmmformat = goal.hhmmFormat self.datapointTableController.datapoints = goal.recentData.sorted(by: { $0.updatedAt < $1.updatedAt }) self.deltasLabel.isHidden = goal.dueBy.isEmpty - self.deltasLabel.attributedText = self.dueByTableAttributedString + self.deltasLabel.attributedText = goal.dueByTableAttributedString self.refreshCountdown() self.updateLastUpdatedLabel() } @@ -684,26 +684,3 @@ extension GoalViewController { return UIMenu(title: "", children: [settingsMenu, webMenu]) } } - -extension GoalViewController { - fileprivate var dueByTableAttributedString: NSAttributedString { - let textAndColor: [(text: String, color: UIColor)] = goal.dueBy.sorted(using: SortDescriptor(\.key)).compactMap { - $0.value.formattedDelta - }.map { $0 == "✔" ? "✓" : $0 }.enumerated().map { offset, element in - var color: UIColor { - switch offset { - case 0: return UIColor.Beeminder.SafetyBuffer.orange - case 1: return UIColor.Beeminder.SafetyBuffer.blue - case 2: return UIColor.Beeminder.SafetyBuffer.green - default: return .label.withAlphaComponent(0.8) - } - } - return (text: element, color: color) - } - let attrStr = NSMutableAttributedString() - textAndColor.map { (text: String, color: UIColor) in - NSAttributedString(string: text + " ", attributes: [.foregroundColor: color]) - }.forEach { attrStr.append($0) } - return attrStr - } -}