|
//
// PhotoDetailViewController.swift
// Paiai_iOS
//
// Created by FFIB on 16/4/6.
// Copyright © 2016年 FFIB. All rights reserved.
//
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
import PaiaiDataKit
import PaiaiUIKit
final class PhotoDetailViewController: UIViewController {
@IBOutlet weak var enterGroupView: UIView!
@IBOutlet weak var group_avatar: UIImageView!
@IBOutlet weak var group_name: UILabel!
@IBOutlet weak var photoCollectionView: UICollectionView!
@IBOutlet weak var userAvatar: UIImageView!
@IBOutlet weak var userName: UILabel!
@IBOutlet weak var photoTime: UILabel!
@IBOutlet weak var thumbupCount: UILabel!
@IBOutlet weak var thumbupView: UIView!
@IBOutlet weak var commentCount: UILabel!
@IBOutlet weak var commentTableView: UITableView!
@IBOutlet weak var commentEditingView: UIView!
@IBOutlet weak var commentHeight: NSLayoutConstraint!
@IBOutlet weak var commentTextField: UITextField!
@IBOutlet weak var sendBtn: UIButton!
@IBOutlet weak var buyView: UIView!
@IBOutlet weak var waterMarkView: UIView!
@IBOutlet weak var waterMarkImage: UIImageView!
@IBOutlet weak var waterMarkLabel: UILabel!
@IBOutlet var keyboardGestureRcognizer: UITapGestureRecognizer!
@IBOutlet weak var thumbupViewHeightConstraint: NSLayoutConstraint!
@IBOutlet weak var commentEditYConstraint: NSLayoutConstraint!
// MARK: data property
var viewModel: PhotoDetailViewModel!
let disposeBag = DisposeBag()
// MARK: view function
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "详情"
binding()
setup()
}
func setup() {
setupCommentTextField()
setupWaterMarkView()
}
func setupCommentTextField() {
commentTextField.addLeftPadding(7)
}
func setupWaterMarkView() {
guard let image = UIImage.PhotoDetail.purchaseBackground else { return }
waterMarkView.backgroundColor = UIColor(patternImage: image)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
viewModel.viewWillAppear.accept(())
}
}
/// bind storyboard gesture action
extension PhotoDetailViewController {
@IBAction func recyclingKeyboard(_ sender: UITapGestureRecognizer) {
commentTextField.resignFirstResponder()
}
@IBAction func purchase(_ sender: UITapGestureRecognizer) {
viewModel.purchase()
}
@IBAction func enterGroup(_ sender: UITapGestureRecognizer) {
viewModel.navigateToGroup()
}
}
/// bind storyboard button action
extension PhotoDetailViewController {
@IBAction func share() {
// let ctl = ShareViewController UIStoryboard.photoDetail.instantiateController(ShareViewController.self)
// ctl.shareContent = "我使用拍爱分享了一张美图,你也快来试试吧"
// // ctl.shareImgUrlThumb = datas[currentPhotoIndex].photo_thumbnail_url
// // ctl.shareUrl = datas[currentPhotoIndex].photo_share_url
// presentController(ctl)
}
@IBAction func comment() {
commentTextField.becomeFirstResponder()
}
@IBAction func sendComment() {
guard let text = commentTextField.text else { return }
viewModel.submitComment(text: text)
commentTextField.resignFirstResponder()
}
@IBAction func thumbup() {
viewModel.submitThumbup()
}
}
/// bind rx
extension PhotoDetailViewController {
var commentDataSource: RxTableViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoCommentItem>> {
return RxTableViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoCommentItem>>(
configureCell: {(_, tableView, indexPath, item) in
let cell = tableView.dequeueReusableCell(withIdentifier: "photoDetailCommentCell",
for: indexPath) as! PhotoDetailCommentCell
cell.setInfo(item)
return cell
})
}
var photoDataSource: RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoItem>> {
return RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoItem>>(
configureCell: {(_, collectionView, indexPath, item) in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoDetailImageCell",
for: indexPath) as! PhotoDetailImageCell
cell.imageView.setImage(item.murl.isEmpty ? item.photo_thumbnail2_url : item.murl,
placeholder: UIImage.photoPlaceholder)
return cell
})
}
func binding() {
bindEnterGroupViewHiddenState()
bindViewModelToGroupName()
bindViewModelToGroupAvatar()
bindViewModelToUserName()
bindgingViewModelToUserAvatar()
bindViewModelToPhotoTime()
bindViewModelToThumbupCount()
bindViewModelToThumbupView()
bindViewModelToCommentCount()
bindViewModelToCommentTableView()
bindBuyViewIsVisiable()
bindCommentTextFieldToSendBtn()
bindCollectionViewDelegate()
bindCollectionViewSelected()
bindCollectionViewToListViewModel()
bindListViewModelToCollectionView()
bindViewModelToWatermarkImage()
bindViewModelToWatermarkLabel()
bindViewModelToWatermarkImageWithBought()
bindViewModelToWatermarkLabelWithBought()
bindViewWillAppear()
monitorKeyboardWillShow()
monitorKeyboardWillHide()
}
func bindEnterGroupViewHiddenState() {
viewModel.isHiddenEnterGroupBtn.bind(to: enterGroupView.rx.isHidden).disposed(by: disposeBag)
}
func bindViewModelToGroupName() {
viewModel.group_name.bind(to: group_name.rx.text).disposed(by: disposeBag)
}
func bindViewModelToGroupAvatar() {
viewModel.group_avatar
.map { UIImage(named: #"Group\#($0)"#)}
.bind(to: group_avatar.rx.image)
.disposed(by: disposeBag)
}
func bindgingViewModelToUserAvatar() {
viewModel.userAvatar
.subscribe(onNext: {[weak self] (avatar) in
guard let `self` = self else { return }
self.userAvatar.setImage(avatar)
}).disposed(by: disposeBag)
}
func bindViewModelToUserName() {
viewModel.userName.bind(to: userName.rx.text).disposed(by: disposeBag)
}
func bindViewModelToPhotoTime() {
viewModel.photoTime.bind(to: photoTime.rx.text).disposed(by: disposeBag)
}
func bindViewModelToThumbupCount() {
viewModel.thumbupCount.bind(to: thumbupCount.rx.text).disposed(by: disposeBag)
}
func bindViewModelToThumbupView() {
viewModel.thumbupItems
.asDriver(onErrorJustReturn: [])
.drive(onNext: { [weak self] (items) in
self?.setupThumbupView(items: items)
}).disposed(by: disposeBag)
}
func bindViewModelToCommentCount() {
viewModel.commentCount.bind(to: commentCount.rx.text).disposed(by: disposeBag)
}
func bindViewModelToCommentTableView() {
viewModel.commentItems
.bind(to: commentTableView.rx.items(dataSource: commentDataSource))
.disposed(by: disposeBag)
}
func bindBuyViewIsVisiable() {
viewModel.canBuy.map { !$0 }.bind(to: buyView.rx.isHidden).disposed(by: disposeBag)
}
func bindCommentTextFieldToSendBtn() {
commentTextField.rx.text
.map { !($0?.isEmpty)! }
.bind(to: sendBtn.rx.isEnabled)
.disposed(by: disposeBag)
}
func bindCollectionViewDelegate() {
photoCollectionView.rx.setDelegate(self).disposed(by: disposeBag)
}
func bindListViewModelToCollectionView() {
viewModel.content
.bind(to: photoCollectionView.rx.items(dataSource: photoDataSource))
.disposed(by: disposeBag)
}
func bindCollectionViewToListViewModel() {
photoCollectionView.rx.willDisplayCell
.asDriver()
.drive(onNext: { [unowned self] in
self.viewModel.willShow(index: $0.at.row)
})
.disposed(by: disposeBag)
}
func bindCollectionViewSelected() {
photoCollectionView.rx.itemSelected
.asDriver(onErrorJustReturn: IndexPath(item: 0, section: 0))
.drive(onNext: { [unowned self] _ in self.viewModel.didSelected() })
.disposed(by: disposeBag)
}
func bindViewModelToWatermarkImage() {
viewModel.watermarkImage.bind(to: waterMarkImage.rx.isHidden).disposed(by: disposeBag)
}
func bindViewModelToWatermarkLabel() {
viewModel.watermarkText.bind(to: waterMarkLabel.rx.text).disposed(by: disposeBag)
}
func bindViewModelToWatermarkImageWithBought() {
viewModel.watermarkImageWithBought.bind(to: waterMarkImage.rx.isHidden).disposed(by: disposeBag)
}
func bindViewModelToWatermarkLabelWithBought() {
viewModel.watermarkTextWithBought.bind(to: waterMarkLabel.rx.text).disposed(by: disposeBag)
}
func bindViewWillAppear() {
viewModel.viewWillAppear
.asDriver()
.drive(onNext: { [unowned self] _ in
self.photoCollectionView.scrollToItem(at: IndexPath(item: self.viewModel.currIndex, section: 0),
at: .right, animated: false)
})
.disposed(by: disposeBag)
}
func monitorKeyboardWillShow() {
NotificationCenter.default.rx
.notification(UIResponder.keyboardWillShowNotification)
.takeUntil(self.rx.deallocated)
.subscribe { [unowned self] notification in
self.keyboardGestureRcognizer.isEnabled = true
guard let userInfo = notification.element?.userInfo,
let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect,
let timeInterval = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval,
let curve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? Int
else { return }
UIView.setAnimationCurve(UIView.AnimationCurve(rawValue: curve) ?? .linear)
UIView.animate(withDuration: timeInterval, animations: {
self.commentEditYConstraint.constant = keyboardFrame.height
self.view.layoutIfNeeded()
})
}.disposed(by: disposeBag)
}
func monitorKeyboardWillHide() {
NotificationCenter.default.rx
.notification(UIResponder.keyboardWillHideNotification)
.takeUntil(self.rx.deallocated)
.subscribe { [unowned self] notification in
self.keyboardGestureRcognizer.isEnabled = false
guard let userInfo = notification.element?.userInfo,
let timeInterval = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval,
let curve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? Int
else { return }
UIView.setAnimationCurve(UIView.AnimationCurve(rawValue: curve) ?? .linear)
UIView.animate(withDuration: timeInterval, animations: {
self.commentEditYConstraint.constant = -56
self.view.layoutIfNeeded()
})
self.commentTextField.clear()
}.disposed(by: disposeBag)
}
}
extension PhotoDetailViewController {
func setupThumbupView(items: [PhotoThumbupUserItem]) {
thumbupView.subviews.forEach { $0.removeFromSuperview() }
let row = (Int(kScreenWidth) - 6) / 34
var topConstraint: CGFloat = 6
var last: UIImageView?
for (index, item) in items.enumerated() {
let imageView = UIImageView()
imageView.cornerRadius = 5
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.setImage(item.avatar, placeholder: UIImage.defaultAvatar)
thumbupView.addSubview(imageView)
if index % row == 0 && index != 0 {
topConstraint += 28 + 6
last = nil
}
NSLayoutConstraint.activate([
imageView.widthAnchor.constraint(equalToConstant: 28),
imageView.heightAnchor.constraint(equalToConstant: 28),
imageView.topAnchor.constraint(equalTo: thumbupView.topAnchor, constant: topConstraint),
imageView.leadingAnchor.constraint(equalTo: last?.trailingAnchor ?? thumbupView.leadingAnchor,
constant: 6)
])
last = imageView
}
thumbupViewHeightConstraint.constant = items.isEmpty ? 1 : topConstraint + 34
commentTableView.tableHeaderView?.height = 532 + thumbupViewHeightConstraint.constant
}
}
extension PhotoDetailViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: kScreenWidth, height: 359)
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
}
extension PhotoDetailViewController: NavigationBackViewController {}
extension PhotoDetailViewController: Storyboarded {
static func instantiate() -> PhotoDetailViewController {
return UIStoryboard.photoDetail.instantiateViewController(type: PhotoDetailViewController.self)
}
}
|