// // MPPositive_HomeViewController.swift // MusicPlayer // // Created by Mr.Zhou on 2024/4/19. // import UIKit class MPPositive_HomeViewController: MPPositive_BaseViewController, UIViewControllerTransitioningDelegate{ //背景图片 private lazy var bgImageView:UIImageView = { let imageView:UIImageView = .init(image: .init(named: "B_Home_BG'bg")) imageView.contentMode = .scaleAspectFill return imageView }() //菜单按钮 private lazy var memuBtn:UIButton = { let btn = UIButton() btn.setBackgroundImage(UIImage(named: "Home_Menu'logo"), for: .normal) btn.addTarget(self, action: #selector(menuRightClick(_ :)), for: .touchUpInside) return btn }() //tableView private lazy var tableView:UITableView = { let tableView = UITableView(frame: .init(x: 0, y: 0, width: screen_Width, height: screen_Height), style: .plain) tableView.backgroundColor = .clear tableView.separatorStyle = .none tableView.estimatedRowHeight = 200 tableView.rowHeight = UITableView.automaticDimension tableView.dataSource = self tableView.delegate = self tableView.register(MPPositive_HomeSinglesTableViewCell.self, forCellReuseIdentifier: MPPositive_HomeSinglesTableViewCellID) tableView.register(MPPositive_HomeShowTableViewCell.self, forCellReuseIdentifier: MPPositive_HomeShowTableViewCellID) tableView.contentInset = .init(top: 0, left: 0, bottom: 70*width, right: 0) return tableView }() private let MPPositive_HomeSinglesTableViewCellID = "MPPositive_HomeSinglesTableViewCell" private let MPPositive_HomeShowTableViewCellID = "MPPositive_HomeShowTableViewCell" private var isFirstAppearance:Bool = true // private var loadViewModel:MPPositive_BrowseLoadViewModel! override func viewDidLoad() { super.viewDidLoad() MP_AdMobManager.shared.loadAnyAdMobs() DispatchQueue.main.asyncAfter(deadline: .now() + 3) { // 请求跟踪授权 requestTrackingAuthorization { idfa in } } setTitle("") confirgue() NotificationCenter.notificationKey.add(observer: self, selector: #selector(reloadAction(_ :)), notificationName: .positive_browses_reload) if MPPositive_BrowseLoadViewModel.shared.browseModuleLists.count == 0 { MP_HUD.loading() } errorBlock = { [weak self] in guard let self = self else { return } guard MPPositive_BrowseLoadViewModel.shared.browseModuleLists.count == 0 else { return } //移除所有(除了navView)的子控件,并告知页面处理错误,提示用户重试 view.subviews.forEach { item in if item != self.navView { //移除 if item.superview != nil { item.removeFromSuperview() } } } //添加报错View setErrorView() MP_HUD.hideNow() } retryBlock = { [weak self] in guard let self = self else {return} MP_HUD.loading() DispatchQueue.main.async { //获取首页 MPPositive_BrowseLoadViewModel.shared.reloadBrowseLists() } } } deinit { NotificationCenter.default.removeObserver(self) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) if isFirstAppearance == false { // 第二次展示的逻辑,可触发相应的方法 presentGuide() isFirstAppearance = true } MP_AnalyticsManager.shared.home_b_pvAction() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) } //生成一个顶部搜索框 private func createSearchView() -> UIView{ let searchView:UIView = UIView() searchView.backgroundColor = .init(hex: "#212121") searchView.isUserInteractionEnabled = true searchView.layer.masksToBounds = true searchView.layer.cornerRadius = 16*width //添加一个icon let iconImageView = UIImageView(image: .init(named: "Search_ICON'logo")) searchView.addSubview(iconImageView) iconImageView.snp.makeConstraints { make in make.height.width.equalTo(16*width) make.left.equalToSuperview().offset(16*width) make.centerY.equalToSuperview() } let label = createLabel("Search songs,artists,playlists", font: .systemFont(ofSize: 14*width, weight: .regular), textColor: .init(hex: "#666666"), textAlignment: .left) searchView.addSubview(label) label.snp.makeConstraints { make in make.left.equalTo(iconImageView.snp.right).offset(8*width) make.centerY.equalToSuperview() } searchView.isUserInteractionEnabled = true searchView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(searchClick(_:)))) return searchView } //前往搜索结果页 @objc fileprivate func searchClick(_ sender:UITapGestureRecognizer) { isFirstAppearance = false let resultVC = MPPositive_SearchResultShowViewController() navigationController?.pushViewController(resultVC, animated: false) } ///弹出好评引导框 func presentGuide() { guard UserDefaults.standard.bool(forKey: "isGuide") != true else { //已经评论过了 print("已经评论过了") return } //检索活跃天数是否达到3天 guard var actives = UserDefaults.standard.object(forKey: "ActiveDays") as? [Date], actives.count >= 3 else { return } //达到3天,可以弹出好评引导框 MPPositive_ModalType = .Guide let guideVC = MP_GuideViewController() guideVC.disMissBlock = { DispatchQueue.main.async { //移除所有的日期值,填充一个新的日期值 actives.removeAll() let now = Date().timeZone() UserDefaults.standard.setValue([now], forKey: "ActiveDays") } } guideVC.feedBackBlock = { DispatchQueue.main.async { let alert = UIAlertController(title: "Feedback", message: "If you have any comments or suggestions, please contact us at the following e-mail address", preferredStyle: .actionSheet) let email = UIAlertAction(title: "marketing@lux-ad.com", style: .default) { (_) in //将邮箱复制到剪切板中 UIPasteboard.general.string = "marketing@lux-ad.com" MP_HUD.text("Successfully copied the e-mail address to the clipboard", delay: 1.0, completion: nil) } alert.addAction(email) let cancel = UIAlertAction(title: "Cancel", style: .cancel) alert.addAction(cancel) self.present(alert, animated: true) } } guideVC.storeBlock = { DispatchQueue.main.async { //跳转AppStore if let url = URL(string: "https://apps.apple.com/app/6502973957") { UIApplication.shared.open(url, options: [:], completionHandler: nil) } } } guideVC.transitioningDelegate = self guideVC.modalPresentationStyle = .custom self.present(guideVC, animated: true) } func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? { return MPPositive_PresentationController(presentedViewController: presented, presenting: presenting) } //MARK: - UI生成与配置 //配置 private func confirgue() { let searchView = createSearchView() navView.addSubview(searchView) searchView.snp.makeConstraints { make in make.width.equalTo(300*width) make.height.equalTo(32*width) make.left.equalToSuperview().offset(18*width) make.centerY.equalToSuperview() } view.addSubview(bgImageView) bgImageView.snp.makeConstraints { make in make.top.right.left.equalToSuperview() make.height.equalTo(981*width) } view.addSubview(tableView) navView.addSubview(memuBtn) memuBtn.snp.makeConstraints { make in make.right.equalToSuperview().offset(-16*width) make.centerY.equalToSuperview() make.width.height.equalTo(24*width) } tableView.snp.makeConstraints { make in make.top.equalTo(navView.snp.bottom).offset(32*width) make.left.right.bottom.equalToSuperview() } } //MARK: - 页面刷新 //页面刷新 @objc private func reloadAction(_ sender:Notification?) { DispatchQueue.main.async { [weak self] in guard let self = self else {return} if tableView.superview == nil { confirgue() } removeErrorView() MP_HUD.hideNow() tableView.showMessage(MPPositive_BrowseLoadViewModel.shared.browseModuleLists.count) tableView.reloadData() } } //MARK: - 点击 //点击顶部右侧弹出菜单 @objc private func menuRightClick(_ sender:UIButton) { isFirstAppearance = false let setVC = MPSideA_SettingViewController() navigationController?.pushViewController(setVC, animated: true) } } //MARK: - tableView extension MPPositive_HomeViewController: UITableViewDataSource, UITableViewDelegate { func numberOfSections(in tableView: UITableView) -> Int { return MPPositive_BrowseLoadViewModel.shared.browseModuleLists.count } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 1 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { if let first = MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.section].items.first, first.browseItem.itemType == .single, first.browseItem.pageType == "MUSIC_VIDEO_TYPE_ATV" { //是单曲 let cell = tableView.dequeueReusableCell(withIdentifier: MPPositive_HomeSinglesTableViewCellID, for: indexPath) as! MPPositive_HomeSinglesTableViewCell cell.browseViewModel = MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.section] return cell }else { let cell = tableView.dequeueReusableCell(withIdentifier: MPPositive_HomeShowTableViewCellID, for: indexPath) as! MPPositive_HomeShowTableViewCell cell.browseViewModel = MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.section] if let first = MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.section].items.first, first.browseItem.itemType == .single, first.browseItem.pageType == "MUSIC_VIDEO_TYPE_OMV" { cell.showType = .Fifth }else { //判断是列表还是艺术家 if MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.section].items.first?.browseItem.pageType == "MUSIC_PAGE_TYPE_ARTIST" { cell.showType = .Fourth }else { cell.showType = .Third } } cell.requestNextBlock = { [weak self] (item) in guard let self = self else {return} MP_AnalyticsManager.shared.home_b_module_clickAction(MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.section].title ?? "") switch item.browseItem.itemType { case .single: //单曲/视频跳转 MPPositive_Debouncer.shared.call { [weak self] in guard let self = self else {return} guard MP_NetWorkManager.shared.netWorkStatu == .reachable else { MP_HUD.text("Weak connection.", delay: 2.0, completion: nil) return } MP_AnalyticsManager.shared.song_clickAction("Home") //优先清除数据 MP_PlayerManager.shared.loadPlayer = nil //弹出播放器 NotificationCenter.notificationKey.post(notificationName: .pup_player_vc) MP_AnalyticsManager.shared.player_b_impAction() //触发next请求,优先获取列表全部单曲基础数据(不完善) MP_NetWorkManager.shared.requestNextList(item.browseItem.playListId ?? "", videoId: item.browseItem.videoId ?? ""){ [weak self] listSongs in guard let self = self else {return} //回掉的数据并不完善,生成一个playerloadViewModel let lodaViewModel = MPPositive_PlayerLoadViewModel(listSongs, currentVideoId: item.browseItem.videoId ?? "") lodaViewModel.improveData(item.browseItem.videoId ?? "") //更改播放器播放类型 MP_PlayerManager.shared.setPlayType(.normal) MP_PlayerManager.shared.loadPlayer = lodaViewModel MP_AnalyticsManager.shared.player_b_listAction() } } case .list: isFirstAppearance = false //列表专辑 let listVC = MPPositive_ListShowViewController(item.browseItem.browseId ?? "", params: item.browseItem.params ?? "", title: item.title ?? "", subtitle: item.subtitle ?? "") navigationController?.pushViewController(listVC, animated: true) case .artist: isFirstAppearance = false //前往艺术家页面 let artistVC = MPPositive_ArtistShowViewController(item.browseItem.artistId ?? "") navigationController?.pushViewController(artistVC, animated: true) default: break } } cell.findMoreBlock = { [weak self] in guard let self = self else {return} isFirstAppearance = false let moreVC = MPPositive_MoreContentViewController(MPPositive_BrowseLoadViewModel.shared.browseModuleLists[indexPath.section]) navigationController?.pushViewController(moreVC, animated: true) } return cell } } }