-
Notifications
You must be signed in to change notification settings - Fork 108
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Order Details: Customer Info #53
Conversation
|
||
extension OrderDetailsCustomerInfoCell { | ||
func configure(with viewModel: OrderDetailsViewModel) { | ||
title = "hi" // what now? How to tell between shipping or billing display? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So far every viewModel I have implemented has been a 1:1 representation. But the customer info cell gets used for both shipping info and billing info. How do I detect which data to pull from the viewModel?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey there @mindgraffiti !!
Since the Order actually has two Addresses, we'd probably need something like AddressViewModel
. The Order would have references to the billing / shipping, and you could do...
func configure(with viewModel: AddressViewModel) { }
(Which would hopefully solve the ambiguity issue!)
Hi @jleandroperez, could I bother you with a question about the view model? This PR is not ready for review. It is here for context on the question :) |
…section footer title color
let emailButton = UIButton(type: .custom) | ||
emailButton.frame = CGRect(x: 8, y: 0, width: 44, height: 44) | ||
emailButton.setImage(Gridicon.iconOfType(.mail), for: .normal) | ||
emailButton.contentHorizontalAlignment = .right |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Natural Content Alignment Violation: Forcing content alignment left or right can affect the Right-to-Left layout. Use naturalContentHorizontalAlignment instead. (natural_content_alignment)
let phoneButton = UIButton(type: .custom) | ||
phoneButton.frame = CGRect(x: 8, y: 0, width: 44, height: 44) | ||
phoneButton.setImage(Gridicon.iconOfType(.ellipsis), for: .normal) | ||
phoneButton.contentHorizontalAlignment = .right |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Natural Content Alignment Violation: Forcing content alignment left or right can affect the Right-to-Left layout. Use naturalContentHorizontalAlignment instead. (natural_content_alignment)
contact.givenName = address.firstName | ||
contact.familyName = address.lastName | ||
|
||
if let organization = address.company { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration. (opening_brace)
Hi @jleandroperez! Would you please review this one? No more questions, it's finally ready! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello there @mindgraffiti !! looks good!!. First review pass.
Let's sync over slack on alternatives to approach UITableViewDataSource!!
let infoNib = UINib(nibName: OrderDetailsCustomerInfoCell.reuseIdentifier, bundle: nil) | ||
tableView.register(infoNib, forCellReuseIdentifier: OrderDetailsCustomerInfoCell.reuseIdentifier) | ||
let footerNib = UINib(nibName: ShowHideFooterCell.reuseIdentifier, bundle: nil) | ||
tableView.register(footerNib, forHeaderFooterViewReuseIdentifier: ShowHideFooterCell.reuseIdentifier) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small suggestion to reduce code duplication:
let identifiers = [OrderDetailsSummaryCell.reuseIdentifier, OrderDetailsCustomerNoteCell.reuseIdentifier, OrderDetailsCustomerInfoCell.reuseIdentifier, ShowHideFooterCell.reuseIdentifier[
for identifier in identifiers {
let nib = UINib(nibName: identifier, bundle: nil)
tableView.register(footerNib, forHeaderFooterViewReuseIdentifier: identifier)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
} | ||
set { | ||
titleLabel.text = newValue | ||
titleLabel.applyTitleStyle() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
applyTitleStyle()
sets both, the font and color. Since that doesn't depend on the text
, can we move that elsewhere?
@IBOutlet private weak var titleLabel: UILabel! {
didSet {
titleLabel.applyTitleStyle()
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
} | ||
set { | ||
nameLabel.text = newValue | ||
nameLabel.applyBodyStyle() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same note as above: can we move applyBodyStyle
to nameLabel
's didSet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
} | ||
set { | ||
addressLabel.text = newValue | ||
addressLabel.applyBodyStyle() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same note as above: can we move applyBodyStyle
to the IBOutlet's didSet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
default: | ||
return UITableViewCell() | ||
} | ||
} | ||
|
||
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { | ||
if sectionTitles[section].isEmpty { | ||
return 0.0001 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tip: CGFloat.leastNonzeroMagnitude
Rule of thumb: never ever ever use magic numbers (those are "constants inline"). You'd usually want to define constants for those.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I knew .zero
but didn't know .leastNonzeroMagnitude
existed
} | ||
} | ||
|
||
extension CNContact { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we please move this one to it's own file? (for clarity mostly!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
return cell | ||
} | ||
let zeroFrame = CGRect(x: 0, y: 0, width: 0, height: 0.001) | ||
return UIView(frame: zeroFrame) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Almost sure!!) you can just do return nil
here. Did that trigger a bug on your end?
If so... a cute way to do this is with just return UIView(frame: .zero)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, so the bug is in -heightForFooterSection
, where it has to return a tiny footer height in order to collapse empty section footers. Thanks for the reminder, this one should return nil
, not the tiny UIView.
} | ||
|
||
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { | ||
if section == Section.info.rawValue { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tip tip:
- You'd normally wanna avoid code indentation (Since it's harder to read / grasp what belongs to what brace).
- Since there's a single case here, you could do:
guard section == Section.info.rawValue else {
return nil
}
(And the biggest block gets one less tab)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
phoneButton.tintColor = StyleManager.wooCommerceBrandColor | ||
phoneButton.addTarget(self, action: #selector(phoneButtonAction), for: .touchUpInside) | ||
|
||
let iconView = UIView(frame: CGRect(x: 0, y: 0, width: 44, height: 44)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we please please move all of the magic numbers to constants? (view frames + reuse identifiers)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
emailButton.tintColor = StyleManager.wooCommerceBrandColor | ||
emailButton.addTarget(self, action: #selector(emailButtonAction), for: .touchUpInside) | ||
|
||
let iconView = UIView(frame: CGRect(x: 0, y: 0, width: 44, height: 44)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Same comment as above)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
… functions to more swift-like
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trailing Newline Violation: Files should have a single trailing newline. (trailing_newline)
@jleandroperez thank you for making this code look cute! Ready for another look. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few nipticky comments!!
var formattedAddress: String | ||
var cleanedPhoneNumber: String? | ||
var phoneNumber: String? | ||
var email: String? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please please: Can we switch everything to let
?
cleanedPhoneNumber = address.phone?.components(separatedBy: CharacterSet.decimalDigits.inverted).joined() | ||
|
||
let cnAddress = contact.postalAddresses.first | ||
let postalAddress = cnAddress!.value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use a safe unwrap here, just in case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed formattedAddress
to an optional
self?.setShowHideFooter() | ||
// it would be nice to have `tableView.reloadSections([section], with: .bottom)` | ||
// but iOS 11 has an ugly animation bug https://forums.developer.apple.com/thread/86703 | ||
tableView.reloadData() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We've got this working in WPiOS:
1. Log into a wpcom account (in wpios)
2. Open Me > Notification Settings
3. Press over 'View all...'
(That's the animation you'd like to do here!) Snippet here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh thank you! This looks so much better now.
controller.messageComposeDelegate = self | ||
present(controller, animated: true, completion: nil) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should definitely split this one in two. Reasoning is sendTextMessage
doesn't imply the method may or may not do something.
You'd normally cut this this way:
func sendTextMessageIfPossible() { }
private func sendTextMessage() {}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I didn't consider the implications. Glad to make it more explicit
controller.mailComposeDelegate = self | ||
present(controller, animated: true, completion: nil) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Same as above!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Beautiful!!! 🎉
phoneButton.addTarget(self, action: #selector(phoneButtonAction), for: .touchUpInside) | ||
|
||
let iconView = UIView(frame: Constants.accessoryFrame) | ||
iconView .addSubview(phoneButton) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nipticky: extra space
Task #11
To Do
==================================
Display an Order Details view with the customer information section. Note that the Shipping section does not support a phone number property. See API reference.
To Do
Shipping
Billing