Files
Woka_Native_iOS/WOKA/Theme/Controller/MoreVC.swift
BilalKhanWDI 5164f2fe10 - Handled inline play play pause.
- Created a enum to handle the play pause resume functionality
- Added tap handler with animation for cells.
- Made logic if one audio is playing and then other audio plays , it ill deinit the first audio and play second.
- Added deinit to the view controller, if the view dismiss the play will stop and denitialize
2024-06-11 19:49:10 +05:30

232 lines
7.8 KiB
Swift

//
// MoreVC.swift
// WOKA
//
// Created by MacBook Pro on 10/06/24.
//
import UIKit
import AVFoundation
class MoreVC: UIViewController {
@IBOutlet weak var blogsCollectionView: UICollectionView!
@IBOutlet weak var homeBtn: UIView!
@IBOutlet weak var songTableView: UITableView!
var vm = MoreVM()
override func viewDidLoad() {
super.viewDidLoad()
vm.vc = self
vm.initView()
}
override func viewWillDisappear(_ animated: Bool) {
vm.player.pause()
}
}
// 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: K.CellIdentifier.Home.songListCell) as! SongListCell
let data = vm.songData[indexPath.row]
cell.setData(data: data,playerStatus: vm.playerStatus)
// if let playingIndex = vm.currentIndexPlayingSong {
// if indexPath.row == playingIndex{
// if vm.onGoingTime != nil{ // if index is nil that means its just paused
// cell.setData(data: data,playerStatus: vm.playerStatus,onGoingTime: vm.onGoingTime)
// }else{ // if index is there it means song is playing and needs to be paused
// cell.setData(data: data,playerStatus: .resume,onGoingTime: vm.onGoingTime)
// }
// }else{
// cell.setData(data: data,playerStatus: vm.playerStatus,onGoingTime: nil)
// }
// }else{
// cell.setData(data: data,playerStatus: .stopped ,onGoingTime: nil)
// }
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}
/*
this will declare if the song is playing or not
*/
if let playingIndex = vm.currentIndexPlayingSong {
if indexPath.row == playingIndex{ // if same row is selected pause the row
print(vm.playerStatus)
switch vm.playerStatus{
case .play:
print("Player is playing")
vm.player.pause()
case .pause:
print("Player is pause")
case .loading:
print("Player is loading")
case .resume:
print("Player is resume")
default:
break
}
}else{
/*
this means other cell was playing now stop it and play this new cell
first reload the playing cell and pause the audio
*/
print("Other cell playing")
}
}else{
// if there is no playing audio before
vm.playerStatus = .play
vm.currentIndexPlayingSong = indexPath.row
tableView.reloadRows(at: [indexPath], with: .none)
let data = vm.songData[indexPath.row]
playSong(url: data.contentMoreDetails?.first?.url)
print("First Play")
}
}
}
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 playSong(url : String?){
if let url {
vm.player = AVPlayer(url: URL(string: url)!)
vm.observePlayer()
vm.player.play()
}
}
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) {
print(indexPath.row)
}
}
// 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
let paddingSpace = 5 * (itemsPerRow + 1)
let availableWidth = collectionView.frame.width - paddingSpace
let widthPerItem = availableWidth / itemsPerRow
return CGSize(width: widthPerItem, height: widthPerItem - 20)
}
}
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()
}
}