import UIKit import Firebase import SDWebImage import MessageUI import StoreKit import ProgressHUD class ThumbnailCollectionViewCell: UICollectionViewCell { @IBOutlet weak var imageView: UIImageView? } class ProfileInfoViewCell: UICollectionReusableView { @IBOutlet weak var lblFollowingsCount: UILabel? @IBOutlet weak var lblFollowersCount: UILabel? @IBOutlet weak var lblPostsCount: UILabel? @IBOutlet weak var pvPhoto: ProfileView? @IBOutlet weak var lblUsername: UILabel? @IBOutlet weak var btnAction: UIButton? @IBOutlet weak var bioText: UITextView? @IBOutlet weak var premiumIndicator: UIImageView! @IBOutlet weak var confirmedIndicator: UIImageView! @IBOutlet weak var premiumButton: UIButton! override func awakeFromNib() { super.awakeFromNib() premiumButton.addTarget(self, action: #selector(buyPremium), for: .touchUpInside) } var premiumDone: (() -> Void)? var defaultColor = UIColor.darkText var currentUser: UserModel? var isPremium: Bool? var isFollow: Bool = false { didSet { btnAction?.layer.borderColor = defaultColor.cgColor if isFollow { btnAction?.setTitle(NSLocalizedString("Unfollow", comment: ""), for: .normal) btnAction?.backgroundColor = defaultColor btnAction?.setTitleColor(.white, for: .normal) } else { btnAction?.setTitle(NSLocalizedString("Follow", comment: ""), for: .normal) btnAction?.setTitleColor(defaultColor, for: .normal) btnAction?.backgroundColor = .clear } } } var controller: UIViewController? private let iapManager = IAppManager.shared @IBAction func actionButton() { // follow/unfollow user if let user = self.currentUser, !user.isCurrent() { isFollow = !isFollow if user.isFollow { user.unfollow() } else { user.follow() } } else { controller?.performSegue(withIdentifier: "profile.edit", sender: self) } } func addNotificObserver() { NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: nPurchaseComplited), object: nil, queue: nil) { (notification) in print("Покупка выполнена!") DispatchQueue.main.async { self.isPremium = true self.currentUser?.premiumStatus = true FirebaseClient().savePremiumStatus() self.checkPremium() ProgressHUD.dismiss() self.premiumDone?() } } NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: nPurchaseError), object: nil, queue: nil) { (notification) in print("Ошибка совершения покупки!") DispatchQueue.main.async { ProgressHUD.dismiss() } } } @objc private func buyPremium() { ProgressHUD.show() let identifier = iapManager.products[0].productIdentifier iapManager.purchases(productWith: identifier) } func checkPremium() { if !(self.currentUser?.isCurrent() ?? false) { premiumButton.isHidden = true premiumIndicator.isHidden = !(self.isPremium ?? false) } else { if (self.isPremium ?? false) { premiumIndicator.isHidden = false premiumButton.isHidden = true } else { premiumIndicator.isHidden = true premiumButton.isHidden = false } } } } class ProfileViewController: UICollectionViewController { var activities: NSMutableArray = [] var currentUser: UserModel? = UserModel.current override func viewDidLoad() { super.viewDidLoad() // hide back button text if let collectionWidth = self.collectionView?.bounds.size.width { let cellWidth = collectionWidth/kFavoritesColumns - 1 // minus px padding let flowLayout = self.collectionViewLayout as? UICollectionViewFlowLayout flowLayout?.itemSize = CGSize(width: cellWidth, height: cellWidth) } // remove text 'Back' self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) } override func viewWillAppear(_ animated: Bool) { // load user profile and keep tracking update guard let user = self.currentUser else { return } user.ref.observe(.value, with: { (snap) in user.followersCount = snap.childSnapshot(forPath: kFollowersKey).childrenCount user.followingsCount = snap.childSnapshot(forPath: kFollowinsKey).childrenCount user.loadData(snap: snap, with: { (success) in self.displayUserInfo() }) }) // load favorites/likes collection if let key = user.ref.key { loadActivity(key) } if user.blockedMe() { showBlockedMessage() } } func showBlockedMessage() { let alert = UIAlertController(title: "blocked".localized, message: "blocked.message".localized, preferredStyle: .alert) let action = UIAlertAction(title: "dismiss".localized, style: .cancel) { (action) in self.navigationController?.popViewController(animated: true) } alert.addAction(action) present(alert, animated: true, completion: nil) } func displayUserInfo() { self.navigationItem.title = self.currentUser?.name self.collectionView?.reloadData() } func loadActivity(_ userId: String) { let favorites = UserModel(userId).uploads let ref = favorites.queryOrderedByValue() // bind items, and update collection ref.observe(.value, with: { (snapshot) -> Void in self.activities = NSMutableArray(array: snapshot.children.allObjects) self.collectionView?.reloadData() }) } // MARK: - Table view data source // Layout views in kFavoritesColumns columns override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return self.activities.count } override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { var profileView: ProfileInfoViewCell! = nil if kind == UICollectionElementKindSectionHeader { profileView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "Cell", for: indexPath) as? ProfileInfoViewCell let placeholder = UIImage(named: "avatarPlaceholder")! profileView.currentUser = self.currentUser profileView.controller = self profileView.confirmedIndicator.isHidden = !(currentUser?.verified ?? false) profileView.isPremium = currentUser?.premiumStatus profileView.addNotificObserver() profileView.checkPremium() profileView.premiumDone = { self.currentUser?.premiumStatus = true } profileView.lblFollowingsCount?.text = "\(self.currentUser?.followingsCount ?? 0)" profileView.lblFollowersCount?.text = "\(self.currentUser?.followersCount ?? 0)" profileView.lblPostsCount?.text = "\(self.activities.count)" profileView.lblUsername?.text = currentUser?.name profileView.bioText?.text = currentUser?.bio profileView.needsUpdateConstraints() if let photo = URL(string: currentUser!.photo) { profileView.pvPhoto?.sd_setImage(with: photo, placeholderImage: placeholder, completed: { (image, error, cache, url) in profileView.pvPhoto?.layoutSubviews() }) } if let user = self.currentUser, !user.isCurrent() { profileView.btnAction?.setTitle("Follow", for: UIControlState.normal) profileView.btnAction?.setTitle("Unfollow", for: UIControlState.selected) profileView.isFollow = user.isFollow } } return profileView } override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as? ThumbnailCollectionViewCell, let r = self.activities.object(at: (indexPath as NSIndexPath).row) as? DataSnapshot else { return UICollectionViewCell() } // Configure the cell let story = Story(r.key) cell.imageView?.image = UIImage(named: kDefaultProfilePhoto) cell.imageView?.sd_cancelCurrentImageLoad() story.fetchInBackground { (model, success) in cell.imageView?.sd_imageIndicator = SDWebImageActivityIndicator.gray cell.imageView?.sd_setImage(with: URL(string: story.media)) } return cell } @IBAction func onMoreButtonClicked(_ sender: Any) { guard let user = self.currentUser else { return } let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) if user.isCurrent() { // Log out let actionLogout = UIAlertAction(title: "logout".localized, style: .destructive) { (action) in self.logOut() } actionSheet.addAction(actionLogout) } else { // Send Direct Message let actionMessage = UIAlertAction(title: "message.send".localized, style: .default) { (action) in self.sendMessage() } actionSheet.addAction(actionMessage) // Report the user let actionReport = UIAlertAction(title: "user.report".localized, style: .destructive) { (action) in self.reportUser() } actionSheet.addAction(actionReport) // Block the user if UserModel.current?.hasBlocked(user: user) == true { let actionBlock = UIAlertAction(title: "user.unblock".localized, style: .destructive) { (action) in UserModel.current?.block(user: user, value: false) } actionSheet.addAction(actionBlock) } else { let actionBlock = UIAlertAction(title: "user.block".localized, style: .destructive) { (action) in self.blockUser() } actionSheet.addAction(actionBlock) } } // Cancel let actionCancel = UIAlertAction(title: "cancel".localized, style: .cancel, handler: nil) actionSheet.addAction(actionCancel) if let popoverController = actionSheet.popoverPresentationController { popoverController.barButtonItem = sender as? UIBarButtonItem } present(actionSheet, animated: true, completion: nil) } func logOut() { let alert = UIAlertController(title: "logout".localized, message: "logout.message".localized, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "cancel".localized, style: .cancel, handler: nil)) alert.addAction(UIAlertAction(title: "logout".localized, style: .destructive, handler: { (action) in try? Auth.auth().signOut() })) present(alert, animated: true, completion: nil) } func sendMessage() { if self.currentUser?.isCurrent() ?? true { self.performSegue(withIdentifier: "messages.recents", sender: nil) } else { self.performSegue(withIdentifier: "messages.direct", sender: nil) } } func blockUser() { guard let user = self.currentUser else { return } let msg = "User \(user.name) cannot message you and comment your posts. Continue?" let alert = UIAlertController(title: "user.block".localized, message: msg, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "cancel".localized, style: .cancel, handler: nil)) alert.addAction(UIAlertAction(title: "user.block".localized, style: .destructive, handler: { (action) in // add user to block list UserModel.current?.block(user: user) // move back _ = self.navigationController?.popViewController(animated: true) })) present(alert, animated: true, completion: nil) } func reportUser() { // 1. stop listening for the notification from that user // - guard let key = self.currentUser?.ref.key else { return } let body = "Please block the user with id: \(key), as not appropriate." // 2. send email with report if MFMailComposeViewController.canSendMail() { let email = MFMailComposeViewController() email.setSubject("user.report".localized) email.setMessageBody(body, isHTML: false) email.mailComposeDelegate = self email.setToRecipients([kReportEmail]) self.present(email, animated: true, completion: nil) } else { let encodedBody = body.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? "" if let mailurl = URL(string: "mailto:\(kReportEmail)?subject=\(encodedBody)") { UIApplication.shared.open(mailurl, options: [:], completionHandler: nil) } } } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let feed = segue.destination as? StoryViewController { if let indexPath = self.collectionView?.indexPathsForSelectedItems?.first, let r = self.activities.object(at: (indexPath as NSIndexPath).row) as? DataSnapshot { feed.storyId = r.key } } else if let messages = segue.destination as? ChatViewController { // create new chat or use old one messages.contactRef = self.currentUser?.ref } else if let users = segue.destination as? UsersTableViewController { let gesture = sender as? UITapGestureRecognizer let tag = gesture?.view?.tag ?? 0 switch tag { case 1: users.title = "user.followers".localized users.query = currentUser?.followers.queryOrderedByKey() case 2: users.title = "user.followings".localized users.query = currentUser?.followings.queryOrderedByKey() default: break } } } } extension ProfileViewController: MFMailComposeViewControllerDelegate { func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) { controller.dismiss(animated: true, completion: nil) } }