- WebSeries, Webseries Episode, Karaoke, Audio Books, Games Removed Load More button, and applied infinite Scrolling.

- Also handled null for local ads url.
This commit is contained in:
2024-10-16 19:37:07 +05:30
parent a0bf4a99ac
commit 4ef01bafd7
20 changed files with 523 additions and 407 deletions

View File

@@ -174,6 +174,7 @@
52ACC13A2C64CD0100791528 /* MyOrderDetailsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52ACC1382C64CD0100791528 /* MyOrderDetailsCell.swift */; };
52ACC13B2C64CD0100791528 /* MyOrderDetailsCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 52ACC1392C64CD0100791528 /* MyOrderDetailsCell.xib */; };
52ACC13D2C64DFC300791528 /* MyListViewAllVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52ACC13C2C64DFC300791528 /* MyListViewAllVC.swift */; };
52ADF4762CBFAE3C002B9F4B /* HapticFeedbackGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52ADF4752CBFAE32002B9F4B /* HapticFeedbackGenerator.swift */; };
52AECA802C08BCB6004A7579 /* PlayerVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52AECA7F2C08BCB6004A7579 /* PlayerVC.swift */; };
52AF71EE2C36AD3100BC5972 /* GamesListVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52AF71ED2C36AD3100BC5972 /* GamesListVM.swift */; };
52AF71F02C36B29A00BC5972 /* GamesListDM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52AF71EF2C36B29A00BC5972 /* GamesListDM.swift */; };
@@ -586,6 +587,7 @@
52ACC1382C64CD0100791528 /* MyOrderDetailsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyOrderDetailsCell.swift; sourceTree = "<group>"; };
52ACC1392C64CD0100791528 /* MyOrderDetailsCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MyOrderDetailsCell.xib; sourceTree = "<group>"; };
52ACC13C2C64DFC300791528 /* MyListViewAllVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyListViewAllVC.swift; sourceTree = "<group>"; };
52ADF4752CBFAE32002B9F4B /* HapticFeedbackGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HapticFeedbackGenerator.swift; sourceTree = "<group>"; };
52AECA7F2C08BCB6004A7579 /* PlayerVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerVC.swift; sourceTree = "<group>"; };
52AF71ED2C36AD3100BC5972 /* GamesListVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GamesListVM.swift; sourceTree = "<group>"; };
52AF71EF2C36B29A00BC5972 /* GamesListDM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GamesListDM.swift; sourceTree = "<group>"; };
@@ -1527,6 +1529,7 @@
52C8B0512BDA4B51003B51D0 /* Helpers */ = {
isa = PBXGroup;
children = (
52ADF4752CBFAE32002B9F4B /* HapticFeedbackGenerator.swift */,
525855162CBD3C6C00E6002A /* PlayerStatusEnum.swift */,
52423CD02CB6A8A300623CA7 /* CheckReachability.swift */,
5282DB2D2C981E9300465BA1 /* AdResuable */,
@@ -2518,6 +2521,7 @@
9CBCB29B2BE4D614007D7934 /* LoginVC.swift in Sources */,
52BC3BE82C0E04A9002FACA6 /* FaqListDM.swift in Sources */,
9C56E83B2BDBC6E600E4CA14 /* SelectAgeVM.swift in Sources */,
52ADF4762CBFAE3C002B9F4B /* HapticFeedbackGenerator.swift in Sources */,
9C535DC02C00B36000DA6DCD /* HomeVC.swift in Sources */,
52B8D4E22C04A25E00ED65F3 /* Segue.swift in Sources */,
52AC2D272C29791500337473 /* JWPlayerManager.swift in Sources */,
@@ -2905,7 +2909,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = WOKA/WOKA.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 6;
CURRENT_PROJECT_VERSION = 7;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 4S9A74ZB6H;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
@@ -2949,7 +2953,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = WOKA/WOKA.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 6;
CURRENT_PROJECT_VERSION = 7;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 4S9A74ZB6H;
ENABLE_USER_SCRIPT_SANDBOXING = NO;

View File

@@ -28,7 +28,6 @@ class AudioBookHomeVC: UIViewController {
@IBOutlet weak var listenView: ShimmerEffectView!
@IBOutlet weak var noDataView: UIView!
@IBOutlet weak var loadMoreBtn: LocalisedElementsButton!
@IBOutlet weak var loadMoreActivityIndicator: UIActivityIndicatorView!
override func viewDidLoad() {
@@ -86,25 +85,32 @@ class AudioBookHomeVC: UIViewController {
vm.updateTableHeight()
}
@IBAction func loadMoreBtn(_ sender: LocalisedElementsButton) {
PersistentStorage.shared.addOthersCount()
if CheckReachability.reachability?.isReachable == false{
self.toast(msg: K.ConstantString.noInternet , time: 2)
return
}
loadMoreBtn.isHidden = true
vm.pageNo += 1
loadMoreActivityIndicator.startAnimating()
vm.getShowListing()
}
// @IBAction func loadMoreBtn(_ sender: LocalisedElementsButton) {
// PersistentStorage.shared.addOthersCount()
// if CheckReachability.reachability?.isReachable == false{
// self.toast(msg: K.ConstantString.noInternet , time: 2)
// return
// }
// loadMoreBtn.isHidden = true
// vm.pageNo += 1
// loadMoreActivityIndicator.startAnimating()
// vm.getShowListing()
// }
@IBAction func listenAudioBtnTapped(_ sender: LocalisedElementsButton) {
/*
MAke logic for ads
*/
if let adsData = AuthFunc.shareInstance.adsData{
if let adsData = AuthFunc.shareInstance.adsData, let audioBooksAd = adsData.result?.filter({$0.slug == AdsEnum.audioBooks.rawValue}).first{
// URL maybe null so handle it
if audioBooksAd.advertisement?.isActive == "1" && audioBooksAd.advertisement?.adLink == nil{
// it means local ad is active and url is null
return
}
// check if ads data contains ad for webseries
if let audioBooksAd = adsData.result?.filter({$0.slug == AdsEnum.audioBooks.rawValue}).first, let adLink = audioBooksAd.advertisement?.adLink, let adID = audioBooksAd.advertisement?.id{
if let adLink = audioBooksAd.advertisement?.adLink, let adID = audioBooksAd.advertisement?.id{
PersistentStorage.shared.addAdsCount(adID: adID,clicks: 1)
if let url = URL(string: adLink), UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url)
@@ -405,6 +411,27 @@ extension AudioBookHomeVC: UIScrollViewDelegate {
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
// dont do network call if the showdata count is same as the total count provided by api
// also check if already the api call is done
if vm.audioListData.count == vm.totalDataCount || vm.isAudioDataLoading == true {return}
let contentHeight = scrollView.contentSize.height
let height = scrollView.frame.size.height
// Check if the user scrolled to the bottom
if y > contentHeight - height - 50{
// check if internet is available
if CheckReachability.reachability?.isReachable == false{
return
}
//start the acitvity indicator
loadMoreActivityIndicator.startAnimating()
vm.isAudioDataLoading = true
vm.getShowListing(isBtnClick: true)
}
}
}

View File

@@ -17,7 +17,11 @@ class AudioBookHomeVM{
var headerData : ListenAudioListingDM.AudioDatum?
// PAgination variables
var pageNo = 0
var isAudioDataLoading = false
var totalDataCount = 0 // this will hold the total count from api
var maxHeaderHeight = 0.0
var headerBannerView = GADBannerView()
@@ -168,6 +172,7 @@ class AudioBookHomeVM{
case .success(let data):
guard let self else{
Utilities.dismissProgressHUD()
self?.isAudioDataLoading = false
return
}
switch data.success{
@@ -176,14 +181,27 @@ class AudioBookHomeVM{
Error
*/
Utilities.dismissProgressHUD()
self.isAudioDataLoading = false
vc.toast(msg: data.message ?? "Unrecognised error" , time: 2)
case 1:
Utilities.dismissProgressHUD()
getContinueWatching()
if !isBtnClick{
getContinueWatching()
HapticFeedbackGenerator.shared.rigidImpact()
}
self.pageNo += 1
self.isAudioDataLoading = false
guard let dataCount = data.data?.totalRecords ,let data = data.data?.audioData else{return}
self.totalDataCount = dataCount
self.audioListData.append(contentsOf: data)
self.vc.audioListingTableView.reloadData()
self.vc.tableHeight.constant = self.vc.audioListingTableView.contentSize.height + 100
if !isBtnClick{
self.vc.tableHeight.constant = self.vc.audioListingTableView.contentSize.height + 100
}
self.vc.audioListingTableView.layoutIfNeeded()
self.vc.tableHeight.constant = self.vc.audioListingTableView.contentSize.height
@@ -198,39 +216,12 @@ class AudioBookHomeVM{
self.setHeaderData()
}
}
// if let adsData = AuthFunc.shareInstance.adsData{
// // check if ads data contains ad for webseries
// if let audioBooksAd = adsData.result?.filter({$0.slug == AdsEnum.audioBooks.rawValue}).first, let bannerImage = audioBooksAd.advertisement?.bannerImage, let buttonImage = audioBooksAd.advertisement?.buttonImage{
// vc.headerImage.imageURL(bannerImage, color: .white)
// vc.headerBtn.setTitle("", for: .normal)
// vc.headerTitleLabel.text = ""
// vc.headerTitleHeight.constant = 10
// vc.headerBtn.backgroundColor = .clear
// vc.headerBtn.sd_setBackgroundImage(with: URL(string:buttonImage), for: .normal)
// }else{
// if !isBtnClick{
// self.headerData = self.audioListData.first
// self.setHeaderData()
// }
// }
// }else{
// if !isBtnClick{
// self.headerData = self.audioListData.first
// self.setHeaderData()
// }
// }
self.stopShimmer()
self.vc.loadMoreActivityIndicator.stopAnimating()
self.vc.loadMoreActivityIndicator.hidesWhenStopped = true
if self.audioListData.count == dataCount{
self.vc.loadMoreBtn.isHidden = true
}else{
self.vc.loadMoreBtn.isHidden = false
}
checkAds()
default:
break
@@ -238,9 +229,11 @@ class AudioBookHomeVM{
case .failure(let error):
guard let self else{
Utilities.dismissProgressHUD()
self?.isAudioDataLoading = false
return
}
Utilities.dismissProgressHUD()
self.isAudioDataLoading = false
vc.toast(msg: error.localizedDescription , time: K.ConstantString.errorTime)
self.stopShimmer()
self.vc.noDataView.isHidden = false

View File

@@ -98,7 +98,7 @@
<rect key="frame" x="0.0" y="116" width="393" height="477"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="15" translatesAutoresizingMaskIntoConstraints="NO" id="LRD-os-sag">
<rect key="frame" x="0.0" y="0.0" width="393" height="105"/>
<rect key="frame" x="0.0" y="0.0" width="393" height="75"/>
<subviews>
<stackView hidden="YES" opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="wjN-Eq-Uv8">
<rect key="frame" x="10" y="-270" width="373" height="270"/>
@@ -150,31 +150,10 @@
</subviews>
</stackView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="JdL-UR-aEk">
<rect key="frame" x="10" y="55" width="373" height="50"/>
<rect key="frame" x="10" y="55" width="373" height="20"/>
<subviews>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="r2H-eP-JnE" customClass="LocalisedElementsButton" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="109" y="0.0" width="155" height="50"/>
<color key="backgroundColor" red="0.36862745099999999" green="0.1215686275" blue="0.76862745099999996" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="JCn-Ft-aaW"/>
<constraint firstAttribute="width" constant="155" id="iXA-M0-1Nt"/>
</constraints>
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="18"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<inset key="titleEdgeInsets" minX="5" minY="0.0" maxX="0.0" maxY="0.0"/>
<inset key="imageEdgeInsets" minX="-10" minY="0.0" maxX="10" maxY="0.0"/>
<state key="normal" title="LOAD MORE"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
<integer key="value" value="25"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<connections>
<action selector="loadMoreBtn:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="c1q-er-FbM"/>
</connections>
</button>
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="medium" translatesAutoresizingMaskIntoConstraints="NO" id="SC3-M4-kXo">
<rect key="frame" x="161.66666666666666" y="0.0" width="50" height="50"/>
<rect key="frame" x="176.66666666666666" y="0.0" width="20" height="20"/>
<constraints>
<constraint firstAttribute="width" secondItem="SC3-M4-kXo" secondAttribute="height" multiplier="1:1" id="yMz-Th-LQe"/>
</constraints>
@@ -183,12 +162,9 @@
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="r2H-eP-JnE" secondAttribute="bottom" id="R5x-qH-ThN"/>
<constraint firstAttribute="bottom" secondItem="SC3-M4-kXo" secondAttribute="bottom" id="XbZ-xY-5dk"/>
<constraint firstItem="r2H-eP-JnE" firstAttribute="centerX" secondItem="JdL-UR-aEk" secondAttribute="centerX" id="bOq-9R-kbi"/>
<constraint firstItem="SC3-M4-kXo" firstAttribute="centerX" secondItem="JdL-UR-aEk" secondAttribute="centerX" id="doe-Mg-Vvs"/>
<constraint firstItem="SC3-M4-kXo" firstAttribute="top" secondItem="JdL-UR-aEk" secondAttribute="top" id="q2p-a2-Po0"/>
<constraint firstItem="r2H-eP-JnE" firstAttribute="top" secondItem="JdL-UR-aEk" secondAttribute="top" id="ud7-Eq-r0z"/>
</constraints>
</view>
</subviews>
@@ -281,7 +257,6 @@
<outlet property="headerViewTopConstraint" destination="1nk-Sb-8DA" id="0WC-Ao-ddY"/>
<outlet property="listenView" destination="U8f-iQ-dPK" id="viY-Sn-3SO"/>
<outlet property="loadMoreActivityIndicator" destination="SC3-M4-kXo" id="WiT-SC-pYV"/>
<outlet property="loadMoreBtn" destination="r2H-eP-JnE" id="6rt-ro-60V"/>
<outlet property="noDataView" destination="6Su-mo-dnw" id="cRp-AO-QlG"/>
<outlet property="scrollView" destination="QFQ-dJ-08w" id="iQT-YH-vSA"/>
<outlet property="tableHeight" destination="B9K-xl-IPt" id="DoT-oS-DrI"/>

View File

@@ -22,7 +22,7 @@ class GamesListVC: UIViewController {
@IBOutlet weak var gamesLoadingView: ShimmerEffectView!
@IBOutlet weak var noDataView: UIView!
@IBOutlet weak var loadMoreBtn: LocalisedElementsButton!
// @IBOutlet weak var loadMoreBtn: LocalisedElementsButton!
@IBOutlet weak var loadMoreActivityIndicator: UIActivityIndicatorView!
var vm = GamesListVM()
@@ -35,8 +35,6 @@ class GamesListVC: UIViewController {
self.title = "GAMES".localized(loc: AuthFunc.shareInstance.languageSelected.rawValue)
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()
}
override func viewWillAppear(_ animated: Bool) {
@@ -84,9 +82,16 @@ class GamesListVC: UIViewController {
/*
MAke logic for ads
*/
if let adsData = AuthFunc.shareInstance.adsData{
if let adsData = AuthFunc.shareInstance.adsData, let gamesAd = adsData.result?.filter({$0.slug == AdsEnum.games.rawValue}).first{
// URL maybe null so handle it
if gamesAd.advertisement?.isActive == "1" && gamesAd.advertisement?.adLink == nil{
// it means local ad is active and url is null
return
}
// check if ads data contains ad for webseries
if let gamesAd = adsData.result?.filter({$0.slug == AdsEnum.games.rawValue}).first, let adLink = gamesAd.advertisement?.adLink, let adID = gamesAd.advertisement?.id{
if let adLink = gamesAd.advertisement?.adLink, let adID = gamesAd.advertisement?.id{
PersistentStorage.shared.addAdsCount(adID: adID,clicks: 1)
if let url = URL(string: adLink), UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url)
@@ -110,17 +115,17 @@ class GamesListVC: UIViewController {
self.present(vcPush, animated: true)
}
@IBAction func loadMoreBtnTapped(_ sender: LocalisedElementsButton) {
PersistentStorage.shared.addOthersCount()
if CheckReachability.reachability?.isReachable == false{
self.toast(msg: K.ConstantString.noInternet , time: 2)
return
}
loadMoreBtn.isHidden = true
vm.pageNo += 1
loadMoreActivityIndicator.startAnimating()
vm.getGamesListing(isBtnClick: true)
}
// @IBAction func loadMoreBtnTapped(_ sender: LocalisedElementsButton) {
// PersistentStorage.shared.addOthersCount()
// if CheckReachability.reachability?.isReachable == false{
// self.toast(msg: K.ConstantString.noInternet , time: 2)
// return
// }
// loadMoreBtn.isHidden = true
// vm.pageNo += 1
// loadMoreActivityIndicator.startAnimating()
// vm.getGamesListing(isBtnClick: true)
// }
@IBAction func retryBtnTapped(_ sender: LocalisedElementsButton) {
/*
@@ -298,5 +303,26 @@ extension GamesListVC: UIScrollViewDelegate {
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
// dont do network call if the showdata count is same as the total count provided by api
// also check if already the api call is done
if vm.gameData.count == vm.totalDataCount || vm.isGameDataLoading == true {return}
let contentHeight = scrollView.contentSize.height
let height = scrollView.frame.size.height
// Check if the user scrolled to the bottom
if y > contentHeight - height - 50{
// check if internet is available
if CheckReachability.reachability?.isReachable == false{
return
}
//start the acitvity indicator
loadMoreActivityIndicator.startAnimating()
vm.isGameDataLoading = true
vm.getGamesListing(isBtnClick: true)
}
}
}

View File

@@ -135,9 +135,7 @@ class GamesWebViewVC: UIViewController, WKNavigationDelegate,UIGestureRecognizer
AdReusable.sharedInstance.setupBannerAd(bannerView: self.bottomBannerView, in: adView, adUnitID: K.GoogleAdIDs.themeTwo, viewController: self)
})
}
}
// MARK: - App LifeCycle HAndler

View File

@@ -99,7 +99,7 @@
<rect key="frame" x="0.0" y="116" width="414" height="532"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="15" translatesAutoresizingMaskIntoConstraints="NO" id="KYp-fS-yk4">
<rect key="frame" x="0.0" y="0.0" width="414" height="120"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="90"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="HAVE A FUN TIME" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MGh-K4-gtY" customClass="LocalisedElementsLabel" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="10" y="0.0" width="394" height="40"/>
@@ -118,31 +118,10 @@
</constraints>
</tableView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="9Mm-aO-TTm">
<rect key="frame" x="10" y="70" width="394" height="50"/>
<rect key="frame" x="10" y="70" width="394" height="20"/>
<subviews>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="84a-EX-VYD" customClass="LocalisedElementsButton" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="119.5" y="0.0" width="155" height="50"/>
<color key="backgroundColor" red="0.36862745099999999" green="0.1215686275" blue="0.76862745099999996" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="155" id="447-he-qgr"/>
<constraint firstAttribute="height" constant="50" id="KTi-o8-Dme"/>
</constraints>
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="18"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<inset key="titleEdgeInsets" minX="5" minY="0.0" maxX="0.0" maxY="0.0"/>
<inset key="imageEdgeInsets" minX="-10" minY="0.0" maxX="10" maxY="0.0"/>
<state key="normal" title="LOAD MORE"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
<integer key="value" value="25"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<connections>
<action selector="loadMoreBtnTapped:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="S3u-Ci-UcJ"/>
</connections>
</button>
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="medium" translatesAutoresizingMaskIntoConstraints="NO" id="ulX-KY-9er">
<rect key="frame" x="172" y="0.0" width="50" height="50"/>
<rect key="frame" x="187" y="0.0" width="20" height="20"/>
<constraints>
<constraint firstAttribute="width" secondItem="ulX-KY-9er" secondAttribute="height" multiplier="1:1" id="ZUq-66-WVN"/>
</constraints>
@@ -151,12 +130,9 @@
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="84a-EX-VYD" firstAttribute="top" secondItem="9Mm-aO-TTm" secondAttribute="top" id="1fO-tP-VXK"/>
<constraint firstItem="ulX-KY-9er" firstAttribute="centerX" secondItem="9Mm-aO-TTm" secondAttribute="centerX" id="HRx-A5-AzB"/>
<constraint firstAttribute="bottom" secondItem="ulX-KY-9er" secondAttribute="bottom" id="U6U-gO-JQh"/>
<constraint firstItem="ulX-KY-9er" firstAttribute="top" secondItem="9Mm-aO-TTm" secondAttribute="top" id="WeX-CY-opT"/>
<constraint firstAttribute="bottom" secondItem="84a-EX-VYD" secondAttribute="bottom" id="d3V-th-lSH"/>
<constraint firstItem="84a-EX-VYD" firstAttribute="centerX" secondItem="9Mm-aO-TTm" secondAttribute="centerX" id="jHU-f4-tvs"/>
</constraints>
</view>
</subviews>
@@ -246,7 +222,6 @@
<outlet property="headerTitleLabel" destination="7BL-Zy-PFm" id="kro-hg-bg7"/>
<outlet property="headerView" destination="mer-q0-6Vp" id="Ni3-qe-8Ud"/>
<outlet property="loadMoreActivityIndicator" destination="ulX-KY-9er" id="jGf-y1-HQw"/>
<outlet property="loadMoreBtn" destination="84a-EX-VYD" id="xRs-D4-3hc"/>
<outlet property="noDataView" destination="ROs-m4-xEv" id="JWN-AK-IfB"/>
<outlet property="scrollView" destination="Jyq-DW-OZz" id="1eX-0n-4I1"/>
<outlet property="tableHeight" destination="DJl-l2-EKl" id="5Fi-db-TJJ"/>

View File

@@ -14,12 +14,17 @@ class GamesListVM{
weak var vc : GamesListVC!
var gameData = [GamesListDM.GameDatum]()
var indexToLoad = 0
var pageNo = 0
var maxHeaderHeight = 0.0
// PAgination variables
var pageNo = 0
var isGameDataLoading = false
var totalDataCount = 0 // this will hold the total count from api
var headerBannerView = GADBannerView()
var headerBannerBottomView = GADBannerView()
let feedbackGenerator = UIImpactFeedbackGenerator(style: .rigid)
func initView(){
setupCell()
vc.scrollView.indicatorStyle = .white // or .white
@@ -124,6 +129,7 @@ class GamesListVM{
case .success(let data):
guard let self else{
Utilities.dismissProgressHUD()
self?.isGameDataLoading = false
return
}
switch data.success{
@@ -132,69 +138,68 @@ class GamesListVM{
Error
*/
Utilities.dismissProgressHUD()
self.isGameDataLoading = false
self.vc.loadMoreActivityIndicator.stopAnimating()
self.vc.loadMoreActivityIndicator.hidesWhenStopped = true
// vc.toast(msg: data.message ?? "Unrecognised error" , time: 2)
case 1:
Utilities.dismissProgressHUD()
self.isGameDataLoading = false
self.pageNo += 1
guard let dataCount = data.data?.totalRecords, let data = data.data?.gameData else{return}
//update the total data count
self.totalDataCount = dataCount
self.gameData.append(contentsOf: data)
//Reload games tableview and increase height inside the scrollview
self.vc.gamesListingTableView.reloadData()
self.vc.tableHeight.constant = self.vc.gamesListingTableView.contentSize.height + 100
if !isBtnClick{
HapticFeedbackGenerator.shared.rigidImpact()
self.vc.tableHeight.constant = self.vc.gamesListingTableView.contentSize.height + 100
}
self.vc.gamesListingTableView.layoutIfNeeded()
self.vc.tableHeight.constant = self.vc.gamesListingTableView.contentSize.height
/*
MAke logic for ads
*/
if let adsData = AuthFunc.shareInstance.adsData{
// check if ads data contains ad for webseries
if let gamesAd = adsData.result?.filter({$0.slug == AdsEnum.games.rawValue}).first, let bannerImage = gamesAd.advertisement?.bannerImage, let buttonImage = gamesAd.advertisement?.buttonImage{
vc.headerImage.imageURL(bannerImage, color: .white)
vc.headerBtn.setTitle("", for: .normal)
vc.headerTitleLabel.text = ""
vc.headerTitleHeight.constant = 10
vc.headerBtn.backgroundColor = .clear
vc.headerBtn.sd_setBackgroundImage(with: URL(string:buttonImage), for: .normal)
}else{
if !isBtnClick{
setHeaderData()
}
}
}else{
if !isBtnClick{
setHeaderData()
}
}
self.stopShimmer()
self.vc.loadMoreActivityIndicator.stopAnimating()
self.vc.loadMoreActivityIndicator.hidesWhenStopped = true
if self.gameData.count == dataCount{
self.vc.loadMoreBtn.isHidden = true
}else{
self.vc.loadMoreBtn.isHidden = false
}
// if self.gameData.count.isMultiple(of: 5) && !self.stopFetch{
// // if not multiple of 10, means more data can be there, show more btn
// self.vc.loadMoreBtn.isHidden = false
/*
MAke logic for ads
// */
// if let adsData = AuthFunc.shareInstance.adsData{
// // check if ads data contains ad for webseries
// if let gamesAd = adsData.result?.filter({$0.slug == AdsEnum.games.rawValue}).first, let bannerImage = gamesAd.advertisement?.bannerImage, let buttonImage = gamesAd.advertisement?.buttonImage{
// vc.headerImage.imageURL(bannerImage, color: .white)
// vc.headerBtn.setTitle("", for: .normal)
// vc.headerTitleLabel.text = ""
// vc.headerTitleHeight.constant = 10
// vc.headerBtn.backgroundColor = .clear
// vc.headerBtn.sd_setBackgroundImage(with: URL(string:buttonImage), for: .normal)
// }else{
// if !isBtnClick{
// setHeaderData()
// }
// }
// }else{
// self.stopFetch = true
// self.vc.loadMoreBtn.isHidden = true
// if !isBtnClick{
// setHeaderData()
// }
// }
default:
break
self.isGameDataLoading = false
}
case .failure(let error):
guard let self else{
Utilities.dismissProgressHUD()
self?.isGameDataLoading = false
return
}
Utilities.dismissProgressHUD()
self.isGameDataLoading = false
self.stopShimmer()
self.vc.noDataView.isHidden = false
vc.toast(msg: error.localizedDescription, time: K.ConstantString.errorTime)

View File

@@ -0,0 +1,101 @@
//
// HapticFeedbackGenerator.swift
// WOKA
//
// Created by MacBook Pro on 16/10/24.
//
import UIKit
class HapticFeedbackGenerator{
// Singleton instance for reuse across the app
static let shared = HapticFeedbackGenerator()
// Private initializer to prevent instantiation from outside
private init() {}
/*
// Trigger light impact feedback
HapticFeedbackGenerator.shared.lightImpact()
// Trigger success notification feedback
HapticFeedbackGenerator.shared.successNotification()
// Trigger selection feedback
HapticFeedbackGenerator.shared.simpleSelection()
*/
// MARK: - Impact Feedback
func impact(style: UIImpactFeedbackGenerator.FeedbackStyle) {
let generator = UIImpactFeedbackGenerator(style: style)
generator.prepare() // Prepares the feedback generator to reduce latency
generator.impactOccurred() // Trigger the haptic feedback
}
// MARK: - Notification Feedback
func notification(type: UINotificationFeedbackGenerator.FeedbackType) {
let generator = UINotificationFeedbackGenerator()
generator.prepare()
generator.notificationOccurred(type)
}
// MARK: - Selection Feedback
func selection() {
let generator = UISelectionFeedbackGenerator()
generator.prepare()
generator.selectionChanged()
}
// MARK: - Common Presets
// Light impact feedback
func lightImpact() {
impact(style: .light)
}
// Medium impact feedback
func mediumImpact() {
impact(style: .medium)
}
// Heavy impact feedback
func heavyImpact() {
impact(style: .heavy)
}
// Soft impact feedback (available iOS 13+)
func softImpact() {
if #available(iOS 13.0, *) {
impact(style: .soft)
}
}
// Rigid impact feedback (available iOS 13+)
func rigidImpact() {
if #available(iOS 13.0, *) {
impact(style: .rigid)
}
}
// Success notification feedback
func successNotification() {
notification(type: .success)
}
// Warning notification feedback
func warningNotification() {
notification(type: .warning)
}
// Error notification feedback
func errorNotification() {
notification(type: .error)
}
// Simple selection feedback
func simpleSelection() {
selection()
}
}

View File

@@ -26,7 +26,6 @@ class KaraokeListingVC: UIViewController {
@IBOutlet weak var karaokeListingTableView: UITableView!
@IBOutlet weak var tableHeight: NSLayoutConstraint!
@IBOutlet weak var loadMoreBtn: LocalisedElementsButton!
@IBOutlet weak var loadMoreActivityIndicator: UIActivityIndicatorView!
var vm = KaraokeListingVM()
@@ -85,26 +84,32 @@ class KaraokeListingVC: UIViewController {
}
}
@IBAction func loadMoreBtnTapped(_ sender: LocalisedElementsButton) {
PersistentStorage.shared.addOthersCount()
if CheckReachability.reachability?.isReachable == false{
self.toast(msg: K.ConstantString.noInternet , time: 2)
return
}
loadMoreBtn.isHidden = true
vm.pageNo += 1
loadMoreActivityIndicator.startAnimating()
vm.getKaraokeListing(isBtnClick: true)
}
// @IBAction func loadMoreBtnTapped(_ sender: LocalisedElementsButton) {
// PersistentStorage.shared.addOthersCount()
// if CheckReachability.reachability?.isReachable == false{
// self.toast(msg: K.ConstantString.noInternet , time: 2)
// return
// }
// loadMoreBtn.isHidden = true
// vm.pageNo += 1
// loadMoreActivityIndicator.startAnimating()
// vm.getKaraokeListing(isBtnClick: true)
// }
@IBAction func singBtnTapped(_ sender: LocalisedElementsButton) {
/*
MAke logic for ads
*/
if let adsData = AuthFunc.shareInstance.adsData{
if let adsData = AuthFunc.shareInstance.adsData, let karaokeAd = adsData.result?.filter({$0.slug == AdsEnum.karaoke.rawValue}).first{
// check if ads data contains ad for webseries
if let karaokeAd = adsData.result?.filter({$0.slug == AdsEnum.karaoke.rawValue}).first, let adLink = karaokeAd.advertisement?.adLink, let adID = karaokeAd.advertisement?.id{
// URL maybe null so handle it
if karaokeAd.advertisement?.isActive == "1" && karaokeAd.advertisement?.adLink == nil{
// it means local ad is active and url is null
return
}
if let adLink = karaokeAd.advertisement?.adLink, let adID = karaokeAd.advertisement?.id{
PersistentStorage.shared.addAdsCount(adID: adID ,clicks: 1)
if let url = URL(string: adLink), UIApplication.shared.canOpenURL(url) {
@@ -399,5 +404,26 @@ extension KaraokeListingVC: UIScrollViewDelegate {
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
// dont do network call if the showdata count is same as the total count provided by api
// also check if already the api call is done
if vm.karaokeListData.count == vm.totalDataCount || vm.isKaraokeDataLoading == true {return}
let contentHeight = scrollView.contentSize.height
let height = scrollView.frame.size.height
// Check if the user scrolled to the bottom
if y > contentHeight - height - 50{
// check if internet is available
if CheckReachability.reachability?.isReachable == false{
return
}
//start the acitvity indicator
loadMoreActivityIndicator.startAnimating()
vm.isKaraokeDataLoading = true
vm.getKaraokeListing(isBtnClick: true)
}
}
}

View File

@@ -106,7 +106,7 @@
<rect key="frame" x="0.0" y="116" width="414" height="532"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="15" translatesAutoresizingMaskIntoConstraints="NO" id="WYB-AZ-whM">
<rect key="frame" x="0.0" y="0.0" width="414" height="105"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="75"/>
<subviews>
<stackView hidden="YES" opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="CKh-Ui-Z3R">
<rect key="frame" x="10" y="-270" width="394" height="270"/>
@@ -158,32 +158,10 @@
</subviews>
</stackView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="za1-RR-su2">
<rect key="frame" x="10" y="55" width="394" height="50"/>
<rect key="frame" x="10" y="55" width="394" height="20"/>
<subviews>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ims-Sc-C3R" customClass="LocalisedElementsButton" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="119.5" y="0.0" width="155" height="50"/>
<color key="backgroundColor" red="0.36862745098039218" green="0.12156862745098039" blue="0.76862745098039209" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="1b8-Iq-uIU"/>
<constraint firstAttribute="width" constant="155" id="l1r-Rg-TRh"/>
</constraints>
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="18"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<inset key="titleEdgeInsets" minX="5" minY="0.0" maxX="0.0" maxY="0.0"/>
<inset key="imageEdgeInsets" minX="-10" minY="0.0" maxX="10" maxY="0.0"/>
<state key="normal" title="LOAD MORE"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
<integer key="value" value="25"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<connections>
<action selector="loadMoreBtnTapped:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="jtf-4I-BTn"/>
<action selector="playNowBtnTapped:" destination="fax-bi-Mb9" eventType="touchUpInside" id="bu2-m8-dfO"/>
</connections>
</button>
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="medium" translatesAutoresizingMaskIntoConstraints="NO" id="OhD-ec-2sW">
<rect key="frame" x="172" y="0.0" width="50" height="50"/>
<rect key="frame" x="187" y="0.0" width="20" height="20"/>
<constraints>
<constraint firstAttribute="width" secondItem="OhD-ec-2sW" secondAttribute="height" multiplier="1:1" id="dva-fK-OUW"/>
</constraints>
@@ -192,10 +170,7 @@
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="ims-Sc-C3R" firstAttribute="top" secondItem="za1-RR-su2" secondAttribute="top" id="0AM-fH-QEM"/>
<constraint firstItem="OhD-ec-2sW" firstAttribute="centerX" secondItem="za1-RR-su2" secondAttribute="centerX" id="REE-mu-rcw"/>
<constraint firstAttribute="bottom" secondItem="ims-Sc-C3R" secondAttribute="bottom" id="dMT-GX-v3Z"/>
<constraint firstItem="ims-Sc-C3R" firstAttribute="centerX" secondItem="za1-RR-su2" secondAttribute="centerX" id="iBj-MG-25D"/>
<constraint firstAttribute="bottom" secondItem="OhD-ec-2sW" secondAttribute="bottom" id="tIx-Ac-OrU"/>
<constraint firstItem="OhD-ec-2sW" firstAttribute="top" secondItem="za1-RR-su2" secondAttribute="top" id="xlJ-jO-zbq"/>
</constraints>
@@ -288,7 +263,6 @@
<outlet property="headerViewLabelHeight" destination="Dm6-9O-x7v" id="chh-we-0BP"/>
<outlet property="karaokeListingTableView" destination="haV-Gw-hD2" id="1En-mN-yVg"/>
<outlet property="loadMoreActivityIndicator" destination="OhD-ec-2sW" id="yfU-R6-UbS"/>
<outlet property="loadMoreBtn" destination="ims-Sc-C3R" id="WEX-0M-lBp"/>
<outlet property="noDataStack" destination="mxw-ad-FKZ" id="HNo-RJ-uiw"/>
<outlet property="scrollView" destination="5mW-wO-b1Z" id="vX8-Dp-fHu"/>
<outlet property="selectedShowView" destination="JKB-7I-uN7" id="1hm-Jj-hg2"/>

View File

@@ -17,12 +17,18 @@ class KaraokeListingVM{
var headerData : KaraokeListingDM.KaraokeDatum?
// PAgination variables
var pageNo = 0
var isKaraokeDataLoading = false
var totalDataCount = 0 // this will hold the total count from api
var maxHeaderHeight = 0.0
var headerBannerView = GADBannerView()
var headerBannerBottomView = GADBannerView()
let feedbackGenerator = UIImpactFeedbackGenerator(style: .rigid)
func initView(){
setupCell()
vc.scrollView.indicatorStyle = .white // or .white
@@ -168,6 +174,7 @@ class KaraokeListingVM{
switch result{
case .success(let data):
guard let self else{
self?.isKaraokeDataLoading = false
return
}
switch data.success{
@@ -175,13 +182,23 @@ class KaraokeListingVM{
/*
Error
*/
self.vc.loadMoreBtn.isHidden = true
self.isKaraokeDataLoading = false
self.vc.loadMoreActivityIndicator.stopAnimating()
self.vc.loadMoreActivityIndicator.hidesWhenStopped = true
// vc.toast(msg: data.message ?? "Unrecognised error" , time: 2)
case 1:
getContinueWatching()
if !isBtnClick{
getContinueWatching()
feedbackGenerator.impactOccurred()
}
self.isKaraokeDataLoading = false
self.pageNo += 1
guard let dataCount = data.data?.totalRecords, let data = data.data?.karaokeData else{return}
self.totalDataCount = dataCount
self.karaokeListData.append(contentsOf: data)
self.vc.karaokeListingTableView.reloadData()
self.vc.tableHeight.constant = self.vc.karaokeListingTableView.contentSize.height + 100
@@ -197,24 +214,19 @@ class KaraokeListingVM{
self.setHeaderData()
}
}
self.vc.loadMoreActivityIndicator.stopAnimating()
self.vc.loadMoreActivityIndicator.hidesWhenStopped = true
if self.karaokeListData.count == dataCount{
self.vc.loadMoreBtn.isHidden = true
}else{
self.vc.loadMoreBtn.isHidden = false
}
default:
break
self.isKaraokeDataLoading = false
}
case .failure(let error):
guard let self else{
self?.isKaraokeDataLoading = false
return
}
self.stopShimmer()
self.isKaraokeDataLoading = false
vc.toast(msg: error.localizedDescription , time: 2)
vc.noDataStack.isHidden = false
}

View File

@@ -95,9 +95,16 @@ extension ShopListingVC : TableViewSRC{
MAke logic for ads
*/
if vm.superCatData[indexPath.row].isAD == true{
if let adsData = AuthFunc.shareInstance.adsData{
if let adsData = AuthFunc.shareInstance.adsData, let shopSuperCatAd = adsData.result?.filter({$0.slug == AdsEnum.shop_super_category.rawValue}).first{
// URL maybe null so handle it
if shopSuperCatAd.advertisement?.isActive == "1" && shopSuperCatAd.advertisement?.adLink == nil{
// it means local ad is active and url is null
return
}
// check if ads data contains ad for webseries
if let shopSuperCatAd = adsData.result?.filter({$0.slug == AdsEnum.shop_super_category.rawValue}).first,let adLink = shopSuperCatAd.advertisement?.adLink, let adID = shopSuperCatAd.advertisement?.id{
if let adLink = shopSuperCatAd.advertisement?.adLink, let adID = shopSuperCatAd.advertisement?.id{
PersistentStorage.shared.addAdsCount(adID: adID,clicks: 1)
if let url = URL(string: adLink), UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url)

View File

@@ -581,16 +581,16 @@
</constraints>
</imageView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="U0W-18-4oe">
<rect key="frame" x="0.0" y="45" width="414" height="224"/>
<rect key="frame" x="0.0" y="45" width="414" height="222.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" text="Coming Soon on WOKA" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="D2p-c5-usH" customClass="LocalisedElementsLabel" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="10" y="10" width="394" height="24"/>
<rect key="frame" x="10" y="10" width="394" height="22.5"/>
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="20"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="UKc-92-GPa">
<rect key="frame" x="10" y="44" width="394" height="180"/>
<rect key="frame" x="10" y="42.5" width="394" height="180"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="MasilaComingSoon" translatesAutoresizingMaskIntoConstraints="NO" id="Kj9-jH-Y88">
<rect key="frame" x="7" y="7" width="380" height="140"/>
@@ -652,7 +652,7 @@
<edgeInsets key="layoutMargins" top="10" left="10" bottom="0.0" right="10"/>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="Qcq-yj-AzB">
<rect key="frame" x="0.0" y="269" width="414" height="209"/>
<rect key="frame" x="0.0" y="267.5" width="414" height="209"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" text="BLOGS" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lW0-W4-2hl" customClass="LocalisedElementsLabel" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="10" y="10" width="394" height="24"/>
@@ -678,7 +678,7 @@
<edgeInsets key="layoutMargins" top="10" left="10" bottom="0.0" right="10"/>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="pJu-fq-XmG">
<rect key="frame" x="0.0" y="478" width="414" height="321"/>
<rect key="frame" x="0.0" y="476.5" width="414" height="322.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" text="WOKA Songs" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FSJ-QT-rAW" customClass="LocalisedElementsLabel" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="10" y="10" width="394" height="24"/>
@@ -687,7 +687,7 @@
<nil key="highlightedColor"/>
</label>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" dataMode="prototypes" style="plain" separatorStyle="none" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="-1" estimatedSectionHeaderHeight="-1" sectionFooterHeight="-1" estimatedSectionFooterHeight="-1" translatesAutoresizingMaskIntoConstraints="NO" id="31Z-fz-1ec">
<rect key="frame" x="10" y="44" width="394" height="277"/>
<rect key="frame" x="10" y="44" width="394" height="278.5"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</tableView>
</subviews>
@@ -696,7 +696,7 @@
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="7bh-PD-sIH">
<rect key="frame" x="164.5" y="441" width="85" height="20"/>
<rect key="frame" x="164.5" y="439.5" width="85" height="20"/>
<subviews>
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="medium" translatesAutoresizingMaskIntoConstraints="NO" id="S8Q-xR-4aq">
<rect key="frame" x="0.0" y="0.0" width="85" height="20"/>
@@ -727,7 +727,7 @@
</constraints>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="xv5-81-JIV">
<rect key="frame" x="164.5" y="708.5" width="85" height="20"/>
<rect key="frame" x="164.5" y="708" width="85" height="20"/>
<subviews>
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="medium" translatesAutoresizingMaskIntoConstraints="NO" id="dLn-zw-LM2">
<rect key="frame" x="0.0" y="0.0" width="85" height="20"/>

View File

@@ -32,6 +32,18 @@ class UserNotificationVM{
refreshControl.addTarget(self, action: #selector(self.refresh(_:)), for: .valueChanged)
vc.tableView.addSubview(refreshControl)
checkAds()
}
func setupCell(){
vc.tableView.register(UINib(nibName: K.CellIdentifier.Home.userNotificationCell, bundle: nil), forCellReuseIdentifier: K.CellIdentifier.Home.userNotificationCell)
vc.tableView.delegate = vc.self
vc.tableView.dataSource = vc.self
}
// MARK: - Adss check
func checkAds(){
/*
First check if webSeries ad is present via slug, then check for Local Ads, if not then check google ads.
*/
@@ -49,6 +61,8 @@ class UserNotificationVM{
}else{
let height = UIScreen.main.bounds.width * 0.192
vc.adViewHeight.constant = height
vc.adView.alpha = 0
vc.adView.isHidden = false
// Set the image you want to display
imageView.imageURL(bannerImage, color: .white)
@@ -81,43 +95,6 @@ class UserNotificationVM{
}
}
}
//
// let height = UIScreen.main.bounds.width * 0.192
// vc.adViewHeight.constant = height
// vc.adView.alpha = 0
// let imageView = UIImageView()
//
// // Set the image you want to display
// imageView.imageURL(bannerImage, color: .white)
//
// // Enable auto-layout
// imageView.translatesAutoresizingMaskIntoConstraints = false
//
// // Add the UIImageView to the view
// vc.adView.addSubview(imageView)
//
// // Set UIImageView to match the size of the parent UIView
// NSLayoutConstraint.activate([
// imageView.leadingAnchor.constraint(equalTo: vc.adView.leadingAnchor),
// imageView.trailingAnchor.constraint(equalTo: vc.adView.trailingAnchor),
// imageView.topAnchor.constraint(equalTo: vc.adView.topAnchor),
// imageView.bottomAnchor.constraint(equalTo: vc.adView.bottomAnchor)
// ])
// imageView.contentMode = .scaleAspectFit
// UIView.animate(withDuration: 0.2, animations: { [weak self] in
// guard let self else{return}
// vc.adView.alpha = 1
// vc.adView.isHidden = false
// })
//
// vc.adView.addTapGesture {
// if let adID = notificatonAd.id{
// PersistentStorage.shared.addAdsCount(adID: adID ,clicks: 1)
// }
// if let adLink = notificatonAd.advertisement?.adLink ,let url = URL(string: adLink), UIApplication.shared.canOpenURL(url) {
// UIApplication.shared.open(url)
// }
// }
}else if notificatonAd.googleAd != nil{
/*
Show google ads with dispatch queue.
@@ -129,12 +106,7 @@ class UserNotificationVM{
}
}
}
func setupCell(){
vc.tableView.register(UINib(nibName: K.CellIdentifier.Home.userNotificationCell, bundle: nil), forCellReuseIdentifier: K.CellIdentifier.Home.userNotificationCell)
vc.tableView.delegate = vc.self
vc.tableView.dataSource = vc.self
}
// MARK: - Pull to refresh

View File

@@ -41,7 +41,7 @@ class WebSeriesSeasonVC: UIViewController {
@IBOutlet weak var shareView: UIView!
@IBOutlet weak var likeView: UIView!
@IBOutlet weak var loadMoreBtn: LocalisedElementsButton!
// @IBOutlet weak var loadMoreBtn: LocalisedElementsButton!
@IBOutlet weak var loadMoreActivityIndicator: UIActivityIndicatorView!
@IBOutlet weak var scrollView: UIScrollView!
@@ -113,17 +113,17 @@ class WebSeriesSeasonVC: UIViewController {
JWPlayerManager.shared.presentPlayer(from: self, playerItems: playerItems, startIndex: 0, contentType: .trailer, videoIDs: [0])
}
@IBAction func loadMoreBtnTapped(_ sender: LocalisedElementsButton) {
PersistentStorage.shared.addOthersCount()
if CheckReachability.reachability?.isReachable == false{
self.toast(msg: K.ConstantString.noInternet , time: 2)
return
}
loadMoreBtn.isHidden = true
vm.pageNo += 1
loadMoreActivityIndicator.startAnimating()
vm.getSeasonEpisode()
}
// @IBAction func loadMoreBtnTapped(_ sender: LocalisedElementsButton) {
// PersistentStorage.shared.addOthersCount()
// if CheckReachability.reachability?.isReachable == false{
// self.toast(msg: K.ConstantString.noInternet , time: 2)
// return
// }
// loadMoreBtn.isHidden = true
// vm.pageNo += 1
// loadMoreActivityIndicator.startAnimating()
// vm.getSeasonEpisode()
// }
@IBAction func retryBtnTapped(_ sender: LocalisedElementsButton) {
vm.getSeasonListing()
@@ -389,5 +389,34 @@ extension WebSeriesSeasonVC : UICollectionViewDelegateFlowLayout{
let cellWidth = textWidth + padding
return CGSize(width: cellWidth , height: 60)
}
}
extension WebSeriesSeasonVC : UIScrollViewDelegate{
// MARK: - UIScrollViewDelegate
func scrollViewDidScroll(_ scrollView: UIScrollView) {
// dont do network call if the showdata count is same as the total count provided by api
// also check if already the api call is done
if vm.seasonEpisodeData.count == vm.totalDataCount || vm.isShowDataLoading == true {return}
if vm.seasonEpisodeData.count == 0{ // this means no data was fetched before for season episodes
return
}
// Check if the user scrolled to the bottom
let offsetY = scrollView.contentOffset.y
let contentHeight = scrollView.contentSize.height
let height = scrollView.frame.size.height
if offsetY > contentHeight - height {
// check if internet is available
if CheckReachability.reachability?.isReachable == false{
return
}
//start the acitvity indicator
loadMoreActivityIndicator.startAnimating()
vm.isShowDataLoading = true
vm.getSeasonEpisode()
}
}
}

View File

@@ -39,7 +39,7 @@ class WebSeriesVC: UIViewController {
@IBOutlet weak var continueWatchingStack: UIStackView!
@IBOutlet weak var noDataView: UIView!
@IBOutlet weak var loadMoreBtn: LocalisedElementsButton!
// @IBOutlet weak var loadMoreBtn: LocalisedElementsButton!
@IBOutlet weak var loadMoreActivityIndicator: UIActivityIndicatorView!
var vm = WebSeriesVM()
@@ -114,6 +114,13 @@ class WebSeriesVC: UIViewController {
//If its ads then nav user to webview
if let adsData = AuthFunc.shareInstance.adsData, let webSeriesAd = adsData.result?.filter({$0.slug == AdsEnum.web_series.rawValue}).first{
// URL maybe null so handle it
if webSeriesAd.advertisement?.isActive == "1" && webSeriesAd.advertisement?.adLink == nil{
// it means local ad is active and url is null
return
}
// check if ads data contains ad for webseries
if let adLink = webSeriesAd.advertisement?.adLink,let adID = webSeriesAd.advertisement?.id{
PersistentStorage.shared.addAdsCount(adID: adID ,clicks: 1)
@@ -135,20 +142,20 @@ class WebSeriesVC: UIViewController {
self.expandBtn.setImage(UIImage(named: "SupportUpArrow"), for: .normal)
}
@IBAction func loadMoreBtnTapped(_ sender: LocalisedElementsButton) {
PersistentStorage.shared.addOthersCount()
if CheckReachability.reachability?.isReachable == false{
self.toast(msg: K.ConstantString.noInternet , time: 2)
return
}
loadMoreBtn.isHidden = true
vm.pageNo += 1
loadMoreActivityIndicator.startAnimating()
if let index = vm.dropDownModule.indexForSelectedRow, let categoryIndex = vm.categoryListingData[index].id{
vm.getShowListing(categoryID: categoryIndex, isBtnClick: true)
}
// @IBAction func loadMoreBtnTapped(_ sender: LocalisedElementsButton) {
// PersistentStorage.shared.addOthersCount()
}
// if CheckReachability.reachability?.isReachable == false{
// self.toast(msg: K.ConstantString.noInternet , time: 2)
// return
// }
// loadMoreBtn.isHidden = true
// vm.pageNo += 1
// loadMoreActivityIndicator.startAnimating()
// if let index = vm.dropDownModule.indexForSelectedRow, let categoryIndex = vm.categoryListingData[index].id{
// vm.getShowListing(categoryID: categoryIndex, isBtnClick: true)
// }
//// PersistentStorage.shared.addOthersCount()
// }
@IBAction func retryBtnTapped(_ sender: LocalisedElementsButton) {
PersistentStorage.shared.addOthersCount()
@@ -167,7 +174,7 @@ class WebSeriesVC: UIViewController {
// MARK: - TableView DataSource , Delegates
extension WebSeriesVC : TableViewSRC{
extension WebSeriesVC : TableViewSRC {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return vm.showData.count == 0 ? 2 : vm.showData.count
@@ -510,6 +517,31 @@ extension WebSeriesVC: UIScrollViewDelegate {
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
let contentHeight = scrollView.contentSize.height
let height = scrollView.frame.size.height
// dont do network call if the showdata count is same as the total count provided by api
// also check if already the api call is done
if vm.showData.count == vm.totalDataCount || vm.isShowDataLoading == true {return}
// Check if the user scrolled to the bottom
if y > contentHeight - height * 1.6{
// check if internet is available
if CheckReachability.reachability?.isReachable == false{
return
}
//start the acitvity indicator
loadMoreActivityIndicator.startAnimating()
// get the category index and do the network call
if let index = vm.dropDownModule.indexForSelectedRow, let categoryIndex = vm.categoryListingData[index].id{
vm.isShowDataLoading = true
vm.getShowListing(categoryID: categoryIndex, isBtnClick: true)
}
}
}
}

View File

@@ -25,9 +25,15 @@ class WebSeriesSeasonVM{
var showData : WebSeriesShowListDM.ShowDatum?
var indexSelected : Int?
// PAgination variables
var pageNo = 0
var totalDataCount = 0 // this will hold the total count from api
var isShowDataLoading = false // if true means api is being called.
let feedbackGenerator = UIImpactFeedbackGenerator(style: .rigid)
func initView(){
vc.scrollView.delegate = self.vc
let color1 = #colorLiteral(red: 0.5921568627, green: 0.2588235294, blue: 0.8941176471, alpha: 1)
let color2 = #colorLiteral(red: 0.368627451, green: 0.1215686275, blue: 0.768627451, alpha: 1)
self.vc.view.applyGradient(colors: [color1,color2], startPoint: .Point.left.point , endPoint: .Point.right.point)
@@ -44,7 +50,7 @@ class WebSeriesSeasonVM{
guard let self ,let indexSelected, let categoryID, let showData, let showID = showData.id, let isFav = showData.markAsFavourite, let postType = showData.contentMoreDetails?.first?.postType else{return}
PersistentStorage.shared.addWebSeries(catID: categoryID, postID: showID, postType: .series)
HapticFeedbackGenerator.shared.lightImpact()
if isFav {
//remove
LikeFavCommonFunc.shareInstance.removeFavourite(postID: showID, postType: postType, categoryID: categoryID, vc: self.vc) { isDone in
@@ -82,18 +88,7 @@ class WebSeriesSeasonVM{
//For updating mylist allview
K.GVar.reloadMyListAll = 1
K.GVar.reloadMyListAllID = showID
// if self.categoryID == 18{ // hindi
// guard let showData = self.showData else{return}
// MyListDataTemp.shareInstance.favListingData?.showData?.hindi?.append(FavouriteListingDM.ResultData.ShowDatum(id: showData.id, title: showData.title, description: showData.description, thumbnailPath: showData.thumbnailPath, showType: showData.showType, totalSeasons: showData.totalSeasons, totalEpisodes: showData.totalEpisodes, ageRangeMasterID: showData.ageRangeMasterID, genderMasterID: showData.genderMasterID, categoryMasterID: self.categoryID?.toString(), contentMoreDetails: showData.contentMoreDetails, markAsFavourite: showData.markAsFavourite, isLiked: showData.isLiked, likesCount: showData.likesCount, viewsCount: showData.viewsCount, bookmarkCount: showData.bookmarkCount, bookmarkCategoryIDS: "18"))
// K.GVar.myListSoftReload = true
// }else{ // english
// guard let showData = self.showData else{return}
// if MyListDataTemp.shareInstance.favListingData?.showData == nil {
// MyListDataTemp.shareInstance.favListingData?.showData = []
// }
// MyListDataTemp.shareInstance.favListingData?.showData?.append(FavouriteListingDM.ResultData.ShowDatum(id: showData.id, title: showData.title, description: showData.description, thumbnailPath: showData.thumbnailPath, showType: showData.showType, totalSeasons: showData.totalSeasons, totalEpisodes: showData.totalEpisodes, ageRangeMasterID: showData.ageRangeMasterID, genderMasterID: showData.genderMasterID, categoryMasterID: self.categoryID?.toString(), contentMoreDetails: showData.contentMoreDetails, markAsFavourite: showData.markAsFavourite, isLiked: showData.isLiked, likesCount: showData.likesCount, viewsCount: showData.viewsCount, bookmarkCount: showData.bookmarkCount, bookmarkCategoryIDS: "1"))
// K.GVar.myListSoftReload = true
// }
}
}
}
@@ -103,7 +98,7 @@ class WebSeriesSeasonVM{
guard let self ,let indexSelected, let showData, let showID = showData.id, let isLiked = showData.isLiked, let postType = showData.contentMoreDetails?.first?.postType else{return}
PersistentStorage.shared.addWebSeries(catID: self.categoryID ?? 0, postID: showID, postType: .series)
HapticFeedbackGenerator.shared.lightImpact()
if isLiked{
LikeFavCommonFunc.shareInstance.unlikePost(postID: showID, postType: postType, vc: self.vc) { isDone in
self.showData?.isLiked = false
@@ -303,7 +298,6 @@ class WebSeriesSeasonVM{
}
func getSeasonEpisode(){
guard let watchShowID = showData?.id, let episodeSelectedCateogory else{return}
let headers : HTTPHeaders = ["access-token" : AuthFunc.shareInstance.getAccessToken()]
let params : Parameters = ["watch_show_master_id" : watchShowID,
@@ -311,11 +305,13 @@ class WebSeriesSeasonVM{
"api_version" : "v2",
"start" : pageNo,
"limit": 10]
NetworkManager.shareInstance.apiRequest(url: APIEndPoints.WebSeries.episode_listing, method: .post,parameters: params,headers : headers) { [weak self](result : Result<BaseResponseModel<EpisodeListingDM>, NetworkManager.APIError>) in
switch result{
case .success(let data):
guard let self else{
Utilities.dismissProgressHUD()
self?.isShowDataLoading = false
return
}
switch data.success{
@@ -324,34 +320,39 @@ class WebSeriesSeasonVM{
Error
*/
Utilities.dismissProgressHUD()
self.isShowDataLoading = false
if pageNo == 0 {
self.seasonEpisodeData.removeAll()
}
self.vc.episodeTableView.reloadData()
self.vc.tableHeight.constant = self.vc.episodeTableView.contentSize.height + 100
self.vc.episodeTableView.layoutIfNeeded()
self.vc.tableHeight.constant = self.vc.episodeTableView.contentSize.height
// vc.toast(msg: data.message ?? "Unrecognised error" , time: 2)
case 1:
Utilities.dismissProgressHUD()
guard let dataCount = data.data?.totalRecords ,let data = data.data?.result else{return}
if pageNo == 0 {
self.seasonEpisodeData.removeAll()
}
self.seasonEpisodeData.append(contentsOf: data)
// self.seasonEpisodeData = self.seasonEpisodeData.filter {
// $0.episodeData != nil && !$0.episodeData!.isEmpty
// }
self.vc.loadMoreActivityIndicator.stopAnimating()
self.vc.loadMoreActivityIndicator.hidesWhenStopped = true
// vc.toast(msg: data.message ?? "Unrecognised error" , time: 2)
case 1:
Utilities.dismissProgressHUD()
self.isShowDataLoading = false
guard let dataCount = data.data?.totalRecords ,let data = data.data?.result else{return}
if self.seasonEpisodeData.count == dataCount{
self.vc.loadMoreBtn.isHidden = true
}else{
self.vc.loadMoreBtn.isHidden = false
//Initialize total data count.
self.totalDataCount = dataCount
// page number
if pageNo == 0 {
feedbackGenerator.impactOccurred()
self.seasonEpisodeData.removeAll()
}
pageNo += 1
self.seasonEpisodeData.append(contentsOf: data)
self.vc.loadMoreActivityIndicator.stopAnimating()
self.vc.loadMoreActivityIndicator.hidesWhenStopped = true
if self.seasonEpisodeData.count == 0{
self.vc.episodeTitle.isHidden = true
@@ -370,19 +371,16 @@ class WebSeriesSeasonVM{
}
case .failure(let error):
guard let self else{
self?.isShowDataLoading = false
Utilities.dismissProgressHUD()
return
}
Utilities.dismissProgressHUD()
self.isShowDataLoading = false
vc.toast(msg: error.localizedDescription , time: 2)
self.vc.loadMoreActivityIndicator.stopAnimating()
self.vc.loadMoreActivityIndicator.hidesWhenStopped = true
//if its not page 0 then for sure user must be loading next page and got error
if pageNo != 0{
vc.loadMoreBtn.isHidden = true
}
}
}
}
@@ -412,6 +410,7 @@ class WebSeriesSeasonVM{
case 1:
Utilities.dismissProgressHUD()
guard let data = data.data?.result else{return}
HapticFeedbackGenerator.shared.rigidImpact()
self.teaserData.removeAll()
self.teaserData = data
self.reloadTeaserTable()

View File

@@ -19,19 +19,18 @@ class WebSeriesVM{
let dropDownModule = DropDown()
var dataSource = [String]()
// var tempCount = 2
//Static url for masila
//// var masilaUrl = "https://content.jwplatform.com/videos/Iygt11AD-Ysj2G4DQ.mp4"
// var masilaUrl = "https://cdn.jwplayer.com/manifests/Iygt11AD.m3u8"
// PAgination variables
var pageNo = 0
var stopFetch = false
var isShowDataLoading = false
var totalDataCount = 0 // this will hold the total count from api
var maxHeaderHeight = 0.0
var headerBannerView = GADBannerView()
var masilaBannerView = GADBannerView()
let feedbackGenerator = UIImpactFeedbackGenerator(style: .rigid)
func initView(){
// let heightMultiplier: CGFloat = 0.257511
@@ -223,16 +222,17 @@ class WebSeriesVM{
}
func getShowListing(categoryID : Int, isBtnClick : Bool = false, languageChange : Bool = false){
// Utilities.startProgressHUD()
let headers : HTTPHeaders = ["access-token" : AuthFunc.shareInstance.getAccessToken()]
let params : Parameters = ["category_id" : categoryID,
"api_version" : "v2",
"start" : pageNo,
"start" : pageNo, // if page no is 0 then its the first page, if not the increase it by one
"limit": 6] // from category listing api , default will be 1
NetworkManager.shareInstance.apiRequest(url: APIEndPoints.WebSeries.watch_show_listing, method: .post,parameters: params,headers: headers, queue: QueueHelper.utilityGroup) { [weak self](result : Result<BaseResponseModel<WebSeriesShowListDM>, NetworkManager.APIError>) in
NetworkManager.shareInstance.apiRequest(url: APIEndPoints.WebSeries.watch_show_listing, method: .post,parameters: params,headers: headers, queue: QueueHelper.utilityGroup) { [weak self] (result : Result<BaseResponseModel<WebSeriesShowListDM>, NetworkManager.APIError>) in
switch result{
case .success(let data):
guard let self else{
self?.isShowDataLoading = false
Utilities.dismissProgressHUD()
return
}
@@ -242,10 +242,20 @@ class WebSeriesVM{
Error
*/
Utilities.dismissProgressHUD()
self.isShowDataLoading = false
vc.toast(msg: data.message ?? "Unrecognised error" , time: 2)
case 1:
Utilities.dismissProgressHUD()
self.isShowDataLoading = false
guard let dataCount = data.data?.totalRecords , let data = data.data?.showData else{return}
//update the total data count on success.
totalDataCount = dataCount
//update the page no on success
pageNo += 1
//if user changes language from dropdown
if languageChange{
self.showData.removeAll()
self.showData.append(contentsOf: data)
@@ -253,31 +263,33 @@ class WebSeriesVM{
self.showData.append(contentsOf: data)
}
//stop the shimmer, enable the scrollview scroll, increase the table height inside the scrollview.
self.stopShimmer()
self.vc.scrollView.isScrollEnabled = true
self.vc.showListingTableView.reloadData()
self.vc.tableHeight.constant = self.vc.showListingTableView.contentSize.height + 100
if !isBtnClick{
feedbackGenerator.impactOccurred()
self.vc.tableHeight.constant = self.vc.showListingTableView.contentSize.height + 100
}
self.vc.showListingTableView.layoutIfNeeded()
self.vc.tableHeight.constant = self.vc.showListingTableView.contentSize.height
//stop activity indicator and hide it when stopped
self.vc.loadMoreActivityIndicator.stopAnimating()
self.vc.loadMoreActivityIndicator.hidesWhenStopped = true
if self.showData.count == dataCount{
self.vc.loadMoreBtn.isHidden = true
}else{
self.vc.loadMoreBtn.isHidden = false
}
default:
break
}
case .failure(let error):
guard let self else{
self?.isShowDataLoading = false
Utilities.dismissProgressHUD()
return
}
Utilities.dismissProgressHUD()
self.isShowDataLoading = false
vc.toast(msg: error.localizedDescription , time: K.ConstantString.errorTime)
}
}

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23094" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_72" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22685"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23084"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
@@ -102,7 +102,7 @@
<rect key="frame" x="0.0" y="116" width="430" height="517"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="15" translatesAutoresizingMaskIntoConstraints="NO" id="c6v-VU-iKP">
<rect key="frame" x="0.0" y="0.0" width="430" height="170"/>
<rect key="frame" x="0.0" y="0.0" width="430" height="140"/>
<subviews>
<stackView hidden="YES" opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="mFz-UO-YUA">
<rect key="frame" x="10" y="-270" width="410" height="270"/>
@@ -207,31 +207,10 @@
</constraints>
</tableView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uJQ-Z1-n44">
<rect key="frame" x="10" y="120" width="410" height="50"/>
<rect key="frame" x="10" y="120" width="410" height="20"/>
<subviews>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="7ol-RU-bwy" customClass="LocalisedElementsButton" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="127.66666666666666" y="0.0" width="154.99999999999997" height="50"/>
<color key="backgroundColor" red="0.36862745099999999" green="0.1215686275" blue="0.76862745099999996" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="155" id="T89-an-q4g"/>
<constraint firstAttribute="height" constant="50" id="aPy-dy-Xxq"/>
</constraints>
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="18"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<inset key="titleEdgeInsets" minX="5" minY="0.0" maxX="0.0" maxY="0.0"/>
<inset key="imageEdgeInsets" minX="-10" minY="0.0" maxX="10" maxY="0.0"/>
<state key="normal" title="LOAD MORE"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
<integer key="value" value="25"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<connections>
<action selector="loadMoreBtnTapped:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="YrG-sY-XXq"/>
</connections>
</button>
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="medium" translatesAutoresizingMaskIntoConstraints="NO" id="eOC-qb-KNO">
<rect key="frame" x="180" y="0.0" width="50" height="50"/>
<rect key="frame" x="195" y="0.0" width="20" height="20"/>
<constraints>
<constraint firstAttribute="width" secondItem="eOC-qb-KNO" secondAttribute="height" multiplier="1:1" id="bFH-MC-10o"/>
</constraints>
@@ -240,9 +219,6 @@
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="7ol-RU-bwy" firstAttribute="top" secondItem="uJQ-Z1-n44" secondAttribute="top" id="1yB-bD-RQb"/>
<constraint firstItem="7ol-RU-bwy" firstAttribute="centerX" secondItem="uJQ-Z1-n44" secondAttribute="centerX" id="53s-T0-e7M"/>
<constraint firstAttribute="bottom" secondItem="7ol-RU-bwy" secondAttribute="bottom" id="67l-gg-0nz"/>
<constraint firstItem="eOC-qb-KNO" firstAttribute="top" secondItem="uJQ-Z1-n44" secondAttribute="top" id="Hap-dx-ulP"/>
<constraint firstItem="eOC-qb-KNO" firstAttribute="centerX" secondItem="uJQ-Z1-n44" secondAttribute="centerX" id="o0q-8i-Nfa"/>
<constraint firstAttribute="bottom" secondItem="eOC-qb-KNO" secondAttribute="bottom" id="poC-B3-ai9"/>
@@ -339,7 +315,6 @@
<outlet property="languageLabel" destination="Exa-2W-66W" id="e7q-aD-laV"/>
<outlet property="languageStack" destination="yFH-vA-sul" id="pBj-Ph-i57"/>
<outlet property="loadMoreActivityIndicator" destination="eOC-qb-KNO" id="wjE-aj-J2d"/>
<outlet property="loadMoreBtn" destination="7ol-RU-bwy" id="slu-Zm-hE1"/>
<outlet property="masilaTrailerView" destination="Cog-DZ-ib0" id="IMd-wS-yNh"/>
<outlet property="noDataView" destination="gY9-3R-0TH" id="Faz-ba-PbN"/>
<outlet property="scrollView" destination="rom-H6-7RC" id="8bD-vg-lG2"/>
@@ -365,7 +340,7 @@
<rect key="frame" x="0.0" y="59" width="430" height="873"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="JVZ-ee-mig">
<rect key="frame" x="0.0" y="0.0" width="430" height="693"/>
<rect key="frame" x="0.0" y="0.0" width="430" height="663"/>
<subviews>
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8zm-IG-hTk">
<rect key="frame" x="0.0" y="0.0" width="430" height="553"/>
@@ -476,7 +451,7 @@
<rect key="frame" x="377.66666666666669" y="0.0" width="32.333333333333314" height="49"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="hand.thumbsup.fill" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="eng-oC-d9H">
<rect key="frame" x="0.0" y="0.66666666666666785" width="20" height="47.666666666666671"/>
<rect key="frame" x="0.0" y="0.66666666666666785" width="20" height="47.666666666666657"/>
<color key="tintColor" red="0.035294117649999998" green="0.0" blue="0.36470588240000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Egv-Cu-aPK">
@@ -739,32 +714,10 @@
</subviews>
</stackView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sFz-dF-Xbi">
<rect key="frame" x="0.0" y="643" width="430" height="50"/>
<rect key="frame" x="0.0" y="643" width="430" height="20"/>
<subviews>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ORc-ik-Kgr" customClass="LocalisedElementsButton" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="137.66666666666666" y="0.0" width="154.99999999999997" height="50"/>
<color key="backgroundColor" red="0.36862745099999999" green="0.1215686275" blue="0.76862745099999996" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="Du6-Wu-tRD"/>
<constraint firstAttribute="width" constant="155" id="jJQ-Tq-7d8"/>
</constraints>
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="18"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<inset key="titleEdgeInsets" minX="5" minY="0.0" maxX="0.0" maxY="0.0"/>
<inset key="imageEdgeInsets" minX="-10" minY="0.0" maxX="10" maxY="0.0"/>
<state key="normal" title="LOAD MORE"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
<integer key="value" value="25"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<connections>
<action selector="loadMoreBtnTapped:" destination="sPj-Um-9Xm" eventType="touchUpInside" id="4yV-hI-9Un"/>
<action selector="loadMoreBtnTapped:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="vFQ-zS-GIg"/>
</connections>
</button>
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="medium" translatesAutoresizingMaskIntoConstraints="NO" id="eSs-vC-anB">
<rect key="frame" x="190" y="0.0" width="50" height="50"/>
<rect key="frame" x="205" y="0.0" width="20" height="20"/>
<constraints>
<constraint firstAttribute="width" secondItem="eSs-vC-anB" secondAttribute="height" multiplier="1:1" id="2gV-30-mFk"/>
</constraints>
@@ -773,11 +726,8 @@
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="ORc-ik-Kgr" secondAttribute="bottom" id="So4-mi-YSn"/>
<constraint firstAttribute="bottom" secondItem="eSs-vC-anB" secondAttribute="bottom" id="WX7-wR-0Ls"/>
<constraint firstItem="ORc-ik-Kgr" firstAttribute="centerX" secondItem="sFz-dF-Xbi" secondAttribute="centerX" id="Yn3-GL-Dca"/>
<constraint firstItem="eSs-vC-anB" firstAttribute="centerX" secondItem="sFz-dF-Xbi" secondAttribute="centerX" id="hW2-ZM-F1P"/>
<constraint firstItem="ORc-ik-Kgr" firstAttribute="top" secondItem="sFz-dF-Xbi" secondAttribute="top" id="oY6-iY-j53"/>
<constraint firstItem="eSs-vC-anB" firstAttribute="top" secondItem="sFz-dF-Xbi" secondAttribute="top" id="sgn-ME-OHx"/>
</constraints>
</view>
@@ -855,7 +805,6 @@
<outlet property="likeLabel" destination="Q4V-Gl-g6v" id="p5K-OM-Lmn"/>
<outlet property="likeView" destination="GRu-Ep-rmR" id="F5U-OH-z0d"/>
<outlet property="loadMoreActivityIndicator" destination="eSs-vC-anB" id="Ehy-49-VBM"/>
<outlet property="loadMoreBtn" destination="ORc-ik-Kgr" id="8mA-Cd-TBN"/>
<outlet property="noDataStack" destination="MKx-HL-GiZ" id="VOi-TC-bfe"/>
<outlet property="scrollView" destination="Ka5-Rt-V3L" id="fhE-mL-ilt"/>
<outlet property="seasonDate" destination="3AX-wl-iqI" id="4Zq-76-ZN2"/>