// // MoreVC.swift // WOKA // // Created by MacBook Pro on 10/06/24. // import UIKit import AVFoundation import GoogleMobileAds class MoreVC: UIViewController { @IBOutlet weak var blogsCollectionView: UICollectionView! @IBOutlet weak var homeBtn: UIView! @IBOutlet weak var songTableView: UITableView! @IBOutlet weak var blogRetryStack: UIStackView! @IBOutlet weak var blogActivityIndicator: UIActivityIndicatorView! @IBOutlet weak var blogRetryBtn: LocalisedElementsButton! @IBOutlet weak var songRetryStack: UIStackView! @IBOutlet weak var songActivityIndicator: UIActivityIndicatorView! @IBOutlet weak var songRetry: LocalisedElementsButton! @IBOutlet weak var trailerTask: UIStackView! @IBOutlet weak var trailerView: UIView! @IBOutlet weak var customAdImage: UIImageView! @IBOutlet weak var customAdHeight: NSLayoutConstraint! var vm = MoreVM() var timeObserverToken: Any? override func viewDidLoad() { super.viewDidLoad() vm.vc = self vm.initView() NotificationCenter.default.addObserver(self,selector: #selector(appDidEnterBackground),name: UIApplication.didEnterBackgroundNotification,object: nil) NotificationCenter.default.addObserver(self,selector: #selector(appWillEnterForeground),name: UIApplication.didBecomeActiveNotification,object: nil) } deinit{ NotificationCenter.default.post(name: .enableDisableSideBar, object: nil, userInfo: ["type": true]) NotificationCenter.default.removeObserver(self,name: UIApplication.didEnterBackgroundNotification, object: nil) NotificationCenter.default.removeObserver(self,name: UIApplication.didBecomeActiveNotification, object: nil) do { try AVAudioSession.sharedInstance().setActive(false) } catch { print("Failed to deactivate audio session: \(error.localizedDescription)") } vm.player?.pause() } override func viewWillAppear(_ animated: Bool) { NotificationCenter.default.post(name: .enableDisableSideBar, object: nil, userInfo: ["type": false]) } @IBAction func playTrailerBtnTapped(_ sender: LocalisedElementsButton) { PersistentStorage.shared.addTrailerCount() let item = JwPlayerItemCreate(url: APIEndPoints.StaticURLs.masilaUrl, poster: nil, titles: "Masila") JWPlayerManager.shared.presentPlayer(from: self, playerItems: [item], contentType: .trailer, videoIDs: [0]) } @IBAction func retryBtnTapped(_ sender: LocalisedElementsButton) { } // MARK: - App Lifecycle @objc func appDidEnterBackground() { if let currentIndexPlayingSong = vm.currentIndexPlayingSong{ let song = vm.songData[currentIndexPlayingSong] vm.setupNowPlayingInfo(songTitle: song.title ?? "WOKA Song") vm.setupRemoteCommandCenter() } } @objc func appWillEnterForeground(){ vm.stopMPNowPlayin() } } // MARK: - TableView DataSource , Delegates extension MoreVC : TableViewSRC{ func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return vm.songData.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "SongListCell", for: indexPath) as! SongListCell let songData = vm.songData[indexPath.row] // let isActive = (indexPath.row == vm.currentIndexPlayingSong) if let index = vm.currentIndexPlayingSong , index == indexPath.row{ cell.setData(data: songData,playerStatus: vm.playerStatus, active: true, currentTime: currentTimePlayer) }else{ cell.setData(data: songData,playerStatus: .stopped , active: false, currentTime: 0) } return cell } func getFormattedTime(from player: AVPlayer) -> String { let currentTime = player.currentTime() let seconds = CMTimeGetSeconds(currentTime) if !seconds.isFinite { return "00:00:00" } let hours = Int(seconds) / 3600 let minutes = (Int(seconds) % 3600) / 60 let secs = Int(seconds) % 60 return String(format: "%02d:%02d:%02d", hours, minutes, secs) } func handleTap(indexPath : IndexPath){ } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { guard let cell = tableView.cellForRow(at: indexPath) else { return } addAnimation(cell: cell) { [weak self] in guard let self else{return} vm.handleInlinePlay(indexPath: indexPath.row) } } func addAnimation(cell : UITableViewCell, completion : @escaping () -> Void){ UIView.animate(withDuration: 0.1,animations: { cell.transform = CGAffineTransform(scaleX: 0.95, y: 0.95) }, completion: { _ in UIView.animate(withDuration: 0.1) { cell.transform = CGAffineTransform.identity completion() } }) } func startPlaying(song: SongBlogDM.PaintDatum, at indexPath: IndexPath) { // Set up and start the player stopPlaying() if let urlString = song.contentMoreDetails?.first?.url , let url = URL(string: urlString){ vm.player = AVPlayer(url: url) vm.player?.play() vm.playerStatus = .play vm.currentIndexPlayingSong = indexPath.row addPeriodicTimeObserver() vm.observePlayer() } } func stopPlaying() { // Remove the periodic time observer removePeriodicTimeObserver() // Stop the player vm.player?.pause() // vm.player = nil vm.playerStatus = .stopped vm.currentIndexPlayingSong = nil } func removePeriodicTimeObserver() { if let token = timeObserverToken { vm.player?.removeTimeObserver(token) timeObserverToken = nil } } func addPeriodicTimeObserver() { let interval = CMTime(seconds: 1, preferredTimescale: CMTimeScale(NSEC_PER_SEC)) timeObserverToken = vm.player?.addPeriodicTimeObserver(forInterval: interval, queue: .main) { [weak self] time in guard let self = self else { return } currentTimePlayer = Int(CMTimeGetSeconds(time)) if let currentPlayingIndex = self.vm.currentIndexPlayingSong, let cell = self.songTableView.cellForRow(at: IndexPath(row: currentPlayingIndex, section: 0)) as? SongListCell { cell.updateCurrentTime() } } } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 60 } } // MARK: - CollectionView DataSource Delegate extension MoreVC : CollectionViewSRC{ func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return vm.blogData.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: K.CellIdentifier.Home.blogsCell, for: indexPath) as! BlogsCell cell.setData(data : vm.blogData[indexPath.row]) return cell } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { PersistentStorage.shared.addOthersCount() let data = vm.blogData[indexPath.row] let sb = UIStoryboard(name: K.StoryBoard.theme, bundle: nil) let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Theme.blogDetailsVC) as! BlogDetailsVC vcPush.blogData = data vcPush.modalPresentationStyle = .overCurrentContext vcPush.modalTransitionStyle = .crossDissolve self.present(vcPush, animated: true) } } // MARK: - Collection Flow Layout extension MoreVC : UICollectionViewDelegateFlowLayout{ func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { return 5 } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { return 5 } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { return UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let itemsPerRow: CGFloat = 2.2 let paddingSpace = 5 * (itemsPerRow + 1) let availableWidth = collectionView.frame.width - paddingSpace let widthPerItem = availableWidth / itemsPerRow return CGSize(width: widthPerItem, height: widthPerItem) } } // MARK: - Google Ad Banner Delegate extension MoreVC : GADBannerViewDelegate{ func bannerViewDidReceiveAd(_ bannerView: GADBannerView) { bannerView.alpha = 0 bannerView.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) UIView.animate(withDuration: 0.3, animations: { [weak self] in guard let self else{return} trailerView.alpha = 0 bannerView.alpha = 1 }) print("bannerViewDidReceiveAd") } func bannerView(_ bannerView: GADBannerView, didFailToReceiveAdWithError error: Error) { print("bannerView:didFailToReceiveAdWithError: \(error.localizedDescription)") } func bannerViewDidRecordImpression(_ bannerView: GADBannerView) { print("bannerViewDidRecordImpression") } func bannerViewWillPresentScreen(_ bannerView: GADBannerView) { print("bannerViewWillPresentScreen") } func bannerViewWillDismissScreen(_ bannerView: GADBannerView) { print("bannerViewWillDIsmissScreen") } func bannerViewDidDismissScreen(_ bannerView: GADBannerView) { print("bannerViewDidDismissScreen") } } //class VideoAVPlayer { // // var player: AVPlayer? // var playerObserver: NSKeyValueObservation? // var status = PlayerStatus.loading // // init(url: URL) { // self.player = AVPlayer(url: url) // observePlayer() // } // // private func observePlayer() { // playerObserver = player?.observe(\.timeControlStatus, options: [.new, .old], changeHandler: { [weak self] player, change in // guard let self = self else { return } // switch player.timeControlStatus { // case .playing: // print("Player is playing") // self.status = .play // case .paused: // print("Player is paused") // self.status = .pause // case .waitingToPlayAtSpecifiedRate: // print("Player is waiting to play at specified rate") // self.status = .loading // @unknown default: // print("Unknown player status") // } // }) // } // // deinit { // playerObserver?.invalidate() // } // // func play() { // player?.play() // } // // func pause() { // player?.pause() // } //}