From db0994460641ec66bea7c7b704a50e1819aa33b1 Mon Sep 17 00:00:00 2001 From: Aleksey Belouosv Date: Wed, 8 Jan 2020 11:27:07 +0300 Subject: [PATCH] [iOS] [refactoring] More Reviews screen refactoring --- iphone/Maps/Categories/UIView+Hierarchy.swift | 10 +- iphone/Maps/Maps.xcodeproj/project.pbxproj | 20 +- .../HotelDescriptionViewController.swift | 15 +- .../PlacePage/MoreReviewsViewController.swift | 97 +++++ .../UI/PlacePage/MyReviewViewController.swift | 48 --- iphone/Maps/UI/PlacePage/PlacePage.storyboard | 334 ++++-------------- .../PlacePageBookmarkViewController.swift | 15 +- .../PlacePageReviewViewController.swift | 29 -- .../PlacePageReviewsViewController.swift | 57 +-- .../PlacePage/PlacePageViewController.swift | 11 +- .../UI/PlacePage/Views/ExpandableLabel.swift | 116 ++++-- .../UI/PlacePage/Views/MyReviewView.swift | 91 +++++ .../Maps/UI/PlacePage/Views/ReviewView.swift | 53 +++ 13 files changed, 473 insertions(+), 423 deletions(-) create mode 100644 iphone/Maps/UI/PlacePage/MoreReviewsViewController.swift delete mode 100644 iphone/Maps/UI/PlacePage/MyReviewViewController.swift delete mode 100644 iphone/Maps/UI/PlacePage/PlacePageReviewViewController.swift create mode 100644 iphone/Maps/UI/PlacePage/Views/MyReviewView.swift create mode 100644 iphone/Maps/UI/PlacePage/Views/ReviewView.swift diff --git a/iphone/Maps/Categories/UIView+Hierarchy.swift b/iphone/Maps/Categories/UIView+Hierarchy.swift index 9b1b672cc1..6b9c1209f9 100644 --- a/iphone/Maps/Categories/UIView+Hierarchy.swift +++ b/iphone/Maps/Categories/UIView+Hierarchy.swift @@ -8,13 +8,13 @@ extension UIView { subviews.forEach { $0.clearTreeBackground() } } - func alignToSuperview() { + func alignToSuperview(_ insets: UIEdgeInsets = .zero) { translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ - topAnchor.constraint(equalTo: superview!.topAnchor), - leftAnchor.constraint(equalTo: superview!.leftAnchor), - bottomAnchor.constraint(equalTo: superview!.bottomAnchor), - rightAnchor.constraint(equalTo: superview!.rightAnchor) + topAnchor.constraint(equalTo: superview!.topAnchor, constant: insets.top), + leftAnchor.constraint(equalTo: superview!.leftAnchor, constant: insets.left), + bottomAnchor.constraint(equalTo: superview!.bottomAnchor, constant: insets.bottom), + rightAnchor.constraint(equalTo: superview!.rightAnchor, constant: insets.right) ]) } } diff --git a/iphone/Maps/Maps.xcodeproj/project.pbxproj b/iphone/Maps/Maps.xcodeproj/project.pbxproj index 13c3c91391..79ab2d7829 100644 --- a/iphone/Maps/Maps.xcodeproj/project.pbxproj +++ b/iphone/Maps/Maps.xcodeproj/project.pbxproj @@ -335,7 +335,6 @@ 470A89FD21342A9D00D72FBF /* TutorialBlurView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 470A89FC21342A9D00D72FBF /* TutorialBlurView.swift */; }; 470A89FF2134517600D72FBF /* BookmarksTutorialBlur.xib in Resources */ = {isa = PBXBuildFile; fileRef = 470A89FE2134517600D72FBF /* BookmarksTutorialBlur.xib */; }; 470A8A012136097000D72FBF /* SubwayTutorialBlur.xib in Resources */ = {isa = PBXBuildFile; fileRef = 470A8A002136073000D72FBF /* SubwayTutorialBlur.xib */; }; - 470F0B7A23882955006AEC94 /* PlacePageReviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 470F0B7923882955006AEC94 /* PlacePageReviewViewController.swift */; }; 470F0B7D238842EA006AEC94 /* ExpandableLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 470F0B7C238842EA006AEC94 /* ExpandableLabel.swift */; }; 470F0B7F2388431E006AEC94 /* StarRatingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 470F0B7E2388431E006AEC94 /* StarRatingView.swift */; }; 470F5A5B2181DE7500754295 /* PaidRouteViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 470F5A592181DE7400754295 /* PaidRouteViewController.swift */; }; @@ -359,7 +358,6 @@ 472848FB238573EE00176158 /* RatingSummaryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472848FA238573EE00176158 /* RatingSummaryViewController.swift */; }; 472848FD2386A17500176158 /* AddReviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472848FC2386A17300176158 /* AddReviewViewController.swift */; }; 472848FF2386BE6E00176158 /* PlacePageReviewsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472848FE2386BE6E00176158 /* PlacePageReviewsViewController.swift */; }; - 472849012388098300176158 /* MyReviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472849002388098300176158 /* MyReviewViewController.swift */; }; 47289E5A2212DFFF002ABFC0 /* EditOnWebAlertViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47289E582212DFFF002ABFC0 /* EditOnWebAlertViewController.swift */; }; 47289E5B2212DFFF002ABFC0 /* EditOnWebAlertViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 47289E592212DFFF002ABFC0 /* EditOnWebAlertViewController.xib */; }; 4728F69322CF89A400E00028 /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4728F69222CF89A400E00028 /* GradientView.swift */; }; @@ -393,6 +391,9 @@ 4788738F20EE30B300F6826B /* LayersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4788738D20EE30B300F6826B /* LayersViewController.swift */; }; 4788739020EE30B300F6826B /* LayersViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4788738E20EE30B300F6826B /* LayersViewController.xib */; }; 4788739220EE326500F6826B /* VerticallyAlignedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4788739120EE326400F6826B /* VerticallyAlignedButton.swift */; }; + 478F6FA423C447E500054A53 /* ReviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 478F6FA323C447E500054A53 /* ReviewView.swift */; }; + 478F6FA623C4521F00054A53 /* MoreReviewsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 478F6FA523C4521F00054A53 /* MoreReviewsViewController.swift */; }; + 478F6FA823C5067C00054A53 /* MyReviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 478F6FA723C5067C00054A53 /* MyReviewView.swift */; }; 479388F92395A4D3006ECACC /* ActionBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 479388F82395A4D3006ECACC /* ActionBarViewController.swift */; }; 479D305722C627CB00D18278 /* MWMMegafonBannerViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 479D305522C627CB00D18278 /* MWMMegafonBannerViewController.xib */; }; 479D305B22C62F4000D18278 /* MWMBookmarksBannerViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 479D305922C62F4000D18278 /* MWMBookmarksBannerViewController.xib */; }; @@ -1420,7 +1421,6 @@ 470A89FC21342A9D00D72FBF /* TutorialBlurView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TutorialBlurView.swift; sourceTree = ""; }; 470A89FE2134517600D72FBF /* BookmarksTutorialBlur.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BookmarksTutorialBlur.xib; sourceTree = ""; }; 470A8A002136073000D72FBF /* SubwayTutorialBlur.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SubwayTutorialBlur.xib; sourceTree = ""; }; - 470F0B7923882955006AEC94 /* PlacePageReviewViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlacePageReviewViewController.swift; sourceTree = ""; }; 470F0B7C238842EA006AEC94 /* ExpandableLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpandableLabel.swift; sourceTree = ""; }; 470F0B7E2388431E006AEC94 /* StarRatingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StarRatingView.swift; sourceTree = ""; }; 470F5A592181DE7400754295 /* PaidRouteViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaidRouteViewController.swift; sourceTree = ""; }; @@ -1445,7 +1445,6 @@ 472848FA238573EE00176158 /* RatingSummaryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RatingSummaryViewController.swift; sourceTree = ""; }; 472848FC2386A17300176158 /* AddReviewViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddReviewViewController.swift; sourceTree = ""; }; 472848FE2386BE6E00176158 /* PlacePageReviewsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlacePageReviewsViewController.swift; sourceTree = ""; }; - 472849002388098300176158 /* MyReviewViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyReviewViewController.swift; sourceTree = ""; }; 47289E582212DFFF002ABFC0 /* EditOnWebAlertViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditOnWebAlertViewController.swift; sourceTree = ""; }; 47289E592212DFFF002ABFC0 /* EditOnWebAlertViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = EditOnWebAlertViewController.xib; sourceTree = ""; }; 4728F69222CF89A400E00028 /* GradientView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = GradientView.swift; path = CustomViews/GradientView.swift; sourceTree = ""; }; @@ -1485,6 +1484,9 @@ 4788738D20EE30B300F6826B /* LayersViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayersViewController.swift; sourceTree = ""; }; 4788738E20EE30B300F6826B /* LayersViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LayersViewController.xib; sourceTree = ""; }; 4788739120EE326400F6826B /* VerticallyAlignedButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerticallyAlignedButton.swift; sourceTree = ""; }; + 478F6FA323C447E500054A53 /* ReviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewView.swift; sourceTree = ""; }; + 478F6FA523C4521F00054A53 /* MoreReviewsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoreReviewsViewController.swift; sourceTree = ""; }; + 478F6FA723C5067C00054A53 /* MyReviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyReviewView.swift; sourceTree = ""; }; 479388F82395A4D3006ECACC /* ActionBarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionBarViewController.swift; sourceTree = ""; }; 4797A4DB226F4B2900D3A984 /* DeepLinkHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeepLinkHandler.swift; sourceTree = ""; }; 479D305522C627CB00D18278 /* MWMMegafonBannerViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MWMMegafonBannerViewController.xib; sourceTree = ""; }; @@ -3392,6 +3394,8 @@ children = ( 470F0B7C238842EA006AEC94 /* ExpandableLabel.swift */, 470F0B7E2388431E006AEC94 /* StarRatingView.swift */, + 478F6FA323C447E500054A53 /* ReviewView.swift */, + 478F6FA723C5067C00054A53 /* MyReviewView.swift */, ); path = Views; sourceTree = ""; @@ -4470,8 +4474,7 @@ 472848FA238573EE00176158 /* RatingSummaryViewController.swift */, 472848FC2386A17300176158 /* AddReviewViewController.swift */, 472848FE2386BE6E00176158 /* PlacePageReviewsViewController.swift */, - 472849002388098300176158 /* MyReviewViewController.swift */, - 470F0B7923882955006AEC94 /* PlacePageReviewViewController.swift */, + 478F6FA523C4521F00054A53 /* MoreReviewsViewController.swift */, 47F701F5238C8A8300D18E95 /* PlacePageButtonsViewController.swift */, 47A0416C238DBB6200D84E95 /* HotelPhotosViewController.swift */, 47A0416E238DD0FD00D84E95 /* HotelDescriptionViewController.swift */, @@ -5481,6 +5484,7 @@ 349D1ADE1E2E325C004A2006 /* MWMBottomMenuViewController.mm in Sources */, BB87BF8A22FAF1CA008A8A72 /* TracksSection.mm in Sources */, 6741A9EC1BF340DE002C974C /* MWMCircularProgress.m in Sources */, + 478F6FA423C447E500054A53 /* ReviewView.swift in Sources */, 99CB34C3236AEAEA001D28AD /* WhatsNewController.swift in Sources */, 470A89FD21342A9D00D72FBF /* TutorialBlurView.swift in Sources */, 342CC5F21C2D7730005F3FE5 /* MWMAuthorizationLoginViewController.mm in Sources */, @@ -5578,7 +5582,6 @@ 34FE5A6F1F18F30F00BCA729 /* TrafficButtonArea.swift in Sources */, F6E2FF691E097BA00083EBEC /* MWMUnitsController.mm in Sources */, 6741AA031BF340DE002C974C /* MWMActivityViewController.mm in Sources */, - 472849012388098300176158 /* MyReviewViewController.swift in Sources */, CDCA27382237F1BD00167D87 /* BookmarkInfo.swift in Sources */, 993F5509237C622700545511 /* DeepLinkHandlerStrategy.swift in Sources */, 34AB668C1FC5AA330078E451 /* NavigationStreetNameView.swift in Sources */, @@ -5590,6 +5593,7 @@ 472E3F472146BCD30020E412 /* SubscriptionManager.swift in Sources */, F6E2FE131E097BA00083EBEC /* MWMOpeningHoursTimeSelectorTableViewCell.mm in Sources */, 344532311F6FE5880059FBCC /* UGCSummaryRatingStarsCell.swift in Sources */, + 478F6FA623C4521F00054A53 /* MoreReviewsViewController.swift in Sources */, F626D52F1C3E83F800C17D15 /* MWMTableViewCell.m in Sources */, 34AB66591FC5AA330078E451 /* TransportTransitFlowLayout.swift in Sources */, 99CB34962369C281001D28AD /* FirstLaunchBuilder.swift in Sources */, @@ -5645,6 +5649,7 @@ B32FE74020D2844600EF7446 /* DownloadedBookmarksViewController.swift in Sources */, 4707E4B62375B2900017DF6E /* PlacePagePreviewViewController.swift in Sources */, 340416541E7C09C200E2B6D6 /* PhotoScalingView.swift in Sources */, + 478F6FA823C5067C00054A53 /* MyReviewView.swift in Sources */, 4767CDA820AB401000BD8166 /* LinkTextView.swift in Sources */, 47289E5A2212DFFF002ABFC0 /* EditOnWebAlertViewController.swift in Sources */, 34763EE71F2F392300F4D2D3 /* MWMTextToSpeech.mm in Sources */, @@ -5790,7 +5795,6 @@ F5BD29FF26AD58255766C51A /* DiscoverySpinnerCell.swift in Sources */, 47E3C72B2111E62A008B3B27 /* FadeOutAnimatedTransitioning.swift in Sources */, F5BD255A0838E70EC012748E /* DiscoverySearchCell.swift in Sources */, - 470F0B7A23882955006AEC94 /* PlacePageReviewViewController.swift in Sources */, 47C7F9732191E15A00C2760C /* InAppBilling.swift in Sources */, F5BD2CA4DBEFACBC48195F39 /* DiscoveryCollectionHolderCell.swift in Sources */, ); diff --git a/iphone/Maps/UI/PlacePage/HotelDescriptionViewController.swift b/iphone/Maps/UI/PlacePage/HotelDescriptionViewController.swift index 194a2ded4c..bec321c488 100644 --- a/iphone/Maps/UI/PlacePage/HotelDescriptionViewController.swift +++ b/iphone/Maps/UI/PlacePage/HotelDescriptionViewController.swift @@ -8,7 +8,7 @@ class HotelDescriptionViewController: UIViewController { var hotelDescription: String? { didSet { - descriptionExpandableLabel.textLabel.text = hotelDescription + descriptionExpandableLabel.text = hotelDescription } } weak var delegate: HotelDescriptionViewControllerDelegate? @@ -16,13 +16,12 @@ class HotelDescriptionViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - descriptionExpandableLabel.textLabel.numberOfLines = 3 - descriptionExpandableLabel.textLabel.text = hotelDescription - descriptionExpandableLabel.textLabel.font = UIFont.regular16() - descriptionExpandableLabel.textLabel.textColor = UIColor.blackPrimaryText() - descriptionExpandableLabel.expandButton.setTitleColor(UIColor.linkBlue(), for: .normal) - descriptionExpandableLabel.expandButton.titleLabel?.font = UIFont.regular16() - descriptionExpandableLabel.expandButton.setTitle(L("booking_show_more"), for: .normal) + descriptionExpandableLabel.numberOfLines = 3 + descriptionExpandableLabel.text = hotelDescription + descriptionExpandableLabel.font = UIFont.regular16() + descriptionExpandableLabel.textColor = UIColor.blackPrimaryText() + descriptionExpandableLabel.expandColor = UIColor.linkBlue() + descriptionExpandableLabel.expandText = L("booking_show_more") } @IBAction func onMoreButton(_ sender: UIButton) { diff --git a/iphone/Maps/UI/PlacePage/MoreReviewsViewController.swift b/iphone/Maps/UI/PlacePage/MoreReviewsViewController.swift new file mode 100644 index 0000000000..fa7e61011d --- /dev/null +++ b/iphone/Maps/UI/PlacePage/MoreReviewsViewController.swift @@ -0,0 +1,97 @@ +final class MyReviewCell: MWMTableViewCell { + @IBOutlet var myReviewView: MyReviewView! + + override func awakeFromNib() { + super.awakeFromNib() + myReviewView.defaultConfig() + } + + func config(_ myReview: UgcMyReview, + formatter: DateFormatter, + expanded: Bool, + onExpand: @escaping ExpandableLabel.OnExpandClosure) { + myReviewView.defaultConfig() + myReviewView.reviewView.authorLabel.text = L("placepage_reviews_your_comment") + myReviewView.reviewView.dateLabel.text = formatter.string(from: myReview.date) + myReviewView.reviewView.reviewLabel.text = myReview.text + myReviewView.reviewView.reviewLabel.numberOfLines = expanded ? 0 : 2 + myReviewView.reviewView.reviewLabel.onExpandClosure = onExpand + + for i in 0..<3 { + if myReview.starRatings.count > i { + let starRating = myReview.starRatings[i] + myReviewView.ratingViews[i].nameLabel.text = L(starRating.title) + myReviewView.ratingViews[i].starRatingView.rating = Int(round(starRating.value)) + } else { + myReviewView.ratingViews[i].isHidden = true + } + } + } +} + +final class UserReviewCell: MWMTableViewCell { + @IBOutlet var reviewView: ReviewView! + + override func awakeFromNib() { + super.awakeFromNib() + reviewView.defaultConfig() + } + + func config(_ review: UgcReview, formatter: DateFormatter, expanded: Bool, onExpand: @escaping ExpandableLabel.OnExpandClosure) { + reviewView.authorLabel.text = review.author + reviewView.dateLabel.text = formatter.string(from: review.date) + reviewView.reviewLabel.text = review.text + reviewView.reviewLabel.numberOfLines = expanded ? 0 : 2 + reviewView.reviewLabel.onExpandClosure = onExpand + } +} + +final class MoreReviewsViewController: MWMTableViewController { + private var expanded: [Bool] = [] + + var ugcData: UgcData? { + didSet { + expanded = Array(repeating: false, count: tableView.numberOfRows(inSection: 0)) + } + } + + private lazy var dateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateStyle = .long + formatter.timeStyle = .none + return formatter + } () + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + let reviewsCount = ugcData?.reviews.count ?? 0 + return reviewsCount + (ugcData?.myReview != nil ? 1 : 0); + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + if let myReview = ugcData?.myReview, indexPath.item == 0 { + let cell = tableView.dequeueReusableCell(withIdentifier: "MyReviewCell", for: indexPath) as! MyReviewCell + cell.config(myReview, formatter: dateFormatter, expanded: expanded[indexPath.row]) { [unowned self] expandClosure in + tableView.performBatchUpdates({ + self.expanded[indexPath.row] = true + expandClosure() + }) + } + return cell + } + + let cell = tableView.dequeueReusableCell(withIdentifier: "UserReviewCell", for: indexPath) as! UserReviewCell + var index = indexPath.item - (ugcData?.myReview != nil ? 1 : 0) + if index >= ugcData!.reviews.count { + index = index % ugcData!.reviews.count + } + guard let review = ugcData?.reviews[index] else { fatalError() } + cell.config(review, formatter: dateFormatter, expanded: expanded[indexPath.row]) { [unowned self] expandClosure in + tableView.performBatchUpdates({ + self.expanded[indexPath.row] = true + expandClosure() + }) + } + + return cell + } +} diff --git a/iphone/Maps/UI/PlacePage/MyReviewViewController.swift b/iphone/Maps/UI/PlacePage/MyReviewViewController.swift deleted file mode 100644 index 0377d51c9b..0000000000 --- a/iphone/Maps/UI/PlacePage/MyReviewViewController.swift +++ /dev/null @@ -1,48 +0,0 @@ -class MyReviewViewController: UIViewController { - @IBOutlet var dateLabel: UILabel! - @IBOutlet var expandableLabel: ExpandableLabel! { - didSet { - expandableLabel.textLabel.font = UIFont.regular14() - expandableLabel.textLabel.textColor = UIColor.blackPrimaryText() - expandableLabel.expandButton.setTitleColor(UIColor.linkBlue(), for: .normal) - expandableLabel.expandButton.titleLabel?.font = UIFont.regular14() - expandableLabel.expandButton.setTitle(L("placepage_more_button"), for: .normal) - } - } - - @IBOutlet var ratingViews: [UIView]! - @IBOutlet var ratingLabels: [UILabel]! - @IBOutlet var starViews: [StarRatingView]! { - didSet { - starViews.forEach { - $0.activeColor = UIColor.yellow - $0.inactiveColor = UIColor.blackDividers() - } - } - } - - var myReview: UgcMyReview! - lazy var dateFormatter: DateFormatter = { - let formatter = DateFormatter() - formatter.dateStyle = .long - formatter.timeStyle = .none - return formatter - } () - - override func viewDidLoad() { - super.viewDidLoad() - - dateLabel.text = dateFormatter.string(from: myReview.date) - expandableLabel.textLabel.text = myReview.text - - for i in 0..<3 { - if myReview.starRatings.count > i { - let starRating = myReview.starRatings[i] - ratingLabels[i].text = L(starRating.title) - starViews[i].rating = Int(round(starRating.value)) - } else { - ratingViews[i].isHidden = true - } - } - } -} diff --git a/iphone/Maps/UI/PlacePage/PlacePage.storyboard b/iphone/Maps/UI/PlacePage/PlacePage.storyboard index bcd43a162a..97498518e1 100644 --- a/iphone/Maps/UI/PlacePage/PlacePage.storyboard +++ b/iphone/Maps/UI/PlacePage/PlacePage.storyboard @@ -1,9 +1,9 @@ - + - + @@ -1875,195 +1875,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2180,81 +1991,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -3204,6 +2940,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iphone/Maps/UI/PlacePage/PlacePageBookmarkViewController.swift b/iphone/Maps/UI/PlacePage/PlacePageBookmarkViewController.swift index d7054edaa0..e47eb8c408 100644 --- a/iphone/Maps/UI/PlacePage/PlacePageBookmarkViewController.swift +++ b/iphone/Maps/UI/PlacePage/PlacePageBookmarkViewController.swift @@ -8,12 +8,11 @@ class PlacePageBookmarkViewController: UIViewController { @IBOutlet var editButton: UIButton! @IBOutlet var expandableLabel: ExpandableLabel! { didSet { - expandableLabel.textLabel.font = UIFont.regular14() - expandableLabel.textLabel.textColor = UIColor.blackPrimaryText() - expandableLabel.textLabel.numberOfLines = 5 - expandableLabel.expandButton.setTitleColor(UIColor.linkBlue(), for: .normal) - expandableLabel.expandButton.titleLabel?.font = UIFont.regular14() - expandableLabel.expandButton.setTitle(L("placepage_more_button"), for: .normal) + expandableLabel.font = UIFont.regular14() + expandableLabel.textColor = UIColor.blackPrimaryText() + expandableLabel.numberOfLines = 5 + expandableLabel.expandColor = UIColor.linkBlue() + expandableLabel.expandText = L("placepage_more_button") } } @@ -36,7 +35,7 @@ class PlacePageBookmarkViewController: UIViewController { if bookmarkData.isHtmlDescription { setHtmlDescription(description) } else { - expandableLabel.textLabel.text = description + expandableLabel.text = description } } } @@ -62,7 +61,7 @@ class PlacePageBookmarkViewController: UIViewController { } DispatchQueue.main.async { - self.expandableLabel.textLabel.attributedText = attributedString + self.expandableLabel.attributedText = attributedString } } } diff --git a/iphone/Maps/UI/PlacePage/PlacePageReviewViewController.swift b/iphone/Maps/UI/PlacePage/PlacePageReviewViewController.swift deleted file mode 100644 index 82747db262..0000000000 --- a/iphone/Maps/UI/PlacePage/PlacePageReviewViewController.swift +++ /dev/null @@ -1,29 +0,0 @@ -class PlacePageReviewViewController: UIViewController { - @IBOutlet var titleLabel: UILabel! - @IBOutlet var dateLabel: UILabel! - @IBOutlet var expandableLabel: ExpandableLabel! { - didSet { - expandableLabel.textLabel.font = UIFont.regular14() - expandableLabel.textLabel.textColor = UIColor.blackPrimaryText() - expandableLabel.expandButton.setTitleColor(UIColor.linkBlue(), for: .normal) - expandableLabel.expandButton.titleLabel?.font = UIFont.regular14() - expandableLabel.expandButton.setTitle(L("placepage_more_button"), for: .normal) - } - } - - var review: UgcReview! - lazy var dateFormatter: DateFormatter = { - let formatter = DateFormatter() - formatter.dateStyle = .long - formatter.timeStyle = .none - return formatter - } () - - override func viewDidLoad() { - super.viewDidLoad() - - titleLabel.text = review.author - dateLabel.text = dateFormatter.string(from: review.date) - expandableLabel.textLabel.text = review.text - } -} diff --git a/iphone/Maps/UI/PlacePage/PlacePageReviewsViewController.swift b/iphone/Maps/UI/PlacePage/PlacePageReviewsViewController.swift index c6b4c3c09e..6ba0386efd 100644 --- a/iphone/Maps/UI/PlacePage/PlacePageReviewsViewController.swift +++ b/iphone/Maps/UI/PlacePage/PlacePageReviewsViewController.swift @@ -2,7 +2,7 @@ protocol PlacePageReviewsViewControllerDelegate: AnyObject { func didPressMoreReviews() } -class PlacePageReviewsViewController: UIViewController { +final class PlacePageReviewsViewController: UIViewController { @IBOutlet var stackView: UIStackView! var ugcData: UgcData? { @@ -10,33 +10,44 @@ class PlacePageReviewsViewController: UIViewController { updateReviews() } } + weak var delegate: PlacePageReviewsViewControllerDelegate? - lazy var myReviewViewController: MyReviewViewController = { - let vc = storyboard!.instantiateViewController(ofType: MyReviewViewController.self) - return vc - } () - - override func viewDidLoad() { - super.viewDidLoad() - } - // MARK: private + private lazy var dateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateStyle = .long + formatter.timeStyle = .none + return formatter + } () + private func updateReviews() { guard let ugcData = ugcData else { return } if let myReview = ugcData.myReview { - myReviewViewController.myReview = myReview - addToStack(myReviewViewController) + let myReviewView = MyReviewView() + myReviewView.defaultConfig() + myReviewView.reviewView.authorLabel.text = L("placepage_reviews_your_comment") + myReviewView.reviewView.dateLabel.text = dateFormatter.string(from: myReview.date) + myReviewView.reviewView.reviewLabel.text = myReview.text + + for i in 0..<3 { + if myReview.starRatings.count > i { + let starRating = myReview.starRatings[i] + myReviewView.ratingViews[i].nameLabel.text = L(starRating.title) + myReviewView.ratingViews[i].starRatingView.rating = Int(round(starRating.value)) + } else { + myReviewView.ratingViews[i].isHidden = true + } + } + stackView.addArrangedSubview(myReviewView) } for i in 0..<3 { if i < ugcData.reviews.count { let review = ugcData.reviews[i] - let vc = storyboard!.instantiateViewController(ofType: PlacePageReviewViewController.self) - vc.review = review - addToStack(vc) + addReviewView(review) } else { break } @@ -47,6 +58,16 @@ class PlacePageReviewsViewController: UIViewController { } } + private func addReviewView(_ review: UgcReview) { + let reviewView = ReviewView() + reviewView.defaultConfig() + reviewView.authorLabel.text = review.author + reviewView.dateLabel.text = dateFormatter.string(from: review.date) + reviewView.reviewLabel.text = review.text + + stackView.addArrangedSubview(reviewView) + } + @objc private func onMoreReviewsButton(_ sender: UIButton) { delegate?.didPressMoreReviews() } @@ -60,10 +81,4 @@ class PlacePageReviewsViewController: UIViewController { stackView.addArrangedSubview(button) button.addTarget(self, action: #selector(onMoreReviewsButton), for: .touchUpInside) } - - private func addToStack(_ viewController: UIViewController) { - addChild(viewController) - stackView.addArrangedSubview(viewController.view) - viewController.didMove(toParent: self) - } } diff --git a/iphone/Maps/UI/PlacePage/PlacePageViewController.swift b/iphone/Maps/UI/PlacePage/PlacePageViewController.swift index 5d6177f563..6a152227c5 100644 --- a/iphone/Maps/UI/PlacePage/PlacePageViewController.swift +++ b/iphone/Maps/UI/PlacePage/PlacePageViewController.swift @@ -339,11 +339,11 @@ enum PlacePageState { } private func updatePreviewOffset() { - if traitCollection.horizontalSizeClass != .compact { - return - } self.view.layoutIfNeeded() scrollSteps = calculateSteps() + if traitCollection.horizontalSizeClass != .compact || beginDragging { + return + } let state = placePageData.isPreviewPlus ? scrollSteps[2] : scrollSteps[1] UIView.animate(withDuration: kDefaultAnimationDuration) { self.scrollView.contentOffset = CGPoint(x: 0, y: state.offset) @@ -421,7 +421,10 @@ extension PlacePageViewController: AddReviewViewControllerDelegate { extension PlacePageViewController: PlacePageReviewsViewControllerDelegate { func didPressMoreReviews() { - + let moreReviews = storyboard!.instantiateViewController(ofType: MoreReviewsViewController.self) + moreReviews.ugcData = placePageData.ugcData + moreReviews.title = placePageData.previewData.title + MapViewController.shared()?.navigationController?.pushViewController(moreReviews, animated: true) } } diff --git a/iphone/Maps/UI/PlacePage/Views/ExpandableLabel.swift b/iphone/Maps/UI/PlacePage/Views/ExpandableLabel.swift index 1f8f8744a3..3a9b8d5aa3 100644 --- a/iphone/Maps/UI/PlacePage/Views/ExpandableLabel.swift +++ b/iphone/Maps/UI/PlacePage/Views/ExpandableLabel.swift @@ -1,8 +1,56 @@ -class ExpandableLabel: UIView { - private var stackView = UIStackView() - var textLabel = UILabel() - var expandButton = UIButton() - var expanded = false +final class ExpandableLabel: UIView { + typealias OnExpandClosure = (() -> Void) -> Void + + private let stackView = UIStackView() + private let textLabel = UILabel() + private let expandLabel = UILabel() + + var onExpandClosure: OnExpandClosure? + + var font = UIFont.systemFont(ofSize: 16) { + didSet { + textLabel.font = font + expandLabel.font = font + } + } + + var textColor = UIColor.black { + didSet { + textLabel.textColor = textColor + } + } + + var expandColor = UIColor.systemBlue { + didSet { + expandLabel.textColor = expandColor + } + } + + var text: String? { + didSet { + textLabel.text = text + expandLabel.isHidden = true + } + } + + var attributedText: NSAttributedString? { + didSet { + textLabel.attributedText = attributedText + expandLabel.isHidden = true + } + } + + var expandText = "More" { + didSet { + expandLabel.text = expandText + } + } + + var numberOfLines = 2 { + didSet { + textLabel.numberOfLines = numberOfLines > 0 ? numberOfLines + 1 : 0 + } + } override init(frame: CGRect) { super.init(frame: frame) @@ -15,44 +63,60 @@ class ExpandableLabel: UIView { } private func commonInit() { - stackView.translatesAutoresizingMaskIntoConstraints = false stackView.axis = .vertical stackView.alignment = .leading - textLabel.numberOfLines = 2 + textLabel.numberOfLines = numberOfLines > 0 ? numberOfLines + 1 : 0 textLabel.contentMode = .topLeft - expandButton.clipsToBounds = true - expandButton.addTarget(self, action: #selector(onExpand(_:)), for: .touchUpInside) + textLabel.font = font + textLabel.textColor = textColor + textLabel.text = text + textLabel.attributedText = attributedText + expandLabel.font = font + expandLabel.textColor = expandColor + expandLabel.text = expandText + expandLabel.isHidden = true addSubview(stackView) stackView.addArrangedSubview(textLabel) - stackView.addArrangedSubview(expandButton) - NSLayoutConstraint.activate([ - stackView.leftAnchor.constraint(equalTo: leftAnchor), - stackView.topAnchor.constraint(equalTo: topAnchor), - stackView.rightAnchor.constraint(equalTo: rightAnchor), - stackView.bottomAnchor.constraint(equalTo: bottomAnchor) - ]) + stackView.addArrangedSubview(expandLabel) + stackView.alignToSuperview() + let gr = UITapGestureRecognizer(target: self, action: #selector(onExpand(_:))) + addGestureRecognizer(gr) } - @objc func onExpand(_ sender: UIButton) { - UIView.animate(withDuration: kDefaultAnimationDuration) { - self.textLabel.numberOfLines = 0 - self.expandButton.isHidden = true - self.stackView.layoutIfNeeded() + @objc func onExpand(_ sender: UITapGestureRecognizer) { + if expandLabel.isHidden { return } + + let expandClosure = { + UIView.animate(withDuration: kDefaultAnimationDuration) { + self.textLabel.numberOfLines = 0 + self.expandLabel.isHidden = true + self.stackView.layoutIfNeeded() + } + } + if let onExpandClosure = onExpandClosure { + onExpandClosure(expandClosure) + } else { + expandClosure() } } override func layoutSubviews() { super.layoutSubviews() - guard let s = textLabel.text as NSString? else { return } - let textRect = s.boundingRect(with: size, + guard textLabel.numberOfLines > 0, textLabel.numberOfLines != numberOfLines, let s = textLabel.text as NSString? else { return } + let textRect = s.boundingRect(with: CGSize(width: width, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, - attributes: [.font: textLabel.font!], + attributes: [.font: font], context: nil) let lineHeight = textLabel.font.lineHeight - if Int(lineHeight * CGFloat(textLabel.numberOfLines)) >= Int(textRect.height) { - expandButton.isHidden = true + if Int(lineHeight * CGFloat(numberOfLines + 1)) >= Int(textRect.height) { + expandLabel.isHidden = true + textLabel.numberOfLines = 0 + } else { + expandLabel.isHidden = false + textLabel.numberOfLines = numberOfLines } + layoutIfNeeded() } } diff --git a/iphone/Maps/UI/PlacePage/Views/MyReviewView.swift b/iphone/Maps/UI/PlacePage/Views/MyReviewView.swift new file mode 100644 index 0000000000..0689ab9287 --- /dev/null +++ b/iphone/Maps/UI/PlacePage/Views/MyReviewView.swift @@ -0,0 +1,91 @@ +final class ReviewRatingView: UIView { + private let stackView = UIStackView() + let nameLabel = UILabel() + let starRatingView = StarRatingView() + + override init(frame: CGRect) { + super.init(frame: frame) + + stackView.axis = .vertical + stackView.alignment = .leading + stackView.spacing = 4 + addSubview(stackView) + + stackView.addArrangedSubview(nameLabel) + stackView.addArrangedSubview(starRatingView) + stackView.alignToSuperview() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +extension ReviewRatingView { + func defaultConfig() { + nameLabel.font = UIFont.regular14() + nameLabel.textColor = UIColor.blackSecondaryText() + starRatingView.activeColor = UIColor.ratingYellow() + starRatingView.inactiveColor = UIColor.blackDividers() + } +} + +final class MyReviewView: UIView { + private let stackView = UIStackView() + private let ratingsStackView = UIStackView() + private let ratingsContainerView = UIView() + let reviewView = ReviewView() + let ratingViews = [ReviewRatingView(), ReviewRatingView(), ReviewRatingView()] + let separator = UIView() + + override init(frame: CGRect) { + super.init(frame: frame) + commonInit() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + commonInit() + } + + private func commonInit() { + stackView.axis = .vertical + stackView.alignment = .fill + stackView.spacing = 8 + addSubview(stackView) + + ratingsStackView.axis = .horizontal + ratingsStackView.alignment = .fill + ratingsStackView.distribution = .fillEqually + ratingsContainerView.addSubview(ratingsStackView) + ratingsStackView.alignToSuperview(UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 0)) + + stackView.addArrangedSubview(reviewView) + stackView.addArrangedSubview(ratingsContainerView) + + ratingViews.forEach { + ratingsStackView.addArrangedSubview($0) + } + + stackView.alignToSuperview(UIEdgeInsets(top: 0, left: 0, bottom: -16, right: 0)) + + separator.translatesAutoresizingMaskIntoConstraints = false + addSubview(separator) + NSLayoutConstraint.activate([ + separator.heightAnchor.constraint(equalToConstant: 1), + separator.leftAnchor.constraint(equalTo: leftAnchor), + separator.bottomAnchor.constraint(equalTo: bottomAnchor), + separator.rightAnchor.constraint(equalTo: rightAnchor) + ]) + } +} + +extension MyReviewView { + func defaultConfig() { + reviewView.defaultConfig() + ratingViews.forEach { + $0.defaultConfig() + } + separator.backgroundColor = UIColor.blackDividers() + } +} diff --git a/iphone/Maps/UI/PlacePage/Views/ReviewView.swift b/iphone/Maps/UI/PlacePage/Views/ReviewView.swift new file mode 100644 index 0000000000..d65636d859 --- /dev/null +++ b/iphone/Maps/UI/PlacePage/Views/ReviewView.swift @@ -0,0 +1,53 @@ +final class ReviewView: UIView { + private let stackView = UIStackView() + let authorLabel = UILabel() + let dateLabel = UILabel() + let reviewLabel = ExpandableLabel() + let separator = UIView() + + override init(frame: CGRect) { + super.init(frame: frame) + commonInit() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + commonInit() + } + + private func commonInit() { + stackView.axis = .vertical + stackView.alignment = .leading + stackView.spacing = 4 + addSubview(stackView) + + stackView.addArrangedSubview(authorLabel) + stackView.addArrangedSubview(dateLabel) + stackView.addArrangedSubview(reviewLabel) + stackView.setCustomSpacing(8, after: dateLabel) + stackView.alignToSuperview(UIEdgeInsets(top: 16, left: 16, bottom: -8, right: -16)) + + separator.translatesAutoresizingMaskIntoConstraints = false + addSubview(separator) + NSLayoutConstraint.activate([ + separator.heightAnchor.constraint(equalToConstant: 1), + separator.leftAnchor.constraint(equalTo: authorLabel.leftAnchor), + separator.bottomAnchor.constraint(equalTo: bottomAnchor), + separator.rightAnchor.constraint(equalTo: rightAnchor) + ]) + } +} + +extension ReviewView { + func defaultConfig() { + authorLabel.font = UIFont.bold14() + authorLabel.textColor = UIColor.blackPrimaryText() + dateLabel.font = UIFont.regular12() + dateLabel.textColor = UIColor.blackSecondaryText() + reviewLabel.font = UIFont.regular14() + reviewLabel.textColor = UIColor.blackPrimaryText() + reviewLabel.expandColor = UIColor.linkBlue() + reviewLabel.expandText = L("placepage_more_button") + separator.backgroundColor = UIColor.blackDividers() + } +}