From 16d9a91863012b19bbe0e1c9ac2385232a71dc31 Mon Sep 17 00:00:00 2001 From: BilalKhanWDI Date: Tue, 2 Jul 2024 19:51:14 +0530 Subject: [PATCH] - Started ui fr audio books - Completed audio listing with api and model --- WOKA.xcodeproj/project.pbxproj | 56 +++ WOKA/Audio Books/AudioBookHomeVC.swift | 329 ++++++++++++++++++ WOKA/Audio Books/AudioBookHomeVM.swift | 160 +++++++++ WOKA/Audio Books/AudioBooks.storyboard | 194 +++++++++++ WOKA/Audio Books/ListenAudioListingDM.swift | 95 +++++ WOKA/Constants K/StoryBoard.swift | 1 + WOKA/Constants K/StoryBoardID.swift | 7 + WOKA/Network Adapter/APIEndPoints.swift | 4 + WOKA/Theme/Base.lproj/Theme.storyboard | 67 ++-- WOKA/Theme/Controller/ThemeOneVC.swift | 1 + WOKA/Theme/ViewModel/ThemeOneVM.swift | 9 + .../View/WebSeriesShowListingCell.swift | 31 ++ 12 files changed, 926 insertions(+), 28 deletions(-) create mode 100644 WOKA/Audio Books/AudioBookHomeVC.swift create mode 100644 WOKA/Audio Books/AudioBookHomeVM.swift create mode 100644 WOKA/Audio Books/AudioBooks.storyboard create mode 100644 WOKA/Audio Books/ListenAudioListingDM.swift diff --git a/WOKA.xcodeproj/project.pbxproj b/WOKA.xcodeproj/project.pbxproj index a842bda..96cf345 100644 --- a/WOKA.xcodeproj/project.pbxproj +++ b/WOKA.xcodeproj/project.pbxproj @@ -111,6 +111,10 @@ 52BC3BEE2C16FBDB002FACA6 /* MoreVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52BC3BED2C16FBDB002FACA6 /* MoreVC.swift */; }; 52BC3BF02C1701F8002FACA6 /* BlogDM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52BC3BEF2C1701F8002FACA6 /* BlogDM.swift */; }; 52BC3BF22C170264002FACA6 /* MoreVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52BC3BF12C170264002FACA6 /* MoreVM.swift */; }; + 52BFB52D2C33DAA500BAAE15 /* AudioBooks.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 52BFB52C2C33DAA500BAAE15 /* AudioBooks.storyboard */; }; + 52BFB5332C33DAD700BAAE15 /* AudioBookHomeVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52BFB5322C33DAD700BAAE15 /* AudioBookHomeVC.swift */; }; + 52BFB5352C33DF8A00BAAE15 /* ListenAudioListingDM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52BFB5342C33DF8A00BAAE15 /* ListenAudioListingDM.swift */; }; + 52BFB5372C33E0C500BAAE15 /* AudioBookHomeVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52BFB5362C33E0C500BAAE15 /* AudioBookHomeVM.swift */; }; 52C1A4E12C05B69F007BAA50 /* UIApplicationSwitchRoot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52C1A4E02C05B69F007BAA50 /* UIApplicationSwitchRoot.swift */; }; 52C1A4E52C05BC86007BAA50 /* MainNavController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52C1A4E42C05BC86007BAA50 /* MainNavController.swift */; }; 52C1A4E82C05C95D007BAA50 /* Theme.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 52C1A4E72C05C95D007BAA50 /* Theme.storyboard */; }; @@ -368,6 +372,10 @@ 52BC3BED2C16FBDB002FACA6 /* MoreVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoreVC.swift; sourceTree = ""; }; 52BC3BEF2C1701F8002FACA6 /* BlogDM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlogDM.swift; sourceTree = ""; }; 52BC3BF12C170264002FACA6 /* MoreVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoreVM.swift; sourceTree = ""; }; + 52BFB52C2C33DAA500BAAE15 /* AudioBooks.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = AudioBooks.storyboard; sourceTree = ""; }; + 52BFB5322C33DAD700BAAE15 /* AudioBookHomeVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioBookHomeVC.swift; sourceTree = ""; }; + 52BFB5342C33DF8A00BAAE15 /* ListenAudioListingDM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListenAudioListingDM.swift; sourceTree = ""; }; + 52BFB5362C33E0C500BAAE15 /* AudioBookHomeVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioBookHomeVM.swift; sourceTree = ""; }; 52C1A4E02C05B69F007BAA50 /* UIApplicationSwitchRoot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIApplicationSwitchRoot.swift; sourceTree = ""; }; 52C1A4E42C05BC86007BAA50 /* MainNavController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainNavController.swift; sourceTree = ""; }; 52C1A4E62C05C95D007BAA50 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Theme.storyboard; sourceTree = ""; }; @@ -630,6 +638,7 @@ 523ED25C2BDA2BC700CFED02 /* WOKA */ = { isa = PBXGroup; children = ( + 52BFB52B2C33DA9700BAAE15 /* Audio Books */, 52DAC6462C21761700E2F85B /* WebSeries */, 9C834ED92C1C20EC00B29A9C /* WOKA.entitlements */, 523ED26B2BDA2BC900CFED02 /* Info.plist */, @@ -868,6 +877,49 @@ path = Timer; sourceTree = ""; }; + 52BFB52B2C33DA9700BAAE15 /* Audio Books */ = { + isa = PBXGroup; + children = ( + 52BFB5312C33DAB400BAAE15 /* Model */, + 52BFB5302C33DAB100BAAE15 /* View */, + 52BFB52F2C33DAAE00BAAE15 /* ViewModel */, + 52BFB52E2C33DAA900BAAE15 /* Controller */, + 52BFB52C2C33DAA500BAAE15 /* AudioBooks.storyboard */, + ); + path = "Audio Books"; + sourceTree = ""; + }; + 52BFB52E2C33DAA900BAAE15 /* Controller */ = { + isa = PBXGroup; + children = ( + 52BFB5322C33DAD700BAAE15 /* AudioBookHomeVC.swift */, + ); + name = Controller; + sourceTree = ""; + }; + 52BFB52F2C33DAAE00BAAE15 /* ViewModel */ = { + isa = PBXGroup; + children = ( + 52BFB5362C33E0C500BAAE15 /* AudioBookHomeVM.swift */, + ); + name = ViewModel; + sourceTree = ""; + }; + 52BFB5302C33DAB100BAAE15 /* View */ = { + isa = PBXGroup; + children = ( + ); + name = View; + sourceTree = ""; + }; + 52BFB5312C33DAB400BAAE15 /* Model */ = { + isa = PBXGroup; + children = ( + 52BFB5342C33DF8A00BAAE15 /* ListenAudioListingDM.swift */, + ); + name = Model; + sourceTree = ""; + }; 52C1A4DF2C05B670007BAA50 /* Delegate */ = { isa = PBXGroup; children = ( @@ -1428,6 +1480,7 @@ 52C6E01C2BE383C000E22D59 /* YourIntrestCell.xib in Resources */, 9C834ED32C1C1F9200B29A9C /* Exo2-SemiBold.ttf in Resources */, 9C834ED42C1C1F9200B29A9C /* Exo2-Medium.ttf in Resources */, + 52BFB52D2C33DAA500BAAE15 /* AudioBooks.storyboard in Resources */, 9C834ED52C1C1F9200B29A9C /* Exo2-Bold.ttf in Resources */, 9C834ED62C1C1F9200B29A9C /* Exo2-ExtraBold.ttf in Resources */, 9C834ED72C1C1F9200B29A9C /* Exo2-Regular.ttf in Resources */, @@ -1550,6 +1603,7 @@ 522242662BFC74380085C632 /* MyListVC.swift in Sources */, 52DAC64E2C21775300E2F85B /* WebSeriesVC.swift in Sources */, 5259542B2BEA292800191286 /* UserRegPostModel.swift in Sources */, + 52BFB5352C33DF8A00BAAE15 /* ListenAudioListingDM.swift in Sources */, 52C8B0572BDA57DB003B51D0 /* Constant.swift in Sources */, 52CCD7B02C1AF0F80078BD65 /* RadioVC.swift in Sources */, 52AECA802C08BCB6004A7579 /* PlayerVC.swift in Sources */, @@ -1628,10 +1682,12 @@ 52C8B0742BDA7626003B51D0 /* OnBoardVC.swift in Sources */, 5219C2C22C086D9C00A1DF4D /* DataTypeConversion.swift in Sources */, 525953CF2BE8B28F00191286 /* Utilities.swift in Sources */, + 52BFB5332C33DAD700BAAE15 /* AudioBookHomeVC.swift in Sources */, 52D6A2462C21A29800145908 /* ContinueWatchingDM.swift in Sources */, 9CBCB2A12BE4E50A007D7934 /* TextFieldPassword.swift in Sources */, 52BC3BEC2C16DF9F002FACA6 /* MyOrdersVC.swift in Sources */, 9C56E8482BDBEFAB00E4CA14 /* AssetColor.swift in Sources */, + 52BFB5372C33E0C500BAAE15 /* AudioBookHomeVM.swift in Sources */, 9C0A85432BEE3EC90093783D /* NewPasswordVM.swift in Sources */, 522D65662C1ACE9C0021E505 /* UserNotificationCell.swift in Sources */, 524C42332C049D590016A11C /* CustomizableSegmentControl.swift in Sources */, diff --git a/WOKA/Audio Books/AudioBookHomeVC.swift b/WOKA/Audio Books/AudioBookHomeVC.swift new file mode 100644 index 0000000..af8cfe4 --- /dev/null +++ b/WOKA/Audio Books/AudioBookHomeVC.swift @@ -0,0 +1,329 @@ +// +// AudioBookHomeVC.swift +// WOKA +// +// Created by MacBook Pro on 02/07/24. +// + +import UIKit + +class AudioBookHomeVC: UIViewController { + + var vm = AudioBookHomeVM() + + @IBOutlet weak var scrollView: UIScrollView! + @IBOutlet weak var headerHeight: NSLayoutConstraint! + @IBOutlet weak var continueWatchingCV: UICollectionView! + @IBOutlet weak var audioListingTableView: UITableView! + @IBOutlet weak var tableHeight: NSLayoutConstraint! + @IBOutlet weak var topLabel: UILabel! + @IBOutlet weak var headerViewTopConstraint: NSLayoutConstraint! + @IBOutlet weak var continueWatchingStack: UIStackView! + @IBOutlet weak var headerView: ShimmerEffectView! + @IBOutlet weak var headerImage: UIImageView! + @IBOutlet weak var headerTitleLabel: UILabel! + @IBOutlet weak var listenView: ShimmerEffectView! + + override func viewDidLoad() { + super.viewDidLoad() + vm.vc = self + self.title = "AUDIO BOOKS" + vm.initView() + scrollView.delegate = self + let color1 = #colorLiteral(red: 0, green: 0.7529411765, blue: 0.7529411765, alpha: 1) + let color2 = #colorLiteral(red: 0, green: 0.4784313725, blue: 0.7529411765, alpha: 1) + self.navigationController?.navigationBar.setGradientBackground(colors: [color1, color2], startPoint: .left, endPoint: .right) + + + navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default) + navigationController?.navigationBar.shadowImage = UIImage() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.setNavigationBarHidden(false, animated: animated) + self.navigationController?.setColor(color: .white) + } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + self.navigationController?.setNavigationBarHidden(true, animated: animated) + } + + override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + self.navigationController?.navigationBar.removeGradientBackground() + + // Customize the navigation bar's appearance + self.navigationController?.setColor(color: .black) + } + + override func viewDidLayoutSubviews() { + vm.updateTableHeight() + } +} + +// MARK: - TableView DataSource , Delegates + +extension AudioBookHomeVC : TableViewSRC{ + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return vm.audioListData.count == 0 ? 2 : vm.audioListData.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: K.CellIdentifier.WebSeries.webSeriesShowListingCell) as! WebSeriesShowListingCell + + if vm.audioListData.count == 0{ + cell.showShimmer() + }else{ + let data = vm.audioListData[indexPath.row] + cell.setAudioData(data: data) + cell.stopShimmer() + } + + cell.btnTapped = { [self] (type) -> Void in + updateFavLikes(type: type, index: indexPath.row) + } + + return cell + } + + func updateFavLikes(type : FavCellCLick, index : Int){ +// let data = vm.audioListData[index] +// switch type { +// case .favourite: +// guard let isFav = data.markAsFavourite ,let postID = data.id,let postType = data.contentMoreDetails?.first?.postType else{return} +// if let categoryIds = data.favouriteCategoryIDS?.rawValue { +// let components = categoryIds.components(separatedBy: ",") +// if isFav == true && (components.first == categoryID.toString() || components.last == categoryID.toString()){ +// LikeFavCommonFunc.shareInstance.removeFavourite(postID: postID, postType: postType, categoryID: categoryID, vc: self) { [unowned self] isDone in +// if isDone{ +// vm.showData[index].markAsFavourite = false +// vm.showData[index].favouriteCategoryIDS = ValueWrapper.stringValue("") +// showListingTableView.reloadRows(at: [IndexPath(row: index, section: 0)],with: .none) +// K.GVar.reloadMyList = true +// } +// } +// }else{ +// LikeFavCommonFunc.shareInstance.addFavourite(postID: postID, postType: postType, categoryID: categoryID, vc: self) { [unowned self] isDone in +// if isDone{ +// vm.showData[index].markAsFavourite = true +// vm.showData[index].favouriteCategoryIDS = ValueWrapper.stringValue(categoryID.toString()) +// showListingTableView.reloadRows(at: [IndexPath(row: index, section: 0)],with: .none) +// K.GVar.reloadMyList = true +// } +// } +// } +// return +// } +// case .liked: +// guard let isLiked = data.isLiked ,let postID = data.id,let postType = data.contentMoreDetails?.first?.postType else{return} +// if isLiked{ +// LikeFavCommonFunc.shareInstance.unlikePost(postID: postID, postType: postType, vc: self) { [unowned self] isDone in +// if isDone{ +// vm.showData[index].isLiked = false +// vm.showData[index].likesCount! -= 1 +// showListingTableView.reloadRows(at: [IndexPath(row: index, section: 0)],with: .none) +// } +// } +// }else{ +// LikeFavCommonFunc.shareInstance.likePost(postID: postID, postType: postType, vc: self){ [unowned self] isDone in +// if isDone{ +// vm.showData[index].isLiked = true +// vm.showData[index].likesCount! += 1 +// showListingTableView.reloadRows(at: [IndexPath(row: index, section: 0)],with: .none) +// } +// } +// } +// } + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { +// if vm.showData.count == 0 {return} +// let showData = vm.showData[indexPath.row] +// +// let sb = UIStoryboard(name: K.StoryBoard.webSeries, bundle: nil) +// let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.WebSeries.webSeriesSeasonVC) as! WebSeriesSeasonVC +// vcPush.vm.showData = showData +// vcPush.vm.indexSelected = indexPath.row +// vcPush.likeFavDelegate = self +// if let selectedIndex = vm.dropDownModule.indexForSelectedRow{ +// let categoryID = vm.categoryListingData[selectedIndex] +// vcPush.vm.categoryID = categoryID.id +// } +// self.navigationController?.pushViewController(vcPush, animated: true) + } +} + +// MARK: - CollectionView Delegate and Data Source + +extension AudioBookHomeVC : CollectionViewSRC{ + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return vm.continueWatchingData.count + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: K.CellIdentifier.WebSeries.webSeriesCell, for: indexPath) as! WebSeriesCell + let data = vm.continueWatchingData[indexPath.row] + cell.setData(data: data) + return cell + } + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { +// let data = vm.continueWatchingData[indexPath.row] +// +// let sb = UIStoryboard(name: K.StoryBoard.webSeries, bundle: nil) +// let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.WebSeries.continueWatchingVC) as! ContinueWatchingVC +// vcPush.modalPresentationStyle = .overCurrentContext +// vcPush.modalTransitionStyle = .crossDissolve +// vcPush.watchData = data +// if let selectedIndex = vm.dropDownModule.indexForSelectedRow{ +// let categoryID = vm.categoryListingData[selectedIndex] +// vcPush.categoryID = categoryID.id +// } +// self.present(vcPush, animated: true) + + } + +} + +// MARK: - Collection Flow Layout + +extension AudioBookHomeVC : UICollectionViewDelegateFlowLayout{ + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { + return 5 + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { + let inset: CGFloat = 10 + return UIEdgeInsets(top: 0, left: inset, bottom: 0, right: inset) + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { + return 0 // Space between cells + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + let widthPerItem = collectionView.frame.width - 30 // Adjust to your desired width + return CGSize(width: widthPerItem, height: 230) + } +} + +// MARK: - Animating scrollView + +extension AudioBookHomeVC: UIScrollViewDelegate { + + func scrollViewDidScroll(_ scrollView: UIScrollView) { + + // Get the current vertical offset of the scroll view + let y = scrollView.contentOffset.y + + // Define the height range for the header view + let minHeaderHeight: CGFloat = 0.0 // Height at which the header becomes invisible + let maxHeaderHeight: CGFloat = 200.0 // Maximum height when fully visible + + // Calculate the new height for the header view based on the scroll position + let newHeaderHeight: CGFloat + if y < 0 { + // When scrolling up beyond the top, ensure the header view is fully expanded + newHeaderHeight = maxHeaderHeight + } else { + // Calculate the new height for the header view, ensuring it doesn't go below the minimum height + newHeaderHeight = max(minHeaderHeight, maxHeaderHeight - y) + } + + // Update the header view's height constraint with the new height + headerHeight.constant = newHeaderHeight + + // Animate the layout changes to smoothly transition the header height + UIView.animate(withDuration: 0.3) { + self.view.layoutIfNeeded() + } + } +} + +class UINavigationBarGradientView: UIView { + + enum Point { + case topRight, topLeft + case bottomRight, bottomLeft + case left , right + case custom(point: CGPoint) + + var point: CGPoint { + switch self { + case .topRight: return CGPoint(x: 1, y: 0) + case .topLeft: return CGPoint(x: 0, y: 0) + case .bottomRight: return CGPoint(x: 1, y: 1) + case .bottomLeft: return CGPoint(x: 0, y: 1) + case .left : return CGPoint(x: 0, y: 0) + case .right : return CGPoint(x: 0.8, y: 0) + case .custom(let point): return point + } + } + } + + private weak var gradientLayer: CAGradientLayer! + + convenience init(colors: [UIColor], startPoint: Point = .topLeft, + endPoint: Point = .bottomLeft, locations: [NSNumber] = [0, 1]) { + self.init(frame: .zero) + let gradientLayer = CAGradientLayer() + gradientLayer.frame = frame + layer.addSublayer(gradientLayer) + self.gradientLayer = gradientLayer + set(colors: colors, startPoint: startPoint, endPoint: endPoint, locations: locations) + backgroundColor = .clear + } + + func set(colors: [UIColor], startPoint: Point = .topLeft, + endPoint: Point = .bottomLeft, locations: [NSNumber] = [0, 1]) { + gradientLayer.colors = colors.map { $0.cgColor } + gradientLayer.startPoint = startPoint.point + gradientLayer.endPoint = endPoint.point + gradientLayer.locations = locations + } + + func setupConstraints() { + guard let parentView = superview else { return } + translatesAutoresizingMaskIntoConstraints = false + topAnchor.constraint(equalTo: parentView.topAnchor).isActive = true + leftAnchor.constraint(equalTo: parentView.leftAnchor).isActive = true + parentView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true + parentView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true + } + + override func layoutSubviews() { + super.layoutSubviews() + guard let gradientLayer = gradientLayer else { return } + gradientLayer.frame = frame + superview?.addSubview(self) + } +} + +extension UINavigationBar { + func setGradientBackground(colors: [UIColor], + startPoint: UINavigationBarGradientView.Point = .topLeft, + endPoint: UINavigationBarGradientView.Point = .bottomLeft, + locations: [NSNumber] = [0, 1]) { + guard let backgroundView = value(forKey: "backgroundView") as? UIView else { return } + guard let gradientView = backgroundView.subviews.first(where: { $0 is UINavigationBarGradientView }) as? UINavigationBarGradientView else { + let gradientView = UINavigationBarGradientView(colors: colors, startPoint: startPoint, + endPoint: endPoint, locations: locations) + backgroundView.addSubview(gradientView) + gradientView.setupConstraints() + return + } + gradientView.set(colors: colors, startPoint: startPoint, endPoint: endPoint, locations: locations) + } + + func removeGradientBackground() { + guard let backgroundView = value(forKey: "backgroundView") as? UIView else { return } + if let gradientView = backgroundView.subviews.first(where: { $0 is UINavigationBarGradientView }) { + gradientView.removeFromSuperview() + } + } +} diff --git a/WOKA/Audio Books/AudioBookHomeVM.swift b/WOKA/Audio Books/AudioBookHomeVM.swift new file mode 100644 index 0000000..b93f6d0 --- /dev/null +++ b/WOKA/Audio Books/AudioBookHomeVM.swift @@ -0,0 +1,160 @@ +// +// AudioBookHomeVM.swift +// WOKA +// +// Created by MacBook Pro on 02/07/24. +// + +import Foundation +import Alamofire + +class AudioBookHomeVM{ + + weak var vc : AudioBookHomeVC! + var continueWatchingData = [ContinueWatchingDM.ResultData]() + var audioListData = [ListenAudioListingDM.AudioDatum]() + var indexToLoad = 0 + + func initView(){ + startShimmer() + setupCell() + getContinueWatching() + getShowListing() + } + + func startShimmer(){ + vc.headerView.startShimmer() + vc.listenView.startShimmer() + } + + func updateTableHeight(){ + self.vc.tableHeight.constant = self.vc.audioListingTableView.contentSize.height + 100 + self.vc.audioListingTableView.layoutIfNeeded() + self.vc.tableHeight.constant = self.vc.audioListingTableView.contentSize.height + } + + func setInitialData(){ + if indexToLoad > continueWatchingData.count { + return + } + let data = audioListData[indexToLoad] + + if let url = data.thumbnailPath{ + self.vc.headerImage.imageURL(url, color: .white) + } + + if AuthFunc.shareInstance.getDefaultLanguage() == .english{ + let englishData = data.contentMoreDetails?.filter({$0.languageMasterID == 1}).first + vc.headerTitleLabel.text = englishData?.title + }else{ + let hindiData = data.contentMoreDetails?.filter({$0.languageMasterID == 2}).first + vc.headerTitleLabel.text = hindiData?.title + } + } + + func setupCell(){ + vc.continueWatchingCV.register(UINib(nibName: K.CellIdentifier.WebSeries.webSeriesCell, bundle: nil), forCellWithReuseIdentifier: K.CellIdentifier.WebSeries.webSeriesCell) + vc.continueWatchingCV.delegate = vc.self + vc.continueWatchingCV.dataSource = vc.self + + vc.audioListingTableView.register(UINib(nibName: K.CellIdentifier.WebSeries.webSeriesShowListingCell, bundle: nil), forCellReuseIdentifier: K.CellIdentifier.WebSeries.webSeriesShowListingCell) + vc.audioListingTableView.delegate = vc.self + vc.audioListingTableView.dataSource = vc.self + } + + // MARK: - Api Calls + + func getContinueWatching(){ +// Utilities.startProgressHUD() + let headers : HTTPHeaders = ["access-token" : AuthFunc.shareInstance.getAccessToken()] + let params : Parameters = ["post_type" : 7] // 3- audio + NetworkManager.shareInstance.apiRequest(url: APIEndPoints.WebSeries.continue_watching, method: .post,parameters: params,headers : headers) { [weak self](result : Result, NetworkManager.APIError>) in + switch result{ + case .success(let data): + guard let self else{ + Utilities.dismissProgressHUD() + return + } + switch data.success{ + case 0: + /* + Error + */ + Utilities.dismissProgressHUD() +// vc.toast(msg: data.message ?? "Unrecognised error" , time: 2) + self.vc.continueWatchingStack.isHidden = true + case 1: + Utilities.dismissProgressHUD() + guard let data = data.data?.result else{return} + if data.count == 0{ + self.vc.continueWatchingStack.isHidden = true + }else{ + self.vc.continueWatchingStack.isHidden = false + } + self.continueWatchingData = data.reversed() + self.vc.continueWatchingCV.reloadData() + default: + break + } + case .failure(let error): + guard let self else{ + Utilities.dismissProgressHUD() + return + } + Utilities.dismissProgressHUD() + self.vc.continueWatchingStack.isHidden = true + vc.toast(msg: error.localizedDescription , time: 2) + } + } + } + + func getShowListing(){ +// Utilities.startProgressHUD() + let headers : HTTPHeaders = ["access-token" : AuthFunc.shareInstance.getAccessToken()] + NetworkManager.shareInstance.apiRequest(url: APIEndPoints.AudioBooks.listen_audio_listing, method: .post,headers: headers) { [weak self](result : Result, NetworkManager.APIError>) in + switch result{ + case .success(let data): + guard let self else{ + Utilities.dismissProgressHUD() + return + } + switch data.success{ + case 0: + /* + Error + */ + Utilities.dismissProgressHUD() + vc.toast(msg: data.message ?? "Unrecognised error" , time: 2) + case 1: + Utilities.dismissProgressHUD() + guard let data = data.data?.audioData else{return} + self.audioListData.removeAll() + self.audioListData = data + self.vc.audioListingTableView.reloadData() + self.vc.tableHeight.constant = self.vc.audioListingTableView.contentSize.height + 100 + self.vc.audioListingTableView.layoutIfNeeded() + self.vc.tableHeight.constant = self.vc.audioListingTableView.contentSize.height + self.indexToLoad = 0 + self.setInitialData() + self.stopShimmer() + default: + break + } + case .failure(let error): + guard let self else{ + Utilities.dismissProgressHUD() + return + } + Utilities.dismissProgressHUD() + vc.toast(msg: error.localizedDescription , time: 2) + } + } + } + + func stopShimmer(){ + self.vc.headerView.stopShimmer() + vc.listenView.stopShimmer() +// self.vc.masilaTrailerView.stopShimmer() +// self.vc.videoLanguageView.stopShimmer() + } +} diff --git a/WOKA/Audio Books/AudioBooks.storyboard b/WOKA/Audio Books/AudioBooks.storyboard new file mode 100644 index 0000000..67c6d0f --- /dev/null +++ b/WOKA/Audio Books/AudioBooks.storyboard @@ -0,0 +1,194 @@ + + + + + + + + + + + + Exo2-Bold + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WOKA/Audio Books/ListenAudioListingDM.swift b/WOKA/Audio Books/ListenAudioListingDM.swift new file mode 100644 index 0000000..a22c2d1 --- /dev/null +++ b/WOKA/Audio Books/ListenAudioListingDM.swift @@ -0,0 +1,95 @@ +// +// ListenAudioListingDM.swift +// WOKA +// +// Created by MacBook Pro on 02/07/24. +// + +import Foundation + +// MARK: - ListenAudioListingDM +struct ListenAudioListingDM: Codable { + let audioData: [AudioDatum]? + let totalRecords: Int? + + enum CodingKeys: String, CodingKey { + case audioData = "audio_data" + case totalRecords = "total_records" + } + + // MARK: - AudioDatum + struct AudioDatum: Codable { + let id: Int? + let title, description: String? + let thumbnailPath: String? + let audioURL: String? + let categoryMasterID, ageRangeMasterID, tagsKeyword: String? + let releaseDate: String? + let languageMasterID: Int? + let genderMasterID, audioDuration, mediaID: String? + let contentMoreDetails: [ContentMoreDetail]? +// let userVideoView: [JSONAny]? + let categoryData: [CategoryDatum]? +// let ageRangeData, genderData: [JSONAny]? + let markAsFavourite, isLiked: Bool? + let viewsCount, likesCount, bookmarkCount: Int? + + enum CodingKeys: String, CodingKey { + case id, title, description + case thumbnailPath = "thumbnail_path" + case audioURL = "audio_url" + case categoryMasterID = "category_master_id" + case ageRangeMasterID = "age_range_master_id" + case tagsKeyword = "tags_keyword" + case releaseDate = "release_date" + case languageMasterID = "language_master_id" + case genderMasterID = "gender_master_id" + case audioDuration = "audio_duration" + case mediaID = "media_id" + case contentMoreDetails = "content_more_details" +// case userVideoView = "user_video_view" +// case ageRangeData = "age_range_data" +// case genderData = "gender_data" + case categoryData = "category_data" + case markAsFavourite = "mark_as_favourite" + case isLiked = "is_liked" + case viewsCount = "views_count" + case likesCount = "likes_count" + case bookmarkCount = "bookmark_count" + } + } + + // MARK: - CategoryDatum + struct CategoryDatum: Codable { + let id: Int? + let categoryName: CategoryName? + + enum CodingKeys: String, CodingKey { + case id + case categoryName = "category_name" + } + } + + enum CategoryName: String, Codable { + case audio = "Audio" + } + + // MARK: - ContentMoreDetail + struct ContentMoreDetail: Codable { + let id, contentID, postType, languageMasterID: Int? + let title, description: String? + let url: String? + let tagsKeywords: String? + + enum CodingKeys: String, CodingKey { + case id + case contentID = "content_id" + case postType = "post_type" + case languageMasterID = "language_master_id" + case title, description, url + case tagsKeywords = "tags_keywords" + } + } + +} + diff --git a/WOKA/Constants K/StoryBoard.swift b/WOKA/Constants K/StoryBoard.swift index 1332bce..aef5e49 100644 --- a/WOKA/Constants K/StoryBoard.swift +++ b/WOKA/Constants K/StoryBoard.swift @@ -17,5 +17,6 @@ extension K{ static let theme = "Theme" static let sideBarNav = "SideBarNav" static let webSeries = "WebSeries" + static let audioBooks = "AudioBooks" } } diff --git a/WOKA/Constants K/StoryBoardID.swift b/WOKA/Constants K/StoryBoardID.swift index 132fc17..a9fda95 100644 --- a/WOKA/Constants K/StoryBoardID.swift +++ b/WOKA/Constants K/StoryBoardID.swift @@ -65,5 +65,12 @@ extension K{ static let episodeDetailsVC = "EpisodeDetailsVC" static let continueWatchingVC = "ContinueWatchingVC" } + + // MARK: - AudioBooks + + struct AudioBooks{ + static let audioBookHomeVC = "AudioBookHomeVC" + } + } } diff --git a/WOKA/Network Adapter/APIEndPoints.swift b/WOKA/Network Adapter/APIEndPoints.swift index 16c4aed..756e4fc 100644 --- a/WOKA/Network Adapter/APIEndPoints.swift +++ b/WOKA/Network Adapter/APIEndPoints.swift @@ -90,6 +90,10 @@ struct APIEndPoints { static let teaser_listing = makeURL(path: "teaser_listing") } + struct AudioBooks{ + static let listen_audio_listing = makeURL(path: "listen_audio_listing") + } + // Other endpoint categories... struct Links { static let privacyPolicy = "https://www.wokaland.com/privacy-policy/" diff --git a/WOKA/Theme/Base.lproj/Theme.storyboard b/WOKA/Theme/Base.lproj/Theme.storyboard index c5e8997..2cd316b 100644 --- a/WOKA/Theme/Base.lproj/Theme.storyboard +++ b/WOKA/Theme/Base.lproj/Theme.storyboard @@ -304,34 +304,14 @@ - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + - + + - - - - + @@ -423,6 +432,7 @@ + @@ -430,6 +440,7 @@ + diff --git a/WOKA/Theme/Controller/ThemeOneVC.swift b/WOKA/Theme/Controller/ThemeOneVC.swift index 9100d82..fe4f69c 100644 --- a/WOKA/Theme/Controller/ThemeOneVC.swift +++ b/WOKA/Theme/Controller/ThemeOneVC.swift @@ -23,6 +23,7 @@ class ThemeOneVC: UIViewController { @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! diff --git a/WOKA/Theme/ViewModel/ThemeOneVM.swift b/WOKA/Theme/ViewModel/ThemeOneVM.swift index fd5a042..01a2abc 100644 --- a/WOKA/Theme/ViewModel/ThemeOneVM.swift +++ b/WOKA/Theme/ViewModel/ThemeOneVM.swift @@ -126,6 +126,15 @@ class ThemeOneVM{ vc.navigationController?.pushViewController(vcPush, animated: true) } } + + vc.audioBooksView.addTapGesture { + ViewButtonAnimation.sharedInstance.btnTapped(in: self.vc, view: self.vc.audioBooksView) { [weak self] in + guard let self else{return} + let sb = UIStoryboard(name: K.StoryBoard.audioBooks, bundle: nil) + let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.AudioBooks.audioBookHomeVC) as! AudioBookHomeVC + vc.navigationController?.pushViewController(vcPush, animated: true) + } + } } // MARK: - Animate Clouds and LiveTV diff --git a/WOKA/WebSeries/View/WebSeriesShowListingCell.swift b/WOKA/WebSeries/View/WebSeriesShowListingCell.swift index 7f5fad1..e3ce573 100644 --- a/WOKA/WebSeries/View/WebSeriesShowListingCell.swift +++ b/WOKA/WebSeries/View/WebSeriesShowListingCell.swift @@ -80,6 +80,37 @@ class WebSeriesShowListingCell: UITableViewCell { } } + func setAudioData(data: ListenAudioListingDM.AudioDatum){ + //heart.fill , heart , hand.thumbsup.fill , hand.thumbsup + if AuthFunc.shareInstance.getDefaultLanguage() == .english{ + showTitle.text = data.contentMoreDetails?.filter({$0.languageMasterID == 1}).first?.title + }else{ + showTitle.text = data.contentMoreDetails?.filter({$0.languageMasterID == 2}).first?.title + } + totalLikes.text = data.likesCount?.toString() ?? "0" + + if let url = data.thumbnailPath{ + showThumbnail.imageURL(url) + } + + if let like = data.isLiked{ + switch like{ + case true: + likeBtn.setImage(UIImage(named: "LikeAdd"), for: .normal) + case false: + likeBtn.setImage(UIImage(named: "LikeRemove"), for: .normal) + } + } + + if let favourite = data.markAsFavourite{ + if favourite == true{ + favBtn.setImage(UIImage(named: "FavouriteAdd"), for: .normal) + }else{ + favBtn.setImage(UIImage(named: "FavouriteRemove"), for: .normal) + } + } + } + @IBAction func btnTapped(_ sender: UIButton) { switch sender{ case likeBtn: