// // HomeViewController.swift // GMERemittance // // Created by gme_2 on 21/09/2018. //Copyright © 2018 Gobal Money Express Co. Ltd. All rights reserved. // import UIKit import Crashlytics import Localize_Swift import ChannelIO import LGSideMenuController #if DEBUG import FLEX #endif class HomeViewController: UIViewController { enum Sections: Int { case balance = 0 case collection } struct Constants { static let verificationNoticeHeight: CGFloat = 100 } struct StringConstants { let homeText = "home_text".localized() let registerProcessText = "complete_your_registration_text".localized() let registrationApprovalText = "verification_in_aproval_process_text".localized() let pennyTestPrimaryBankText = "complete_penny_test".localized() let verifyTitleText = "kyc_fill_text".localized() let continueRegistrationTitleText = "penny_test_pending_text".localized() let verificationInProcessTitleText = "kyc_verify_pending_text".localized() let soonToUseGmeServicesTitle = "verification_in_aproval_process_text".localized() } // MARK: IBOutlets @IBOutlet private weak var tableView: UITableView! @IBOutlet private weak var messageViewHeightConstraint: NSLayoutConstraint! @IBOutlet private weak var messageView: UIView! @IBOutlet private weak var messageLabel: UILabel! @IBOutlet private weak var messageTitleLabel: UILabel! @IBOutlet private weak var messageLeftImageview: UIImageView! @IBOutlet private var tapMessageViewGestrueRecognizer: UITapGestureRecognizer! @IBOutlet private weak var seperatorView: UIView! @IBOutlet private weak var supportBarButton: UIBarButtonItem! // MARK: Properties lazy var blobView = UIView() private var isUserVerified: Bool { return Utility.isVerifiedUser() } private var didSubmitKycAndNotVerified: Bool { return Utility.didSubmitKyc() && !Utility.isVerifiedUser() } private var didSubmitKycAndVerified: Bool { return Utility.didSubmitKyc() && Utility.isVerifiedUser() } private var didNotSubmitKycAndNotVerified: Bool { return !Utility.didSubmitKyc() && !Utility.isVerifiedUser() } private var shouldShowPennyTestError: Bool { return Utility.shouldShowPennyTestError() } private var shouldShowUnverifiedNotice: Bool { return !self.isUserVerified } var refreshControl: UIRefreshControl? var presenter: HomeModuleInterface? var user: User? { didSet { // update self.save(user: user) setMessageView() self.tableView.reloadData() updateBalance() self.update() checkKFTCToken() } } var sections: [Sections] = [.balance, .collection] var menuHeight: CGFloat? { didSet { self.tableView.reloadData() } } // MARK: VC's Life cycle var hotLines: [HotLine]? { didSet { guard let nativeCountry = GMEDB.shared.user.string(.countryCode)?.lowercased() else { return } userHotLine = hotLines?.filter { $0.countryCode == nativeCountry }.first } } var userHotLine: HotLine? var isShowTokenRenewAlert = false override func viewDidLoad() { super.viewDidLoad() self.setup() let supportImage = UIImage(named: "ic_support")?.withRenderingMode(.alwaysOriginal) supportBarButton.image = supportImage let sideMenuVC = (MainWireframe.shared?.window?.rootViewController as? LGSideMenuController)? .leftViewController as? SideMenuViewController sideMenuVC?.sideMenuDelegate = self } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.tableView.reloadData() NotificationCenter.default.addObserver( self, selector: #selector(updateTabBarTitle), name: NSNotification.Name(LCLLanguageChangeNotification), object: nil ) setNavBar(isUseMenu: false) presenter?.viewIsReady() presenter?.fetchHotLines() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) self.navigationItem.title = "" blobView.removeFromSuperview() MainWireframe.shared?.isUseSwipeGesture = false navigationController?.interactivePopGestureRecognizer?.isEnabled = true } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) navigationController?.interactivePopGestureRecognizer?.isEnabled = false // if kyc is false then, if self.didNotSubmitKycAndNotVerified { self.presenter?.showKyc() } else if shouldShowPennyTestError { // if pennyTestStatus is not completed(2) then, if Utility.didPennyTestRequested() { // if pennyTestStatus is request(1) then presenter?.showPennyTestSubmit() } else { // if pennyTestStatus is no request(0) then presenter?.showPennyTest() } } else { if KeyChain.shared.get(key: .biometricAuth) == nil { BiometricNotificationWireframe().openMainView(source: self) } } } // MARK: IBActions // MARK: Other Functions private func setup() { // all setup should be done here self.messageViewHeightConstraint.constant = 0 self.messageView.alpha = 0 setupDelegates() setupNotifications() addRefreshControlTableView() addRightCSButton(delegate: self) } private func update() { let platform = self.user?.platforms ?? [] guard let ios = platform.filter({ $0.os ?? "" == "IOS"}).first else {return} let critical = ios.critical ?? "N" GMEDB.shared.app.set(critical, .criticalUpdate) if critical == "Y" { guard let serverVersion = ios.version, let appVersion = Utility.getAppVersion(), let appVersionInfo = Double( appVersion .components(separatedBy: ".") .compactMap { Int($0) } .reduce("0.") {"\($0)\($1)"} ), let serverVersionInfo = Double(serverVersion .components(separatedBy: ".") .compactMap { Int($0) } .reduce("0.") {"\($0)\($1)"} ) else { return } if appVersionInfo < serverVersionInfo { self.presenter?.showAppUpdate() } } } private func updateBalance() { let balance = user?.availableBalance ?? "" GMEDB.shared.user.set(balance, .availableBalance) let userInfo = [SideMenuNavigationNotifications.availableBalance : balance] NotificationCenter.default.post( name: self.getAvailableBalanceNotificationName(), object: nil, userInfo: userInfo ) self.tableView.reloadData() } private func setupDelegates() { tableView.delegate = self tableView.dataSource = self } private func addRefreshControlTableView() { let colorOption = [NSAttributedString.Key.foregroundColor : UIColor.themeWhite] let title = NSAttributedString(string: "pull to refresh", attributes: colorOption) let refreshControl = UIRefreshControl() refreshControl.attributedTitle = title refreshControl.backgroundColor = .themeBlue refreshControl.tintColor = .themeWhite refreshControl.addTarget(self, action: #selector(self.refresh), for: .valueChanged) self.refreshControl = refreshControl if #available(iOS 10.0, *) { tableView.refreshControl = self.refreshControl } else { if let control = self.refreshControl { tableView.addSubview(control) } } } @objc private func refresh() { presenter?.refreshData() } func startCall(contactNumber: String) { if let url = URL(string: "tel://\(contactNumber.removeWhitespacesInBetween())"), UIApplication.shared.canOpenURL(url) { UIApplication.shared.open(url) } } private func setupNotifications() { let center = NotificationCenter.default center.addObserver( self, selector: #selector(self.setupHeight(sender:)), name: self.getCollectionHeightNotificationName(), object: nil ) center.addObserver( self, selector: #selector(self.showUnVerifiedMessage), name: self.getMainControllerNotificationName(), object: nil ) } @objc private func setupHeight(sender: Notification) { if let height = sender.userInfo?[MenuNotificationName.collectionHeight] as? CGFloat { self.menuHeight = height } } } // MARK: - Manage Message View extension HomeViewController { private func setMessageView() { switch GMEDB.shared.user.string(.redirectTo) ?? "" { case "autodebit": setNavBar(isUseMenu: false) showAutoDebitMessage() default: setNavBar(isUseMenu: true) didSubmitKycAndNotVerified ? showWaitVerifyMessage() : removeAllMessage() } } private func showAutoDebitMessage() { showMessageView(isHidden: false) messageTitleLabel.text = "add_auto_debit_account_text".localized() messageLabel.text = "autodebit_account_required_message".localized() messageLeftImageview.image = #imageLiteral(resourceName: "ic_home_verified") let offset = messageView.frame(forAlignmentRect: self.view.frame).origin.y blobView = UIView( frame: CGRect(x: 0, y: offset + 100, width: view.frame.width, height: view.frame.height) ) blobView.backgroundColor = .init(white: 0, alpha: 0.5) tabBarController?.view.addSubview(blobView) tapMessageViewGestrueRecognizer.addTarget(self, action: #selector(tapMessageView(_:))) } @objc private func tapMessageView(_ sender: UITapGestureRecognizer) { let navigationVC = UINavigationController(rootViewController: AutoDebitWireframe().getMainView()) tabBarController?.present(navigationVC, animated: true, completion: nil) } private func showWaitVerifyMessage() { blobView.removeFromSuperview() tapMessageViewGestrueRecognizer.removeTarget(self, action: #selector(tapMessageView(_:))) showMessageView(isHidden: false) messageTitleLabel.text = StringConstants().verificationInProcessTitleText messageLabel.text = StringConstants().soonToUseGmeServicesTitle messageLeftImageview.image = #imageLiteral(resourceName: "ic_home_verified") } private func removeAllMessage() { blobView.removeFromSuperview() showMessageView(isHidden: true) } private func showMessageView(isHidden: Bool) { UIView.animate( withDuration: 0.33, animations: { self.messageViewHeightConstraint.constant = isHidden ? 0 : 100 self.messageView.alpha = isHidden ? 0 : 1 } ) } func setNavBar(isUseMenu: Bool) { let selector = #selector(self.showSideMenu) isUseMenu ? setupPicturedNavBar(sideMenuAction: selector) : setupPicturedNavBar(sideMenuAction: nil) MainWireframe.shared?.isUseSwipeGesture = isUseMenu } } // MARK: - Other functions extension HomeViewController { @objc func showSideMenu() { sideMenuController?.showLeftViewAnimated() } private func showSendMoney() { let kycSubmited = user?.kyc ?? false let pennyTestComplete = Utility.pennyTestVerified() if kycSubmited == true && pennyTestComplete == false { self.show(error: StringConstants().pennyTestPrimaryBankText) return } if isUserVerified { let recipientsVC = RecipientsWireframe().getMainView() self.navigationController?.pushViewController(recipientsVC, animated: true) } else { self.showUnVerifiedMessage() } } private func showDomesticRemit() { let kycSubmited = user?.kyc ?? false let pennyTestComplete = Utility.pennyTestVerified() if kycSubmited == true && pennyTestComplete == false { self.show(error: StringConstants().pennyTestPrimaryBankText) return } if isUserVerified { DomesticRemitWireframe().open(on: self) } else { self.showUnVerifiedMessage() } } private func showResendMoney() { } private func showMobileRecharge() { let kycSubmited = user?.kyc ?? false let pennyTestComplete = Utility.pennyTestVerified() if kycSubmited == true && pennyTestComplete == false { self.show(error: StringConstants().pennyTestPrimaryBankText) return } self.alert(type: .error, message: "This feature is coming soon") } private func showTodaysRate() { presenter?.openTodaysRate() } private func showTrackYourTransfer() { let kycSubmited = user?.kyc ?? false let pennyTestComplete = Utility.pennyTestVerified() if kycSubmited == true && pennyTestComplete == false { self.show(error: StringConstants().pennyTestPrimaryBankText) return } isUserVerified ? (presenter?.openTrackYourTransfer()) : (self.showUnVerifiedMessage()) } private func showTransactionStatement() { let kycSubmited = user?.kyc ?? false let pennyTestComplete = Utility.pennyTestVerified() if kycSubmited == true && pennyTestComplete == false { self.show(error: StringConstants().pennyTestPrimaryBankText) return } isUserVerified ? (presenter?.openTransactionHistory()) : (self.showUnVerifiedMessage()) } @objc private func showUnVerifiedMessage() { if didNotSubmitKycAndNotVerified { self.alert(type: .error, message: StringConstants().registerProcessText) } else if Utility.didSubmitKyc() && !Utility.pennyTestVerified() { self.alert(type: .error, message: StringConstants().pennyTestPrimaryBankText) } else if didSubmitKycAndNotVerified { self.alert(type: .error, message: "verification_in_aproval_process_text".localized()) } } @objc private func showUnVerifiedPennyTestMessage() { self.alert(type: .normal, message: "complete_penny_test".localized()) } @objc private func showWalletToWallet() { self.alert(type: .error, message: "This feature is coming soon") } private func showSideMenuAboutGme() { guard let viewController = UIStoryboard(name: "SideMenu", bundle: nil) .instantiateViewController(withIdentifier: "AboutGMEViewController") as? AboutGMEViewController else { return } self.navigationController?.pushViewController(viewController, animated: true) } private func showSideMenuSetting() { guard let viewController = UIStoryboard(name: "Setting", bundle: nil) .instantiateViewController(withIdentifier: "SettingViewController") as? SettingViewController else { return } self.navigationController?.pushViewController(viewController, animated: true) } private func showAutoDebit() { let wireframe = AutoDebitWireframe() if let navigation = self.navigationController { wireframe.pushMainView(in: navigation) } } private func showWithdraw() { guard let viewController = UIStoryboard(name: "autoRefund", bundle: nil).instantiateViewController( withIdentifier: "AutoRefundsViewController" ) as? AutoRefundsViewController else { return } self.navigationController?.pushViewController(viewController, animated: true) } } // MARK: HomeViewInterface extension HomeViewController: HomeViewInterface { func setHotLine(with model: [HotLine]?) { hotLines = model } func show(model: User) { self.user = model } func show(error: String) { self.alert(type: .error, message: error) } func show(panicError: String) { self.alert(type: .error, message: panicError, title: "Warning") { self.presenter?.logout() } } func showLoading() { self.showProgressHud() } func hideLoading() { self.hideProgressHud() if self.tableView.refreshControl?.isRefreshing ?? false { self.tableView.refreshControl?.endRefreshing() } } } // MARK: - UITableViewDelegate extension HomeViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { guard let section = Sections.init(rawValue: indexPath.section) else { return 0 } switch section { case .balance: return UITableView.automaticDimension case .collection: let totalHeight = view.frame.height let ramainingBalanceCellHeight: CGFloat = 100 let finalHeight = totalHeight - ramainingBalanceCellHeight return finalHeight } } } // MARK: - UITableViewDataSource extension HomeViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 1 } func numberOfSections(in tableView: UITableView) -> Int { return self.sections.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let section = Sections.init(rawValue: indexPath.section) else {return UITableViewCell()} switch section { case .balance: return configureRemainingLimitCell(tableView: tableView, indexPath: indexPath) case .collection: return configureCollectionCell(tableView: tableView, indexPath: indexPath) } } func configureRemainingLimitCell(tableView: UITableView, indexPath: IndexPath) -> UITableViewCell { guard let cell = tableView.dequeueReusableCell( withIdentifier: "HomeRemainingLimitTableViewCell" ) as? HomeRemainingLimitTableViewCell else { return UITableViewCell() } cell.user = self.user cell.setup() return cell } func configureCollectionCell(tableView: UITableView, indexPath: IndexPath) -> UITableViewCell { guard let cell = tableView.dequeueReusableCell( withIdentifier: "HomeCollectionTableViewCell" ) as? HomeCollectionTableViewCell else { return UITableViewCell() } cell.setup() cell.homeCollectionDelegate = self return cell } override func setupTabItem() { let image = UIImage.init(named: "ic-home") self.tabBarItem = UITabBarItem(title: "home_text".localized(), image: image, selectedImage: nil) self.tabBarItem.titlePositionAdjustment = UIOffset( horizontal: 0, vertical: UI_USER_INTERFACE_IDIOM() == .pad ? 2 : -6 ) } @objc func updateTabBarTitle() { self.tabBarItem.title = "home_text".localized() } } // MARK: - Notification Name extension HomeViewController { func getCollectionHeightNotificationName() -> Notification.Name { return Notification.Name.init(rawValue: MenuNotificationName.collectionHeight) } func getAvailableBalanceNotificationName() -> Notification.Name { return Notification.Name.init(rawValue: SideMenuNavigationNotifications.availableBalance) } func getMainControllerNotificationName() -> Notification.Name { return Notification.Name.init(rawValue: AppConstants.MainWireFrameNotificationName) } } // MARK: - UIGestureRecognizerDelegate extension HomeViewController: UIGestureRecognizerDelegate { func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { return !Utility.didSubmitKyc() || Utility.shouldShowPennyTestError() || Utility.didPennyTestCancelled() || Utility.didPennyTestRequested() || Utility.didPennyTestNotInitiated() } } // MARK: - Check KFTC Token, PopUpNotification extension HomeViewController { func save(user: User?) { Utility.save(user: user) } private func checkKFTCToken() { if !GMEDB.shared.app.bool(.isOpenedTokenRenwalAlert) { guard let remind = GMEDB.shared.user.string(.remindKFTCTokenDay), let remindDay = Int(remind) else { popUpNotification() return } if remindDay <= 30 { let expiredMessage = "kftc_token_expired_message_text".localized() let defaultMessage = remindDay != 0 ? "kftc_token_remind_message_text".localized().replacingOccurrences( of: "xx", with: "\(remindDay)" ) : "kftc_token_remind_message_text".localized().replacingOccurrences(of: "xx ", with: "To") alertWithOkCancel( message: remindDay >= 0 ? defaultMessage : expiredMessage, title: "kftc_token_title_message_text".localized(), okTitle: "renewal_text".localized(), cancelTitle: "later_text".localized(), okAction: { AutoDebitWireframe().pushMainView(on: self) GMEDB.shared.app.set(true, .isOpenedTokenRenwalAlert) }, cancelAction : { self.popUpNotification() GMEDB.shared.app.set(true, .isOpenedTokenRenwalAlert) } ) } else { popUpNotification() } } } private func popUpNotification() { // FIXME: Temporary expire date let dateformat = DateFormatter() dateformat.dateFormat = "yyyy-MM-dd" let expireDate = dateformat.date(from: "2019-08-01") GMEDB.shared.app.set(expireDate, .dateOfExpireNotification) PopupNotificationWireframe().show(source: self) } } // MARK: - ChannelPluginDelegate extension HomeViewController: ChannelPluginDelegate { func onChangeBadge(count: Int) { setMessageCount(with: count) } func onReceivePush(event: PushEvent) { //configure your view with push event data //and display print("event: \(event)") } } // MARK: - HomeCollectionDelegate extension HomeViewController: HomeCollectionDelegate { func didSelect( _ collectionView: UICollectionView, didSelectMenu: HomeCollectionTableViewCell.CollectionMenus ) { switch didSelectMenu { case .sendMoney: showSendMoney() case .mobileRecharge: showMobileRecharge() case .todaysRate: presenter?.openTodaysRate() case .walletStatement: showTrackYourTransfer() case .resend: showResendMoney() case .walletToWallet: showWalletToWallet() case .demosticRemit: showDomesticRemit() case .phoneRecharge: () case .cardRecharge: () } } } // MARK: - SideMenuDelegate extension HomeViewController: SideMenuDelegate { func didSelectMenu(_ viewController: UIViewController, didSelectMenu: SideMenuViewController.MenuType) { switch didSelectMenu { case .withDraw: showWithdraw() case .autoDebit: showAutoDebit() case .transferHistory: showTransactionStatement() case .about: showSideMenuAboutGme() case .setting: showSideMenuSetting() } } }