From 1756a8cfbf3239ce2412ff5417d243f41ffb2841 Mon Sep 17 00:00:00 2001 From: Theo Spears Date: Sat, 9 Sep 2023 21:59:25 -0700 Subject: [PATCH 1/7] Update buttons --- BeeSwift/EditDatapointViewController.swift | 81 +++++----------------- 1 file changed, 17 insertions(+), 64 deletions(-) diff --git a/BeeSwift/EditDatapointViewController.swift b/BeeSwift/EditDatapointViewController.swift index 1b6791e9f..48ec6d337 100644 --- a/BeeSwift/EditDatapointViewController.swift +++ b/BeeSwift/EditDatapointViewController.swift @@ -13,12 +13,13 @@ import OSLog class EditDatapointViewController: UIViewController, UITextFieldDelegate { private let logger = Logger(subsystem: "com.beeminder.beeminder", category: "EditDatapointViewController") + + private let margin = 10 var datapoint : ExistingDataPoint var goalSlug : String fileprivate var datePicker = UIDatePicker() fileprivate var scrollView = UIScrollView() - fileprivate var dateLabel = BSLabel() fileprivate var valueField = BSTextField() fileprivate var commentField = BSTextField() @@ -47,32 +48,17 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { make.bottom.equalTo(0) } - self.scrollView.addSubview(self.dateLabel) - self.dateLabel.snp.makeConstraints { (make) in - make.top.left.equalTo(self.scrollView).offset(10) - make.right.equalTo(self.scrollView).offset(-10) - make.width.equalTo(self.scrollView).offset(-20) - make.height.equalTo(42) - } - self.dateLabel.textAlignment = .center - self.dateLabel.isUserInteractionEnabled = true - let tapGR = UITapGestureRecognizer(target: self, action: #selector(self.dateLabelTapped)) - self.dateLabel.addGestureRecognizer(tapGR) - self.scrollView.addSubview(self.datePicker) self.datePicker.snp.makeConstraints { (make) in - make.left.right.equalTo(self.scrollView) - make.width.equalTo(self.scrollView) - make.height.equalTo(0) - make.top.equalTo(self.dateLabel.snp.bottom) + make.top.equalTo(self.scrollView).offset(margin) + make.centerX.equalTo(self.scrollView) } self.datePicker.datePickerMode = .date - self.datePicker.isHidden = true - self.datePicker.addTarget(self, action: #selector(self.datePickerValueChanged), for: .valueChanged) + self.datePicker.preferredDatePickerStyle = .inline self.scrollView.addSubview(self.valueField) self.valueField.snp.makeConstraints { (make) in - make.left.right.height.equalTo(self.dateLabel) + make.left.right.equalTo(self.datePicker) make.top.equalTo(self.datePicker.snp.bottom).offset(10) } self.valueField.delegate = self @@ -80,7 +66,6 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { self.valueField.textAlignment = .center self.valueField.keyboardType = .decimalPad self.valueField.text = "\(self.datapoint.value)" - self.valueField.addTarget(self, action: #selector(self.textFieldEditingDidBegin), for: .editingDidBegin) let accessory = DatapointValueAccessory() accessory.valueField = self.valueField @@ -88,37 +73,33 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { self.scrollView.addSubview(self.commentField) self.commentField.snp.makeConstraints { (make) in - make.left.right.height.equalTo(self.dateLabel) + make.left.right.equalTo(self.datePicker) make.top.equalTo(self.valueField.snp.bottom).offset(10) } self.commentField.placeholder = "Comment" self.commentField.textAlignment = .center self.commentField.text = self.datapoint.comment - self.commentField.addTarget(self, action: #selector(self.textFieldEditingDidBegin), for: .editingDidBegin) - let updateButton = BSButton() + let updateButton = UIButton(type: .system) + if #available(iOS 15.0, *) { + updateButton.configuration = .filled() + } self.scrollView.addSubview(updateButton) updateButton.snp.makeConstraints { (make) in - make.left.right.height.equalTo(self.dateLabel) + make.left.right.equalTo(self.datePicker) make.top.equalTo(self.commentField.snp.bottom).offset(10) } updateButton.setTitle("Update", for: .normal) updateButton.addTarget(self, action: #selector(self.updateButtonPressed), for: .touchUpInside) - - let deleteButton = BSButton() - self.scrollView.addSubview(deleteButton) - deleteButton.snp.makeConstraints { (make) in - make.left.right.height.equalTo(self.dateLabel) - make.top.equalTo(updateButton.snp.bottom).offset(10) - } - deleteButton.setTitle("Delete", for: .normal) - deleteButton.addTarget(self, action: #selector(self.deleteButtonPressed), for: .touchUpInside) + + let deleteButton = UIBarButtonItem(barButtonSystemItem: .trash, target: self, action: #selector(self.deleteButtonPressed)) + deleteButton.tintColor = .red + self.navigationItem.rightBarButtonItem = deleteButton let daystamp = self.datapoint.daystamp let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyyMMdd" self.datePicker.date = dateFormatter.date(from: daystamp)! - self.updateDateLabel() } func urtext() -> String { @@ -127,23 +108,6 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { return "\(dateFormatter.string(from: self.datePicker.date)) \(self.valueField.text!) \"\(self.commentField.text!)\"" } - func updateDateLabel() { - let dateFormatter = DateFormatter() - dateFormatter.dateFormat = "yyyy-MM-dd" - self.dateLabel.text = dateFormatter.string(from: self.datePicker.date) - } - - @objc func datePickerValueChanged() { - self.updateDateLabel() - } - - @objc func textFieldEditingDidBegin() { - self.datePicker.snp.updateConstraints { (make) in - make.height.equalTo(0) - } - self.datePicker.isHidden = true - } - func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { if (textField.isEqual(self.valueField)) { // Only allow a single decimal separator (, or .) @@ -164,18 +128,7 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { } return true } - - @objc func dateLabelTapped() { - self.datePicker.snp.updateConstraints { (make) in - if self.datePicker.isHidden { - make.height.equalTo(200) - } else { - make.height.equalTo(0) - } - } - self.datePicker.isHidden = !self.datePicker.isHidden - self.view.endEditing(true) - } + @objc func updateButtonPressed() { Task { @MainActor in From 12f9be1ea42632bc59c1728815e1ac4c4460de50 Mon Sep 17 00:00:00 2001 From: Theo Spears Date: Sat, 9 Sep 2023 22:02:40 -0700 Subject: [PATCH 2/7] Re-organize date setting --- BeeSwift/EditDatapointViewController.swift | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/BeeSwift/EditDatapointViewController.swift b/BeeSwift/EditDatapointViewController.swift index 48ec6d337..e392f9f80 100644 --- a/BeeSwift/EditDatapointViewController.swift +++ b/BeeSwift/EditDatapointViewController.swift @@ -55,7 +55,12 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { } self.datePicker.datePickerMode = .date self.datePicker.preferredDatePickerStyle = .inline - + + let daystamp = self.datapoint.daystamp + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyyMMdd" + self.datePicker.date = dateFormatter.date(from: daystamp)! + self.scrollView.addSubview(self.valueField) self.valueField.snp.makeConstraints { (make) in make.left.right.equalTo(self.datePicker) @@ -95,11 +100,7 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { let deleteButton = UIBarButtonItem(barButtonSystemItem: .trash, target: self, action: #selector(self.deleteButtonPressed)) deleteButton.tintColor = .red self.navigationItem.rightBarButtonItem = deleteButton - - let daystamp = self.datapoint.daystamp - let dateFormatter = DateFormatter() - dateFormatter.dateFormat = "yyyyMMdd" - self.datePicker.date = dateFormatter.date(from: daystamp)! + } func urtext() -> String { From 7607e98c0e6d2d91b2ba484672ef58319c679e2d Mon Sep 17 00:00:00 2001 From: Theo Spears Date: Sat, 9 Sep 2023 22:27:21 -0700 Subject: [PATCH 3/7] More styling --- BeeSwift/EditDatapointViewController.swift | 70 ++++++++++++++++++---- 1 file changed, 57 insertions(+), 13 deletions(-) diff --git a/BeeSwift/EditDatapointViewController.swift b/BeeSwift/EditDatapointViewController.swift index e392f9f80..458496af2 100644 --- a/BeeSwift/EditDatapointViewController.swift +++ b/BeeSwift/EditDatapointViewController.swift @@ -20,8 +20,8 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { var goalSlug : String fileprivate var datePicker = UIDatePicker() fileprivate var scrollView = UIScrollView() - fileprivate var valueField = BSTextField() - fileprivate var commentField = BSTextField() + fileprivate var valueField = UITextField() + fileprivate var commentField = UITextField() init(goalSlug: String, datapoint: ExistingDataPoint) { self.goalSlug = goalSlug @@ -61,29 +61,67 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { dateFormatter.dateFormat = "yyyyMMdd" self.datePicker.date = dateFormatter.date(from: daystamp)! - self.scrollView.addSubview(self.valueField) - self.valueField.snp.makeConstraints { (make) in + let formView = UIView() + self.scrollView.addSubview(formView) + formView.snp.makeConstraints{ (make) in make.left.right.equalTo(self.datePicker) make.top.equalTo(self.datePicker.snp.bottom).offset(10) } + formView.layer.cornerRadius = 10 + formView.backgroundColor = UIColor(white: 0.5, alpha: 0.2) + + let valueLabel = UILabel() + formView.addSubview(valueLabel) + valueLabel.snp.makeConstraints { (make) in + make.left.right.equalTo(formView).inset(10) + make.top.equalTo(formView).offset(10) + } + valueLabel.text = "Value" + valueLabel.layer.opacity = 0.5 + valueLabel.font = UIFont.systemFont(ofSize: 12) + + formView.addSubview(self.valueField) + self.valueField.snp.makeConstraints { (make) in + make.left.right.equalTo(formView).inset(10) + make.top.equalTo(valueLabel.snp.bottom).offset(3) + } self.valueField.delegate = self - self.valueField.placeholder = "Value" - self.valueField.textAlignment = .center self.valueField.keyboardType = .decimalPad + self.valueField.returnKeyType = .done self.valueField.text = "\(self.datapoint.value)" let accessory = DatapointValueAccessory() accessory.valueField = self.valueField self.valueField.inputAccessoryView = accessory - - self.scrollView.addSubview(self.commentField) - self.commentField.snp.makeConstraints { (make) in - make.left.right.equalTo(self.datePicker) + + // Add a horizontal line divider + let divider = UIView() + formView.addSubview(divider) + divider.snp.makeConstraints { (make) in + make.left.right.equalTo(formView).inset(10) make.top.equalTo(self.valueField.snp.bottom).offset(10) + make.height.equalTo(1) + } + divider.backgroundColor = UIColor(white: 0.5, alpha: 0.5) + + let commentLabel = UILabel() + formView.addSubview(commentLabel) + commentLabel.snp.makeConstraints { (make) in + make.left.right.equalTo(formView).inset(10) + make.top.equalTo(divider).offset(10) + } + commentLabel.text = "Comment" + commentLabel.layer.opacity = 0.5 + commentLabel.font = UIFont.systemFont(ofSize: 12) + + formView.addSubview(self.commentField) + self.commentField.snp.makeConstraints { (make) in + make.left.right.bottom.equalTo(formView).inset(10) + make.top.equalTo(commentLabel.snp.bottom).offset(3) } - self.commentField.placeholder = "Comment" - self.commentField.textAlignment = .center self.commentField.text = self.datapoint.comment + self.commentField.delegate = self + self.commentField.returnKeyType = .done let updateButton = UIButton(type: .system) if #available(iOS 15.0, *) { @@ -92,7 +130,7 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { self.scrollView.addSubview(updateButton) updateButton.snp.makeConstraints { (make) in make.left.right.equalTo(self.datePicker) - make.top.equalTo(self.commentField.snp.bottom).offset(10) + make.top.equalTo(formView.snp.bottom).offset(20) } updateButton.setTitle("Update", for: .normal) updateButton.addTarget(self, action: #selector(self.updateButtonPressed), for: .touchUpInside) @@ -130,6 +168,12 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { return true } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField.resignFirstResponder() + return true + } + @objc func updateButtonPressed() { Task { @MainActor in From 73b65713abe11a2058ec8f554f4961d80f8d34f9 Mon Sep 17 00:00:00 2001 From: Theo Spears Date: Sun, 10 Sep 2023 18:59:17 -0700 Subject: [PATCH 4/7] Some redesign and make it a popover --- BeeSwift/EditDatapointViewController.swift | 80 +++++++++++++++------- BeeSwift/GoalViewController.swift | 4 +- 2 files changed, 60 insertions(+), 24 deletions(-) diff --git a/BeeSwift/EditDatapointViewController.swift b/BeeSwift/EditDatapointViewController.swift index 458496af2..2ce49cf29 100644 --- a/BeeSwift/EditDatapointViewController.swift +++ b/BeeSwift/EditDatapointViewController.swift @@ -19,7 +19,6 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { var datapoint : ExistingDataPoint var goalSlug : String fileprivate var datePicker = UIDatePicker() - fileprivate var scrollView = UIScrollView() fileprivate var valueField = UITextField() fileprivate var commentField = UITextField() @@ -39,42 +38,58 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { self.title = "Edit Datapoint" self.view.backgroundColor = .systemBackground - - self.view.addSubview(self.scrollView) - self.scrollView.snp.makeConstraints { (make) -> Void in - make.top.equalTo(self.view.safeAreaLayoutGuide.snp.topMargin) - make.left.equalTo(0) - make.right.equalTo(0) - make.bottom.equalTo(0) + + let formView = UIView() + self.view.addSubview(formView) + formView.snp.makeConstraints{ (make) in + make.top.left.right.equalTo(self.view.safeAreaLayoutGuide).inset(10) } - - self.scrollView.addSubview(self.datePicker) + formView.layer.cornerRadius = 10 + formView.backgroundColor = UIColor(white: 0.5, alpha: 0.2) + + + let dateLabel = UILabel() + formView.addSubview(dateLabel) + dateLabel.snp.makeConstraints { (make) in + make.top.left.right.equalTo(formView).inset(10) + } + dateLabel.text = "Date" + dateLabel.layer.opacity = 0.5 + dateLabel.font = UIFont.systemFont(ofSize: 12) + + formView.addSubview(self.datePicker) self.datePicker.snp.makeConstraints { (make) in - make.top.equalTo(self.scrollView).offset(margin) - make.centerX.equalTo(self.scrollView) + make.left.right.equalTo(formView) + make.top.equalTo(dateLabel.snp.bottom) } self.datePicker.datePickerMode = .date - self.datePicker.preferredDatePickerStyle = .inline + self.datePicker.preferredDatePickerStyle = .compact + self.datePicker.contentHorizontalAlignment = .left + self.datePicker.backgroundColor = nil + if let bgView = self.datePicker.subviews.first?.subviews.first?.subviews.first { + bgView.backgroundColor = nil + } let daystamp = self.datapoint.daystamp let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyyMMdd" self.datePicker.date = dateFormatter.date(from: daystamp)! - let formView = UIView() - self.scrollView.addSubview(formView) - formView.snp.makeConstraints{ (make) in - make.left.right.equalTo(self.datePicker) - make.top.equalTo(self.datePicker.snp.bottom).offset(10) + // Add a horizontal line divider + let divider1 = UIView() + formView.addSubview(divider1) + divider1.snp.makeConstraints { (make) in + make.left.right.equalTo(formView).inset(10) + make.top.equalTo(self.datePicker.snp.bottom) + make.height.equalTo(1) } - formView.layer.cornerRadius = 10 - formView.backgroundColor = UIColor(white: 0.5, alpha: 0.2) + divider1.backgroundColor = UIColor(white: 0.5, alpha: 0.5) let valueLabel = UILabel() formView.addSubview(valueLabel) valueLabel.snp.makeConstraints { (make) in make.left.right.equalTo(formView).inset(10) - make.top.equalTo(formView).offset(10) + make.top.equalTo(divider1.snp.bottom).offset(10) } valueLabel.text = "Value" valueLabel.layer.opacity = 0.5 @@ -127,9 +142,9 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { if #available(iOS 15.0, *) { updateButton.configuration = .filled() } - self.scrollView.addSubview(updateButton) + self.view.addSubview(updateButton) updateButton.snp.makeConstraints { (make) in - make.left.right.equalTo(self.datePicker) + make.left.right.equalTo(formView) make.top.equalTo(formView.snp.bottom).offset(20) } updateButton.setTitle("Update", for: .normal) @@ -138,7 +153,20 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { let deleteButton = UIBarButtonItem(barButtonSystemItem: .trash, target: self, action: #selector(self.deleteButtonPressed)) deleteButton.tintColor = .red self.navigationItem.rightBarButtonItem = deleteButton + } + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + if let bgView = self.datePicker.subviews.first?.subviews.first?.subviews.first { + bgView.backgroundColor = nil + } + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + if let bgView = self.datePicker.subviews.first?.subviews.first?.subviews.first { + bgView.backgroundColor = nil + } } func urtext() -> String { @@ -236,4 +264,10 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { super.didReceiveMemoryWarning() } + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + if let bgView = self.datePicker.subviews.first?.subviews.first?.subviews.first { + bgView.backgroundColor = nil + } + } + } diff --git a/BeeSwift/GoalViewController.swift b/BeeSwift/GoalViewController.swift index 6d21d4e9b..a93569f5a 100644 --- a/BeeSwift/GoalViewController.swift +++ b/BeeSwift/GoalViewController.swift @@ -412,7 +412,9 @@ class GoalViewController: UIViewController, UIScrollViewDelegate, DatapointTabl guard let existingDatapoint = datapoint as? ExistingDataPoint else { return } let editDatapointViewController = EditDatapointViewController(goalSlug: goal.slug, datapoint: existingDatapoint) - self.navigationController?.pushViewController(editDatapointViewController, animated: true) + let navigationController = UINavigationController(rootViewController: editDatapointViewController) + navigationController.modalPresentationStyle = .popover + self.present(navigationController, animated: true, completion: nil) } @objc func dateStepperValueChanged() { From 748078c5a46db4bb253ab3940a3aa1ff13b35cc6 Mon Sep 17 00:00:00 2001 From: Theo Spears Date: Sun, 24 Sep 2023 21:41:22 -0700 Subject: [PATCH 5/7] Fix iOS 14 layout --- BeeSwift/DatapointsTableView.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/BeeSwift/DatapointsTableView.swift b/BeeSwift/DatapointsTableView.swift index aee791d43..30718b48a 100644 --- a/BeeSwift/DatapointsTableView.swift +++ b/BeeSwift/DatapointsTableView.swift @@ -9,6 +9,11 @@ import Foundation class DatapointsTableView : UITableView { + override var contentSize:CGSize { + didSet { + invalidateIntrinsicContentSize() + } + } override var intrinsicContentSize : CGSize { self.layoutIfNeeded() From df6b475c5a745a43550b38ea60e0ef636dc5e1e7 Mon Sep 17 00:00:00 2001 From: Theo Spears Date: Sat, 30 Sep 2023 20:18:17 -0700 Subject: [PATCH 6/7] Improve the styling --- BeeSwift.xcodeproj/project.pbxproj | 6 ++- BeeSwift/EditDatapointViewController.swift | 24 ++------- BeeSwift/GoalViewController.swift | 2 +- BeeSwift/InlineDatePicker.swift | 62 ++++++++++++++++++++++ 4 files changed, 72 insertions(+), 22 deletions(-) create mode 100644 BeeSwift/InlineDatePicker.swift diff --git a/BeeSwift.xcodeproj/project.pbxproj b/BeeSwift.xcodeproj/project.pbxproj index f19178d5b..04a5ad685 100644 --- a/BeeSwift.xcodeproj/project.pbxproj +++ b/BeeSwift.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 53; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -80,6 +80,7 @@ E42CB452291727B200A35AB9 /* HealthKitError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42CB451291727B200A35AB9 /* HealthKitError.swift */; }; E42CB453291727B200A35AB9 /* HealthKitError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42CB451291727B200A35AB9 /* HealthKitError.swift */; }; E42CB454291727B200A35AB9 /* HealthKitError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42CB451291727B200A35AB9 /* HealthKitError.swift */; }; + E43833942AC1473E0098A38F /* InlineDatePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43833932AC1473E0098A38F /* InlineDatePicker.swift */; }; E43BEA842A036A9C00FC3A38 /* LogReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43BEA832A036A9C00FC3A38 /* LogReader.swift */; }; E43BEA862A036D4300FC3A38 /* LogReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43BEA852A036D4300FC3A38 /* LogReaderTests.swift */; }; E43D9AFB2929C37D00FC1578 /* DatapointValueAccessory.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43D9AFA2929C37D00FC1578 /* DatapointValueAccessory.swift */; }; @@ -348,6 +349,7 @@ E4040D732A7B5F0E008E7D0E /* WorkoutMinutesHealthKitMetric.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkoutMinutesHealthKitMetric.swift; sourceTree = ""; }; E417572C2A6446FE0029CDDA /* CurrentUserManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentUserManagerTests.swift; sourceTree = ""; }; E42CB451291727B200A35AB9 /* HealthKitError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HealthKitError.swift; sourceTree = ""; }; + E43833932AC1473E0098A38F /* InlineDatePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InlineDatePicker.swift; sourceTree = ""; }; E43BEA832A036A9C00FC3A38 /* LogReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogReader.swift; sourceTree = ""; }; E43BEA852A036D4300FC3A38 /* LogReaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogReaderTests.swift; sourceTree = ""; }; E43D9AFA2929C37D00FC1578 /* DatapointValueAccessory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatapointValueAccessory.swift; sourceTree = ""; }; @@ -517,6 +519,7 @@ A1C170DF1BEEB3110018D32B /* UIFontExtension.swift */, E43D9AFA2929C37D00FC1578 /* DatapointValueAccessory.swift */, E46DC80E2AA58DF20059FDFE /* PullToRefreshHint.swift */, + E43833932AC1473E0098A38F /* InlineDatePicker.swift */, ); name = UI; sourceTree = ""; @@ -1143,6 +1146,7 @@ A1BE73AA1E8B45BF00DEC4DB /* ChooseHKMetricViewController.swift in Sources */, A149147B1BE79FD50060600A /* EditNotificationsViewController.swift in Sources */, A1BE73AC1E8B47E700DEC4DB /* HealthKitMetricTableViewCell.swift in Sources */, + E43833942AC1473E0098A38F /* InlineDatePicker.swift in Sources */, A1C11B481B06F5D100D22871 /* Constants.swift in Sources */, E4B0833D293810EB00A71564 /* DataPoint.swift in Sources */, E44CE7732993317B00394E87 /* ServiceLocator.swift in Sources */, diff --git a/BeeSwift/EditDatapointViewController.swift b/BeeSwift/EditDatapointViewController.swift index 2ce49cf29..e2436ed47 100644 --- a/BeeSwift/EditDatapointViewController.swift +++ b/BeeSwift/EditDatapointViewController.swift @@ -18,7 +18,7 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { var datapoint : ExistingDataPoint var goalSlug : String - fileprivate var datePicker = UIDatePicker() + fileprivate var datePicker = InlineDatePicker() fileprivate var valueField = UITextField() fileprivate var commentField = UITextField() @@ -59,16 +59,11 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { formView.addSubview(self.datePicker) self.datePicker.snp.makeConstraints { (make) in - make.left.right.equalTo(formView) - make.top.equalTo(dateLabel.snp.bottom) + make.left.right.equalTo(formView).inset(10) + make.top.equalTo(dateLabel.snp.bottom).offset(3) } self.datePicker.datePickerMode = .date - self.datePicker.preferredDatePickerStyle = .compact self.datePicker.contentHorizontalAlignment = .left - self.datePicker.backgroundColor = nil - if let bgView = self.datePicker.subviews.first?.subviews.first?.subviews.first { - bgView.backgroundColor = nil - } let daystamp = self.datapoint.daystamp let dateFormatter = DateFormatter() @@ -80,7 +75,7 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { formView.addSubview(divider1) divider1.snp.makeConstraints { (make) in make.left.right.equalTo(formView).inset(10) - make.top.equalTo(self.datePicker.snp.bottom) + make.top.equalTo(self.datePicker.snp.bottom).offset(10) make.height.equalTo(1) } divider1.backgroundColor = UIColor(white: 0.5, alpha: 0.5) @@ -259,15 +254,4 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { self.present(alert, animated: true, completion: nil) } - - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - } - - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - if let bgView = self.datePicker.subviews.first?.subviews.first?.subviews.first { - bgView.backgroundColor = nil - } - } - } diff --git a/BeeSwift/GoalViewController.swift b/BeeSwift/GoalViewController.swift index a93569f5a..361a2065a 100644 --- a/BeeSwift/GoalViewController.swift +++ b/BeeSwift/GoalViewController.swift @@ -413,7 +413,7 @@ class GoalViewController: UIViewController, UIScrollViewDelegate, DatapointTabl let editDatapointViewController = EditDatapointViewController(goalSlug: goal.slug, datapoint: existingDatapoint) let navigationController = UINavigationController(rootViewController: editDatapointViewController) - navigationController.modalPresentationStyle = .popover + navigationController.modalPresentationStyle = .formSheet self.present(navigationController, animated: true, completion: nil) } diff --git a/BeeSwift/InlineDatePicker.swift b/BeeSwift/InlineDatePicker.swift new file mode 100644 index 000000000..dbef02eaa --- /dev/null +++ b/BeeSwift/InlineDatePicker.swift @@ -0,0 +1,62 @@ +// +// InlineDatePicker.swift +// BeeSwift +// +// A date picker component designed to be shown fully inline. Unlike +// the default inline date picked mode it does not add margin or background. +// +// This component modifies private subviews within the UIDatePicker hierarchy, so any +// changes should be tested against all supported iOS versions + +import Foundation + +class InlineDatePicker : UIDatePicker { + init() { + super.init(frame: .zero) + self.preferredDatePickerStyle = .compact + + resetStyle() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + override func didMoveToSuperview() { + super.didMoveToSuperview() + resetStyle() + } + + override func layoutSubviews() { + super.layoutSubviews() + resetStyle() + } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + resetStyle() + } + + private func resetStyle() { + if let iosCompactView = self.subviews.first, + let compactDateLabel = iosCompactView.subviews.first { + + // Switch to a transparent background + if let bgView = compactDateLabel.subviews.first { + bgView.backgroundColor = nil + } + + // Remove the padding around the date label + if compactDateLabel.subviews.count >= 2 { + let linkedLabel = compactDateLabel.subviews[1] + + for constraint in compactDateLabel.constraints { + if constraint.firstItem === linkedLabel || constraint.secondItem === linkedLabel { + constraint.constant = 0 + } + } + } + } + } + +} From d819ab6dc77903a94563d305fd79424a1b9f61a3 Mon Sep 17 00:00:00 2001 From: Theo Spears Date: Sat, 30 Sep 2023 19:27:30 -0700 Subject: [PATCH 7/7] Cleanup form code --- BeeSwift/EditDatapointViewController.swift | 80 ++++++++++++---------- 1 file changed, 42 insertions(+), 38 deletions(-) diff --git a/BeeSwift/EditDatapointViewController.swift b/BeeSwift/EditDatapointViewController.swift index e2436ed47..c272ce6c3 100644 --- a/BeeSwift/EditDatapointViewController.swift +++ b/BeeSwift/EditDatapointViewController.swift @@ -41,27 +41,22 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { let formView = UIView() self.view.addSubview(formView) + formView.layer.cornerRadius = 10 + formView.backgroundColor = UIColor(white: 0.5, alpha: 0.2) formView.snp.makeConstraints{ (make) in make.top.left.right.equalTo(self.view.safeAreaLayoutGuide).inset(10) } - formView.layer.cornerRadius = 10 - formView.backgroundColor = UIColor(white: 0.5, alpha: 0.2) - let dateLabel = UILabel() formView.addSubview(dateLabel) - dateLabel.snp.makeConstraints { (make) in - make.top.left.right.equalTo(formView).inset(10) - } dateLabel.text = "Date" dateLabel.layer.opacity = 0.5 dateLabel.font = UIFont.systemFont(ofSize: 12) + dateLabel.snp.makeConstraints { (make) in + make.top.left.right.equalTo(formView).inset(10) + } formView.addSubview(self.datePicker) - self.datePicker.snp.makeConstraints { (make) in - make.left.right.equalTo(formView).inset(10) - make.top.equalTo(dateLabel.snp.bottom).offset(3) - } self.datePicker.datePickerMode = .date self.datePicker.contentHorizontalAlignment = .left @@ -70,86 +65,95 @@ class EditDatapointViewController: UIViewController, UITextFieldDelegate { dateFormatter.dateFormat = "yyyyMMdd" self.datePicker.date = dateFormatter.date(from: daystamp)! - // Add a horizontal line divider - let divider1 = UIView() + self.datePicker.snp.makeConstraints { (make) in + make.left.right.equalTo(formView).inset(10) + make.top.equalTo(dateLabel.snp.bottom).offset(3) + } + + let divider1 = formDivider() formView.addSubview(divider1) divider1.snp.makeConstraints { (make) in make.left.right.equalTo(formView).inset(10) make.top.equalTo(self.datePicker.snp.bottom).offset(10) - make.height.equalTo(1) } - divider1.backgroundColor = UIColor(white: 0.5, alpha: 0.5) let valueLabel = UILabel() formView.addSubview(valueLabel) + valueLabel.text = "Value" + valueLabel.layer.opacity = 0.5 + valueLabel.font = UIFont.systemFont(ofSize: 12) valueLabel.snp.makeConstraints { (make) in make.left.right.equalTo(formView).inset(10) make.top.equalTo(divider1.snp.bottom).offset(10) } - valueLabel.text = "Value" - valueLabel.layer.opacity = 0.5 - valueLabel.font = UIFont.systemFont(ofSize: 12) formView.addSubview(self.valueField) - self.valueField.snp.makeConstraints { (make) in - make.left.right.equalTo(formView).inset(10) - make.top.equalTo(valueLabel.snp.bottom).offset(3) - } self.valueField.delegate = self self.valueField.keyboardType = .decimalPad self.valueField.returnKeyType = .done self.valueField.text = "\(self.datapoint.value)" - + let accessory = DatapointValueAccessory() accessory.valueField = self.valueField self.valueField.inputAccessoryView = accessory - // Add a horizontal line divider - let divider = UIView() - formView.addSubview(divider) - divider.snp.makeConstraints { (make) in + self.valueField.snp.makeConstraints { (make) in + make.left.right.equalTo(formView).inset(10) + make.top.equalTo(valueLabel.snp.bottom).offset(3) + } + + let divider2 = formDivider() + formView.addSubview(divider2) + divider2.snp.makeConstraints { (make) in make.left.right.equalTo(formView).inset(10) make.top.equalTo(self.valueField.snp.bottom).offset(10) - make.height.equalTo(1) } - divider.backgroundColor = UIColor(white: 0.5, alpha: 0.5) let commentLabel = UILabel() formView.addSubview(commentLabel) - commentLabel.snp.makeConstraints { (make) in - make.left.right.equalTo(formView).inset(10) - make.top.equalTo(divider).offset(10) - } commentLabel.text = "Comment" commentLabel.layer.opacity = 0.5 commentLabel.font = UIFont.systemFont(ofSize: 12) + commentLabel.snp.makeConstraints { (make) in + make.left.right.equalTo(formView).inset(10) + make.top.equalTo(divider2).offset(10) + } formView.addSubview(self.commentField) + self.commentField.text = self.datapoint.comment + self.commentField.delegate = self + self.commentField.returnKeyType = .done self.commentField.snp.makeConstraints { (make) in make.left.right.bottom.equalTo(formView).inset(10) make.top.equalTo(commentLabel.snp.bottom).offset(3) } - self.commentField.text = self.datapoint.comment - self.commentField.delegate = self - self.commentField.returnKeyType = .done let updateButton = UIButton(type: .system) + self.view.addSubview(updateButton) + updateButton.setTitle("Update", for: .normal) if #available(iOS 15.0, *) { updateButton.configuration = .filled() } - self.view.addSubview(updateButton) + updateButton.addTarget(self, action: #selector(self.updateButtonPressed), for: .touchUpInside) updateButton.snp.makeConstraints { (make) in make.left.right.equalTo(formView) make.top.equalTo(formView.snp.bottom).offset(20) } - updateButton.setTitle("Update", for: .normal) - updateButton.addTarget(self, action: #selector(self.updateButtonPressed), for: .touchUpInside) let deleteButton = UIBarButtonItem(barButtonSystemItem: .trash, target: self, action: #selector(self.deleteButtonPressed)) deleteButton.tintColor = .red self.navigationItem.rightBarButtonItem = deleteButton } + func formDivider() -> UIView { + let divider = UIView() + divider.backgroundColor = UIColor(white: 0.5, alpha: 0.5) + divider.snp.makeConstraints { (make) in + make.height.equalTo(1) + } + return divider + } + override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() if let bgView = self.datePicker.subviews.first?.subviews.first?.subviews.first {