From 945ae7f45c2a69adcd5223f422b6f708e870425f Mon Sep 17 00:00:00 2001 From: Bilal Date: Fri, 23 Aug 2024 20:34:08 +0530 Subject: [PATCH] - Fixed TC 16, TC 17 - added activity indicators for more vm with retry handling - fixed a issue where karaoke user view was not reflecting when the player closed --- WOKA.xcodeproj/project.pbxproj | 4 +- WOKA/Audio Books/AudioBookHomeVM.swift | 2 +- WOKA/Games/Controller/GamesDetailVC.swift | 2 +- WOKA/Games/Controller/GamesWebViewVC.swift | 8 ++ WOKA/Games/Games.storyboard | 8 +- WOKA/Home/Controller/MyListVC.swift | 2 +- WOKA/Info.plist | 2 - WOKA/Karaoke/Controller/AVAssetMods.swift | 62 ++++++++++++++++ WOKA/Karaoke/ViewModel/KaraokeListingVM.swift | 2 +- .../{WebSeries => Main}/JWPlayerManager.swift | 3 +- WOKA/Theme/Base.lproj/Theme.storyboard | 74 ++++++++++++++++++- WOKA/Theme/Controller/MoreVC.swift | 9 +++ WOKA/Theme/Controller/PlayerVC.swift | 26 +++---- WOKA/Theme/Controller/ThemeOneVC.swift | 14 ++-- WOKA/Theme/ViewModel/MoreVM.swift | 37 ++++++---- WOKA/Theme/ViewModel/ThemeOneVM.swift | 10 ++- WOKA/WebSeries/ViewModel/WebSeriesVM.swift | 2 +- 17 files changed, 218 insertions(+), 49 deletions(-) rename WOKA/{WebSeries => Main}/JWPlayerManager.swift (99%) diff --git a/WOKA.xcodeproj/project.pbxproj b/WOKA.xcodeproj/project.pbxproj index 89d7cf8..04b5e18 100644 --- a/WOKA.xcodeproj/project.pbxproj +++ b/WOKA.xcodeproj/project.pbxproj @@ -1586,7 +1586,6 @@ 52DAC64A2C2176CB00E2F85B /* ViewModel */, 52DAC6492C21767900E2F85B /* Controller */, 52DAC6472C21762900E2F85B /* WebSeries.storyboard */, - 52AC2D262C29791500337473 /* JWPlayerManager.swift */, 52C8D8D32C2D9F3400CA72A6 /* LikeFavCommonFunc.swift */, ); path = WebSeries; @@ -1688,6 +1687,7 @@ 9C27E1612BDB6F0F00EC1DA9 /* Main */ = { isa = PBXGroup; children = ( + 52AC2D262C29791500337473 /* JWPlayerManager.swift */, 52C1A4DF2C05B670007BAA50 /* Delegate */, 52FDBA792BFF26F9009D7AC7 /* AuthFunc */, ); @@ -2773,6 +2773,7 @@ INFOPLIST_FILE = WOKA/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = WOKA; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.entertainment"; + INFOPLIST_KEY_NSMicrophoneUsageDescription = "Give Permissions for Karaoke"; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen.storyboard; INFOPLIST_KEY_UIMainStoryboardFile = Main; @@ -2812,6 +2813,7 @@ INFOPLIST_FILE = WOKA/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = WOKA; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.entertainment"; + INFOPLIST_KEY_NSMicrophoneUsageDescription = "Give Permissions for Karaoke"; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen.storyboard; INFOPLIST_KEY_UIMainStoryboardFile = Main; diff --git a/WOKA/Audio Books/AudioBookHomeVM.swift b/WOKA/Audio Books/AudioBookHomeVM.swift index 724b17a..0a7c17e 100644 --- a/WOKA/Audio Books/AudioBookHomeVM.swift +++ b/WOKA/Audio Books/AudioBookHomeVM.swift @@ -96,7 +96,7 @@ class AudioBookHomeVM{ }else{ self.vc.continueWatchingStack.isHidden = false } - self.continueWatchingData = data.reversed() + self.continueWatchingData = data self.vc.continueWatchingCV.reloadData() default: break diff --git a/WOKA/Games/Controller/GamesDetailVC.swift b/WOKA/Games/Controller/GamesDetailVC.swift index dbda41e..d3f8144 100644 --- a/WOKA/Games/Controller/GamesDetailVC.swift +++ b/WOKA/Games/Controller/GamesDetailVC.swift @@ -231,7 +231,7 @@ class GamesDetailVC: UIViewController { vcPush.postID = gameData?.id vcPush.orientation = self.gameData?.screenOrientation vcPush.modalTransitionStyle = .crossDissolve - vcPush.modalPresentationStyle = .fullScreen + vcPush.modalPresentationStyle = .overFullScreen self.present(vcPush, animated: true) } diff --git a/WOKA/Games/Controller/GamesWebViewVC.swift b/WOKA/Games/Controller/GamesWebViewVC.swift index 5773383..538634d 100644 --- a/WOKA/Games/Controller/GamesWebViewVC.swift +++ b/WOKA/Games/Controller/GamesWebViewVC.swift @@ -24,6 +24,10 @@ class GamesWebViewVC: UIViewController, WKNavigationDelegate,UIGestureRecognizer typealias btnTappedBlock = () -> Void var btnTapped : btnTappedBlock? + override var prefersStatusBarHidden: Bool { + return true + } + deinit{ NotificationCenter.default.removeObserver(self,name: UIApplication.didEnterBackgroundNotification, object: nil) NotificationCenter.default.removeObserver(self,name: UIApplication.willEnterForegroundNotification, object: nil) @@ -63,6 +67,10 @@ class GamesWebViewVC: UIViewController, WKNavigationDelegate,UIGestureRecognizer NotificationCenter.default.addObserver(self,selector: #selector(appWillEnterForeground),name: UIApplication.willEnterForegroundNotification,object: nil) } + override func viewDidAppear(_ animated: Bool) { + setNeedsStatusBarAppearanceUpdate() + } + func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true } diff --git a/WOKA/Games/Games.storyboard b/WOKA/Games/Games.storyboard index f50edab..c5a96e1 100644 --- a/WOKA/Games/Games.storyboard +++ b/WOKA/Games/Games.storyboard @@ -537,17 +537,17 @@ - + - + - + @@ -576,7 +576,7 @@ - + diff --git a/WOKA/Home/Controller/MyListVC.swift b/WOKA/Home/Controller/MyListVC.swift index 023c034..6ec69fc 100644 --- a/WOKA/Home/Controller/MyListVC.swift +++ b/WOKA/Home/Controller/MyListVC.swift @@ -588,7 +588,7 @@ extension MyListVC : CollectionViewSRC{ } let sb = UIStoryboard(name: K.StoryBoard.Karaoke, bundle: nil) let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Karaoke.karaokeDetailsVC) as! KaraokeDetailsVC - vcPush.modalPresentationStyle = .overCurrentContext + vcPush.modalPresentationStyle = .fullScreen vcPush.modalTransitionStyle = .crossDissolve vcPush.karaokeData = karaokeData vcPush.karaokeIndex = indexPath.row diff --git a/WOKA/Info.plist b/WOKA/Info.plist index 51ab366..290a04a 100644 --- a/WOKA/Info.plist +++ b/WOKA/Info.plist @@ -43,7 +43,5 @@ audio remote-notification - NSMicrophoneUsageDescription - Give Permissions for Karaoke diff --git a/WOKA/Karaoke/Controller/AVAssetMods.swift b/WOKA/Karaoke/Controller/AVAssetMods.swift index 08e695a..bf6c513 100644 --- a/WOKA/Karaoke/Controller/AVAssetMods.swift +++ b/WOKA/Karaoke/Controller/AVAssetMods.swift @@ -10,6 +10,68 @@ import AVKit extension AVAsset { +// func writeAudioTrackToURL(_ url: URL, completion: @escaping (Bool, Error?, URL?) -> ()) { +// DispatchQueue.global(qos: .userInitiated).async { [weak self] in +// do { +// guard let audioAsset = try self?.audioAsset() else { +// completion(false, nil, nil) +// return +// } +// audioAsset.writeToURL(url, completion: completion) +// } catch let error as NSError { +// DispatchQueue.main.async { +// completion(false, error, nil) +// } +// } +// } +// } +// +// func writeToURL(_ url: URL, completion: @escaping (Bool, Error?, URL?) -> ()) { +// DispatchQueue.global(qos: .userInitiated).async { +// guard let exportSession = AVAssetExportSession(asset: self, presetName: AVAssetExportPresetAppleM4A) else { +// DispatchQueue.main.async { +// completion(false, nil, nil) +// } +// return +// } +// +// let audioMix = AVMutableAudioMix() +// var inputParameters = [AVMutableAudioMixInputParameters]() +// let volume: Float = 0.4 +// +// for track in self.tracks(withMediaType: .audio) { +// let audioInputParams = AVMutableAudioMixInputParameters(track: track) +// audioInputParams.setVolume(volume, at: .zero) +// inputParameters.append(audioInputParams) +// } +// +// audioMix.inputParameters = inputParameters +// exportSession.audioMix = audioMix +// exportSession.outputFileType = .m4a +// exportSession.outputURL = url +// +// DispatchQueue.main.async { +// Utilities.startProgressHUD(msg: "Preparing") +// } +// +// exportSession.exportAsynchronously { +// DispatchQueue.main.async { +// switch exportSession.status { +// case .completed: +// Utilities.dismissProgressHUD() +// completion(true, nil, url) +// case .unknown, .waiting, .exporting, .failed, .cancelled: +// Utilities.dismissProgressHUD() +// completion(false, nil, nil) +// @unknown default: +// Utilities.dismissProgressHUD() +// completion(false, nil, nil) +// } +// } +// } +// } +// } + func writeAudioTrackToURL(_ url: URL, completion: @escaping (Bool, Error?, URL?) -> ()) { do { let audioAsset = try self.audioAsset() diff --git a/WOKA/Karaoke/ViewModel/KaraokeListingVM.swift b/WOKA/Karaoke/ViewModel/KaraokeListingVM.swift index 1a6aeb6..9a6e172 100644 --- a/WOKA/Karaoke/ViewModel/KaraokeListingVM.swift +++ b/WOKA/Karaoke/ViewModel/KaraokeListingVM.swift @@ -91,7 +91,7 @@ class KaraokeListingVM{ }else{ self.vc.continueWatchingStack.isHidden = false } - self.continueWatchingData = data.reversed() + self.continueWatchingData = data self.vc.continueWatchingCV.reloadData() default: break diff --git a/WOKA/WebSeries/JWPlayerManager.swift b/WOKA/Main/JWPlayerManager.swift similarity index 99% rename from WOKA/WebSeries/JWPlayerManager.swift rename to WOKA/Main/JWPlayerManager.swift index c8ab48b..0e30241 100644 --- a/WOKA/WebSeries/JWPlayerManager.swift +++ b/WOKA/Main/JWPlayerManager.swift @@ -127,8 +127,7 @@ class JWPlayerManager { .autostart(false) .build() } - - + DispatchQueue.main.async { playerVC.videoIndex = startIndex playerVC.contentType = contentType diff --git a/WOKA/Theme/Base.lproj/Theme.storyboard b/WOKA/Theme/Base.lproj/Theme.storyboard index 7e7bad9..3eeda19 100644 --- a/WOKA/Theme/Base.lproj/Theme.storyboard +++ b/WOKA/Theme/Base.lproj/Theme.storyboard @@ -675,14 +675,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -690,8 +756,14 @@ + + + + + + @@ -1330,7 +1402,7 @@ - + diff --git a/WOKA/Theme/Controller/MoreVC.swift b/WOKA/Theme/Controller/MoreVC.swift index 174e57c..013f09a 100644 --- a/WOKA/Theme/Controller/MoreVC.swift +++ b/WOKA/Theme/Controller/MoreVC.swift @@ -14,6 +14,13 @@ class MoreVC: UIViewController { @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! var vm = MoreVM() var timeObserverToken: Any? @@ -43,6 +50,8 @@ class MoreVC: UIViewController { 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: - TableView DataSource , Delegates diff --git a/WOKA/Theme/Controller/PlayerVC.swift b/WOKA/Theme/Controller/PlayerVC.swift index 31e75fc..c0b7f14 100644 --- a/WOKA/Theme/Controller/PlayerVC.swift +++ b/WOKA/Theme/Controller/PlayerVC.swift @@ -9,7 +9,7 @@ import UIKit import JWPlayerKit import AVKit -class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate{ +class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate { @IBOutlet weak var backButton: UIButton! var previousScale: CGFloat = 1.0 @@ -52,8 +52,8 @@ class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate{ override func viewDidLoad() { super.viewDidLoad() - player.configurePlayer(with: config) self.delegate = self + player.configurePlayer(with: config) vm.vc = self vm.initView() //bring back button to the front @@ -158,6 +158,7 @@ class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate{ } if isDone{ Utilities.dismissProgressHUD() + K.GVar.reloadContinueAudioBooks = true vm.handleBackAction() }else{ Utilities.dismissProgressHUD() @@ -230,7 +231,7 @@ class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate{ vm.updateUserView() print("PlayList Over", vm.currentPlayingIndex) } - + override func jwplayer(_ player: any JWPlayer, didLoadPlaylist playlist: [JWPlayerItem]) { super.jwplayer(player, didLoadPlaylist: playlist) print("Playlist loaded") @@ -246,15 +247,14 @@ class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate{ if let videoIndex,vm.currentPlayingIndex == -1 && (index != videoIndex){ return } - } - - - if vm.currentPlayingIndex != -1 && vm.currentPlayingIndex != index{ - // so update the loaded index and increase the current playing index - vm.updateUserView() - vm.currentPlayingIndex = Int(index) - }else{ - vm.currentPlayingIndex = Int(index) + + if vm.currentPlayingIndex != -1 && vm.currentPlayingIndex != index{ + // so update the loaded index and increase the current playing index + vm.updateUserView() + vm.currentPlayingIndex = Int(index) + }else{ + vm.currentPlayingIndex = Int(index) + } } } @@ -295,7 +295,7 @@ class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate{ } print("IsReady") } - + override func jwplayer(_ player: JWPlayer, failedWithSetupError code: UInt, message: String) { super.jwplayer(player, failedWithSetupError: code, message: message) print("Setup Error: \(code) - \(message)") diff --git a/WOKA/Theme/Controller/ThemeOneVC.swift b/WOKA/Theme/Controller/ThemeOneVC.swift index b963aaf..2be7a40 100644 --- a/WOKA/Theme/Controller/ThemeOneVC.swift +++ b/WOKA/Theme/Controller/ThemeOneVC.swift @@ -189,14 +189,14 @@ extension ThemeOneVC{ // 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?) { + 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 2 Player is ready to play") + print("Theme 1 Player is ready to play") vm.avPlayer.play() } else if vm.playerItem.status == .failed { - print("Theme 2 Player failed to load") + print("Theme 1 Player failed to load") vm.setupAvPlayer() } } @@ -206,13 +206,13 @@ extension ThemeOneVC{ if let player = object as? AVPlayer { switch player.timeControlStatus { case .waitingToPlayAtSpecifiedRate: - print("Theme 2 Player Buffering...") + print("Theme 1 Player Buffering...") vm.startStopActivity(isStart: true) case .playing: - print("Theme 2 Player Playing") + print("Theme 1 Player Playing") vm.startStopActivity(isStart: false) case .paused: - print("Theme 2 Player Paused") + print("Theme 1 Player Paused") // check if app is in background return it if UIApplication.shared.applicationState == .background {return} @@ -229,7 +229,7 @@ extension ThemeOneVC{ } @unknown default: - print("Theme 2 Player Unknown status") + print("Theme 1 Player Unknown status") } } } diff --git a/WOKA/Theme/ViewModel/MoreVM.swift b/WOKA/Theme/ViewModel/MoreVM.swift index e793062..a432bfa 100644 --- a/WOKA/Theme/ViewModel/MoreVM.swift +++ b/WOKA/Theme/ViewModel/MoreVM.swift @@ -104,9 +104,10 @@ class MoreVM{ // MARK: - Get BLogs Data func getBLogs(){ - Utilities.startProgressHUD() + vc.blogActivityIndicator.startAnimating() NetworkManager.shareInstance.apiRequest(url: APIEndPoints.Home.blogs, method: .get) { [weak self](result : Result, NetworkManager.APIError>) in guard let self else{return} + Utilities.dismissProgressHUD() switch result{ case .success(let data): switch data.success{ @@ -114,26 +115,32 @@ class MoreVM{ /* Error */ - Utilities.dismissProgressHUD() - vc.toast(msg: data.message ?? "Unrecognised error" , time: 2) + vc.blogActivityIndicator.stopAnimating() + vc.blogRetryBtn.isHidden = false + vc.toast(msg: data.message ?? "Unrecognised error" , time: 1.5) case 1: - Utilities.dismissProgressHUD() + vc.blogActivityIndicator.stopAnimating() + vc.blogRetryBtn.isHidden = true guard let data = data.data?.blogs else{return} blogData = data vc.blogsCollectionView.reloadData() default: - break + vc.blogActivityIndicator.stopAnimating() + vc.blogRetryBtn.isHidden = false } case .failure(let error): - Utilities.dismissProgressHUD() - vc.toast(msg: error.localizedDescription , time: 2) + vc.blogActivityIndicator.stopAnimating() + vc.blogRetryBtn.isHidden = false + vc.toast(msg: error.localizedDescription , time: 1.5) } } } func getSong(){ + vc.songActivityIndicator.startAnimating() NetworkManager.shareInstance.apiRequest(url: APIEndPoints.Home.song_listing, method: .post) { [weak self](result : Result, NetworkManager.APIError>) in guard let self else{return} + Utilities.dismissProgressHUD() switch result{ case .success(let data): switch data.success{ @@ -141,20 +148,24 @@ class MoreVM{ /* Error */ - Utilities.dismissProgressHUD() - vc.toast(msg: data.message ?? "Unrecognised error" , time: 2) + vc.songActivityIndicator.stopAnimating() + vc.songRetry.isHidden = false + vc.toast(msg: data.message ?? "Unrecognised error" , time: 1.5) case 1: - Utilities.dismissProgressHUD() + vc.songActivityIndicator.stopAnimating() + vc.songRetry.isHidden = true guard let data = data.data?.paintData else{return} songData = data vc.songTableView.reloadData() break default: - break + vc.songActivityIndicator.stopAnimating() + vc.songRetry.isHidden = false } case .failure(let error): - Utilities.dismissProgressHUD() - vc.toast(msg: error.localizedDescription , time: 2) + vc.songActivityIndicator.stopAnimating() + vc.songRetry.isHidden = false + vc.toast(msg: error.localizedDescription , time: 1.5) } } } diff --git a/WOKA/Theme/ViewModel/ThemeOneVM.swift b/WOKA/Theme/ViewModel/ThemeOneVM.swift index 49b9764..91611dd 100644 --- a/WOKA/Theme/ViewModel/ThemeOneVM.swift +++ b/WOKA/Theme/ViewModel/ThemeOneVM.swift @@ -138,6 +138,7 @@ class ThemeOneVM{ if let rootViewController = UIApplication.shared.mainKeyWindow?.rootViewController { if let topVC = topVC(in: rootViewController) { if topVC is HomeVC{ + shouldAnimate = false avPlayer.pause() handleBackground() } else { @@ -155,7 +156,14 @@ class ThemeOneVM{ if let rootViewController = UIApplication.shared.mainKeyWindow?.rootViewController { if let topVC = topVC(in: rootViewController) { if topVC is HomeVC{ - avPlayer.play() + shouldAnimate = true + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in + guard let self else{return} + moveLiveTVView() + } + if let player = avPlayer{ + player.play() + } handleBackground() } else { print("The top view controller is not HomeVC") diff --git a/WOKA/WebSeries/ViewModel/WebSeriesVM.swift b/WOKA/WebSeries/ViewModel/WebSeriesVM.swift index 2ea4bb4..caf0778 100644 --- a/WOKA/WebSeries/ViewModel/WebSeriesVM.swift +++ b/WOKA/WebSeries/ViewModel/WebSeriesVM.swift @@ -146,7 +146,7 @@ class WebSeriesVM{ }else{ self.vc.continueWatchingStack.isHidden = false } - self.continueWatchingData = data.reversed() + self.continueWatchingData = data self.vc.continueWatchingCV.reloadData() default: break