Files
Woka_Native_iOS/WOKA/WOKAFM/Controller/WokaFMVC.swift
BilalKhanWDI 7efcbb2d24 - Worked on my list and notification bottom Banner
- Tc - 69 fixed
- Tc - 70 fixed
- TC 71 fixed
- Added local ads to fm and more section
- Added local ads to mylist
- Fixed a bug for sync
* Fixed the crashing by temporary updating the wokastaging with raw data
2024-10-01 19:57:04 +05:30

288 lines
11 KiB
Swift

//
// WokaFMVC.swift
// WOKA
//
// Created by MacBook Pro on 01/08/24.
//
import UIKit
import AVFoundation
import Alamofire
import GoogleMobileAds
class WokaFMVC: UIViewController {
@IBOutlet weak var roundView: UIView!
@IBOutlet weak var mainView: UIView!
@IBOutlet weak var playBtn: UIButton!
@IBOutlet weak var volPlusBtn: UIButton!
@IBOutlet weak var volMinusBtnn: UIButton!
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
@IBOutlet weak var blackView: UIView!
@IBOutlet weak var imageAdView: UIImageView!
@IBOutlet weak var imageAdHeight: NSLayoutConstraint!
var vm = WokaFMVM()
deinit {
vm.playerItem.removeObserver(self, forKeyPath: "status")
vm.player.removeObserver(self, forKeyPath: "timeControlStatus")
vm.playerItem.removeObserver(self, forKeyPath: "isPlaybackBufferEmpty")
vm.playerItem.removeObserver(self, forKeyPath: "isPlaybackLikelyToKeepUp")
vm.player?.pause()
NotificationCenter.default.removeObserver(self,name: UIApplication.didEnterBackgroundNotification, object: nil)
NotificationCenter.default.removeObserver(self,name: UIApplication.didBecomeActiveNotification, object: nil)
// Deactivate the audio session if needed
do {
try AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
} catch {
print("Failed to deactivate audio session: \(error.localizedDescription)")
}
}
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)
}
// MARK: - App LifeCycle HAndler
@objc func appDidEnterBackground() {
vm.setupNowPlayingInfo()
vm.setupRemoteCommandCenter()
if let postID = AuthFunc.shareInstance.staticURLs?.liveFmData?.id {
let duration = DateFormatterLib.dateDifferenceINT(date1: vm.startTimeStamp, date2: Date())
AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.FM.rawValue, duration: duration, catID: 0) { [weak self] isDone in
guard let self else{return}
if isDone{
vm.startTimeStamp = Date()
}
}
}
}
@objc func appWillEnterForeground(){
vm.stopMPNowPlayin()
}
@IBAction func playBtnTapped(_ sender: UIButton) {
PersistentStorage.shared.addRadioCount()
if sender == playBtn{
if sender.image(for: .normal)?.pngData() == UIImage(named: "Reload")?.pngData(){
// when user reloads check for internet connection
if !(NetworkReachabilityManager()?.isReachable ?? false){
return
}
vm.retryCount = 0
vm.retryConnect()
} else if sender.image(for: .normal)?.pngData() == UIImage(named: "PlayButton")?.pngData(){
vm.player.play()
}else{
vm.player.pause()
}
}
}
@IBAction func volumeBtnTapped(_ sender: UIButton) {
PersistentStorage.shared.addRadioCount()
switch sender{
case volPlusBtn:
if vm.player.volume == 1 {
sender.isEnabled = false
return
}
volMinusBtnn.isEnabled = true
let newVolume = min(vm.player.volume + 0.2, 1.0)
vm.player.volume = newVolume
case volMinusBtnn:
if vm.player.volume == 0.0 {
sender.isEnabled = false
return
}
volPlusBtn.isEnabled = true
let newVolume = max(vm.player.volume - 0.2, 0.0)
vm.player.volume = newVolume
default:
break
}
}
@IBAction func closeBtnTapped(_ sender: UIButton) {
PersistentStorage.shared.addRadioCount()
if let postID = AuthFunc.shareInstance.staticURLs?.liveFmData?.id {
let duration = DateFormatterLib.dateDifferenceINT(date1: vm.startTimeStamp, date2: Date())
AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.FM.rawValue, duration: duration, catID: 0) { _ in}
}
self.dismiss(animated: true)
}
func startMonitoring(){
NetworkReachibility.shared.startMonitoring { [weak self] isConnected in
guard let self else{return}
switch isConnected{
case true: // if network is connected than stop
// when internet is back we have to setup player again
NetworkReachibility.shared.stopMonitoring()
vm.setupPlayer()
addObservers()
vm.setupAudioSession()
case false:
// if there is no internet connection prompt user and show reload icon
self.toast(msg: "Lost Connection.", time: 1.4)
activityIndicator.stopAnimating()
playBtn.setImage(UIImage(named: "Reload"), for: .normal)
playBtn.isEnabled = 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.player.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?) {
if keyPath == "status" {
if vm.playerItem.status == .readyToPlay {
print("FM is ready to play")
vm.player.play()
} else if vm.playerItem.status == .failed {
if vm.retryCount < 4{
vm.retryCount += 1
vm.retryConnect()
print("retry fm connect :-", vm.retryCount)
return
}
print("FM failed to load")
activityIndicator.stopAnimating()
playBtn.setImage(UIImage(named: "Reload"), for: .normal)
playBtn.isEnabled = true
}
} else if keyPath == "timeControlStatus" {
switch vm.player.timeControlStatus {
case .playing:
print("FM is playing")
activityIndicator.stopAnimating()
playBtn.isEnabled = true
playBtn.setImage(UIImage(named: "PauseButton"), for: .normal)
case .paused:
print("FM is paused")
playBtn.setImage(UIImage(named: "PlayButton"), for: .normal)
case .waitingToPlayAtSpecifiedRate:
activityIndicator.startAnimating()
playBtn.isEnabled = false
if !(NetworkReachabilityManager()?.isReachable ?? false){
startMonitoring()
}
print("FM is buffering 1 ")
@unknown default:
break
}
} else if keyPath == "isPlaybackBufferEmpty" {
if vm.playerItem.isPlaybackBufferEmpty {
print("FM is buffering 2")
playBtn.isEnabled = false
activityIndicator.startAnimating()
startMonitoring()
}
} else if keyPath == "isPlaybackLikelyToKeepUp" {
if vm.playerItem.isPlaybackLikelyToKeepUp {
print("FM is likely to keep up with the playback")
}
}
}
}
extension UIButton {
func applyGradientBtn(colors: [UIColor], startPoint: CGPoint, endPoint: CGPoint) {
// Remove existing gradient layer if any
self.layer.sublayers?.filter { $0 is CAGradientLayer }.forEach { $0.removeFromSuperlayer() }
// Create a new CAGradientLayer instance
let gradientLayer = CAGradientLayer()
// Set the frame of the gradient layer to match the bounds of the button
gradientLayer.frame = self.bounds
// Convert the array of UIColor objects to an array of CGColor objects
gradientLayer.colors = colors.map { $0.cgColor }
// Set the start and end points of the gradient
gradientLayer.startPoint = startPoint
gradientLayer.endPoint = endPoint
// Insert the gradient layer at the bottom of the button's layer hierarchy
self.layer.insertSublayer(gradientLayer, at: 0)
// Bring image and title layers to front
self.bringSubviewToFront(self.imageView!)
self.bringSubviewToFront(self.titleLabel!)
}
}
// MARK: - Google Ad Banner Delegate
extension WokaFMVC : GADBannerViewDelegate{
func bannerViewDidReceiveAd(_ bannerView: GADBannerView) {
print("bannerViewDidReceiveAd")
imageAdView.isHidden = false
bannerView.alpha = 0
UIView.animate(withDuration: 0.2, animations: {
bannerView.alpha = 1
})
}
func bannerView(_ bannerView: GADBannerView, didFailToReceiveAdWithError error: Error) {
UIView.animate(withDuration: 0.2, animations: { [weak self] in
guard let self else{return}
bannerView.alpha = 0
imageAdView.isHidden = true
})
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")
}
}
////Update system volume
//extension MPVolumeView {
// static func setVolume(_ volume: Float) {
// let volumeView = MPVolumeView()
// let slider = volumeView.subviews.first(where: { $0 is UISlider }) as? UISlider
//
// DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.01) {
// slider?.value = volume
// }
// }
//}