// // ThemeOneVC.swift // WOKA // // Created by Bilal on 03/05/2024. // import UIKit import Alamofire import AVFoundation class ThemeOneVC: UIViewController { @IBOutlet weak var gradientView: UIView! @IBOutlet weak var cloud2: UIImageView! @IBOutlet weak var cloud1: UIImageView! @IBOutlet weak var liveTVView: UIView! @IBOutlet weak var liveTvPlayer: UIView! @IBOutlet weak var homeGrass: UIImageView! @IBOutlet weak var nameLabel: UILabel! @IBOutlet weak var welcomeLabel: LocalisedElementsLabel! @IBOutlet weak var HelloLabel: LocalisedElementsLabel! @IBOutlet weak var liveTVIcon: UIView! @IBOutlet weak var notificationBtnn: UIButton! @IBOutlet weak var avatarImage: UIImageView! @IBOutlet weak var webSeriesView: UIView! @IBOutlet weak var audioBooksView: UIView! @IBOutlet var star: [UIImageView]! @IBOutlet weak var moonImage: UIImageView! @IBOutlet weak var moreStack: UIStackView! @IBOutlet weak var bottomArrow: UIImageView! @IBOutlet weak var gamesView: UIView! @IBOutlet weak var karaokeView: UIView! @IBOutlet weak var shopView: UIView! @IBOutlet weak var allIconView: UIView! @IBOutlet weak var adBanner: UIImageView! @IBOutlet weak var liveTVActivityIndicator: UIActivityIndicatorView! var timer: Timer? var vm = ThemeOneVM() weak var delegate: ChildViewControllerDelegate? // MARK: - LifeCycle deinit{ timer?.invalidate() // Removing observers NotificationCenter.default.removeObserver(self, name: UIApplication.didEnterBackgroundNotification, object: nil) NotificationCenter.default.removeObserver(self, name: UIApplication.willEnterForegroundNotification, object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: K.NotificationCenterReloads.reloadTheme), object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: K.NotificationCenterReloads.themeOnePush), object: nil) NotificationCenter.default.removeObserver(self, name: .languageDidChange, object: nil) // NotificationCenter.default.removeObserver(self, name: NSNotification.Name.connectivityStatus, object: nil) if let playerItem = vm.playerItem{ playerItem.removeObserver(self, forKeyPath: "status") } if let avPlayer = vm.avPlayer { avPlayer.removeObserver(self, forKeyPath: "timeControlStatus") avPlayer.pause() } NotificationCenter.default.removeObserver(self, name: AVAudioSession.routeChangeNotification, object: nil) // NetworkMonitor.shared.stopMonitoring() } override var preferredStatusBarStyle: UIStatusBarStyle { .darkContent } override func viewDidLoad() { super.viewDidLoad() vm.vc = self vm.initView() if MyListDataTemp.shareInstance.favListingData?.showData == nil { MyListDataTemp.shareInstance.favListingData = FavouriteListingDM.ResultData(totalRecords: nil, showData: FavouriteListingDM.ResultData.ShowData(hindi: [],english: []),videoData: [],gameData: [],singKaraokeData: [],audioData: []) } vm.setupAvPlayer() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) setNeedsStatusBarAppearanceUpdate() } override func viewWillDisappear(_ animated: Bool) { vm.shouldAnimate = false if let player = vm.avPlayer{ player.pause() } } override func viewDidAppear(_ animated: Bool) { // AuthFunc.shareInstance.getAds() K.GVar.topView = .theme1 vm.shouldAnimate = true DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in guard let self else{return} vm.moveLiveTVView() vm.moveCloudView() } if let player = vm.avPlayer{ player.play() } /* Check if ads is there to map impressions */ if let adsData = AuthFunc.shareInstance.adsData{ // check if ads data contains ad for webseries if let themeOneAd = adsData.result?.filter({$0.slug == AdsEnum.themeOne.rawValue}).first, let adID = themeOneAd.advertisement?.id{ PersistentStorage.shared.addAdsCount(adID: adID ,impressions: 1) } } } override func viewDidLayoutSubviews() { if vm.playerLayer != nil{ vm.playerLayer.frame = self.liveTvPlayer.bounds } } // Define a function to customize tab bar item icon size func customizeTabBarItemIconSize() { // Get a reference to the tab bar controller if let tabBarController = self.tabBarController { // Loop through each tab bar item for item in tabBarController.tabBar.items! { // Adjust the image insets to increase the icon size item.imageInsets = UIEdgeInsets(top: 2, left: -5, bottom: -8, right: -5) item.titlePositionAdjustment.vertical = CGFloat(8) } } } @IBAction func barButtonTapped(_ sender: UIButton) { PersistentStorage.shared.addOthersCount() self.sideMenuController?.revealMenu() } @IBAction func notificationBtnTapped(_ sender: UIButton) { PersistentStorage.shared.addOthersCount() let sb = UIStoryboard(name: K.StoryBoard.theme, bundle: nil) let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Home.userNotificationVC) as! UserNotificationVC self.navigationController?.pushViewController(vcPush, animated: true) PersistentStorage.shared.sendDataToServer() PersistentStorage.shared.sendAdsData() } @IBAction func radioBtnTapped(_ sender: UIButton) { PersistentStorage.shared.addRadioCount() let sb = UIStoryboard(name: K.StoryBoard.wokaFM, bundle: nil) let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.WokaFM.wokaFMVC) as! WokaFMVC vcPush.modalPresentationStyle = .overCurrentContext vcPush.modalTransitionStyle = .crossDissolve self.present(vcPush, animated: true) } } // MARK: - Handle Live TV Observer extension ThemeOneVC{ func startMonitoringNetwork() { if vm.isNetworkMonitored{return} vm.isNetworkMonitored = true vm.monitor.pathUpdateHandler = { [weak self] path in guard let self else{return} if path.status == .satisfied { // when internet is back we have to setup player again vm.monitor.cancel() DispatchQueue.main.async { self.vm.avPlayer = nil self.vm.setupAvPlayer() } print("network connection is back") } else { print("No connection.") } print("Is on WiFi: \(path.usesInterfaceType(.wifi))") print("Is on Cellular: \(path.usesInterfaceType(.cellular))") } vm.monitor.start(queue: vm.queue) vm.isNetworkMonitored = true } func addObservers() { // Observe the player's status vm.playerItem.addObserver(self, forKeyPath: "status", options: [.new, .old], context: nil) // Observe the player's time control status vm.avPlayer.addObserver(self, forKeyPath: "timeControlStatus", options: [.new, .old], context: nil) // Observe buffering status // vm.playerItem.addObserver(self, forKeyPath: "isPlaybackBufferEmpty", options: [.new, .old], context: nil) // vm.playerItem.addObserver(self, forKeyPath: "isPlaybackLikelyToKeepUp", options: [.new, .old], context: nil) } override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?){ //this will oberver if player loads the url or fails if keyPath == "status" { if vm.playerItem.status == .readyToPlay { print("Theme 1 Player is ready to play") vm.avPlayer.play() } else if vm.playerItem.status == .failed { print("Theme 1 Player failed to load") /* Check if network is connected. */ if vm.reachability?.isReachable == true{ vm.setupAvPlayer() } } } //this will give status of buffering, play pause. if keyPath == "timeControlStatus" { if let player = object as? AVPlayer { switch player.timeControlStatus { case .waitingToPlayAtSpecifiedRate: vm.startStopActivity(isStart: true) print("Theme 1 Player Buffering...") switch vm.reachability?.isReachable{ case true: break case false: /* Start monitoring when the player buffers and there is not internet connection */ print("Monitoring Started") DispatchQueue.main.asyncAfter(deadline: .now() + 0.4){ [weak self] in guard let self else{return} self.startMonitoringNetwork() } default: break } case .playing: print("Theme 1 Player Playing") vm.startStopActivity(isStart: false) case .paused: print("Theme 1 Player Paused") // check if app is in background return it if UIApplication.shared.applicationState == .background {return} if let rootViewController = UIApplication.shared.mainKeyWindow?.rootViewController { if let topVC = topVC(in: rootViewController) { if topVC is HomeVC{ vm.avPlayer.play() } else { print("The top view controller is not HomeVC") } } else { print("No top view controller found") } } @unknown default: print("Theme 1 Player Unknown status") } } } // if keyPath == "status" { // if vm.playerItem.status == .readyToPlay { // print("Player is ready to play") // vm.avPlayer.play() // } else if vm.playerItem.status == .failed { // print("Player failed to load") // if !liveTVActivityIndicator.isAnimating{ // liveTVActivityIndicator.startAnimating() // } // } // } else if keyPath == "timeControlStatus" { // switch vm.avPlayer.timeControlStatus { // case .playing: // print("Player is playing") // liveTVActivityIndicator.stopAnimating() // case .paused: // print("Player is paused") // vm.avPlayer.play() // liveTVActivityIndicator.stopAnimating() // case .waitingToPlayAtSpecifiedRate: // print("Player is Buffering 1") // if !(NetworkReachabilityManager()?.isReachable ?? false){ // if !NetworkReachibility.shared.isMonitoring{ // startMonitoring() // } // } // @unknown default: // break // } // } else if keyPath == "isPlaybackBufferEmpty" { // if vm.playerItem.isPlaybackBufferEmpty { // print("Player is buffering 2") // liveTVActivityIndicator.startAnimating() // startMonitoring() // } // } else if keyPath == "isPlaybackLikelyToKeepUp" { // if vm.playerItem.isPlaybackLikelyToKeepUp { // print("Player is likely to keep up with the playback") // } // } } } class NavigationController: UINavigationController { open override var childForStatusBarHidden: UIViewController? { return self.topViewController } open override var childForStatusBarStyle: UIViewController? { return self.topViewController } } extension UINavigationController { func pushWithPopInAnimation(_ viewController: UIViewController, duration: CFTimeInterval = 0.3) { let transition = CATransition() transition.duration = duration transition.type = CATransitionType.push transition.subtype = CATransitionSubtype.fromRight // Customize the animation to look like a "pop-in" transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut) self.view.layer.add(transition, forKey: kCATransition) self.pushViewController(viewController, animated: false) } }