- [x] Work on mylist data to be updated internally
- [x] Share functionality
This commit is contained in:
@@ -1725,6 +1725,7 @@
|
||||
9CB3D0832C37BA470062869D /* Karaoke */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9CFF27A62C5DF6BE0018C360 /* DumpFiles */,
|
||||
9CB3D0892C37BA650062869D /* Model */,
|
||||
9CB3D0882C37BA630062869D /* View */,
|
||||
9CB3D0872C37BA610062869D /* ViewModel */,
|
||||
@@ -1739,11 +1740,8 @@
|
||||
children = (
|
||||
9CB3D08A2C37BBA50062869D /* KaraokeListingVC.swift */,
|
||||
9CB3D0902C37D6930062869D /* KaraokeDetailsVC.swift */,
|
||||
9C21F81D2C37E3CA0050BFCC /* AVPlayerVC.swift */,
|
||||
52F4E8652C3D123B00778FBC /* JWKaraokePlayerVC.swift */,
|
||||
525FC61C2C3D3DC30049145D /* AVAssetMods.swift */,
|
||||
525FC65C2C3D57D80049145D /* TestingKaraokeVC.swift */,
|
||||
9C8446862C40FC6E003E3E53 /* AVPlayerTesting.swift */,
|
||||
);
|
||||
path = Controller;
|
||||
sourceTree = "<group>";
|
||||
@@ -1752,7 +1750,6 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9CB3D08C2C37CDD50062869D /* KaraokeListingVM.swift */,
|
||||
9C21F8212C382A580050BFCC /* AVPlayerVM.swift */,
|
||||
);
|
||||
path = ViewModel;
|
||||
sourceTree = "<group>";
|
||||
@@ -1844,6 +1841,17 @@
|
||||
path = Sounds;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9CFF27A62C5DF6BE0018C360 /* DumpFiles */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9C8446862C40FC6E003E3E53 /* AVPlayerTesting.swift */,
|
||||
525FC65C2C3D57D80049145D /* TestingKaraokeVC.swift */,
|
||||
9C21F81D2C37E3CA0050BFCC /* AVPlayerVC.swift */,
|
||||
9C21F8212C382A580050BFCC /* AVPlayerVM.swift */,
|
||||
);
|
||||
path = DumpFiles;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
|
||||
@@ -581,7 +581,8 @@
|
||||
<wkWebView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pMD-fy-kTc">
|
||||
<rect key="frame" x="0.0" y="44" width="414" height="852"/>
|
||||
<color key="backgroundColor" red="0.36078431370000003" green="0.38823529410000002" blue="0.4039215686" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<wkWebViewConfiguration key="configuration">
|
||||
<wkWebViewConfiguration key="configuration" allowsAirPlayForMediaPlayback="NO" allowsPictureInPictureMediaPlayback="NO">
|
||||
<dataDetectorTypes key="dataDetectorTypes"/>
|
||||
<audiovisualMediaTypes key="mediaTypesRequiringUserActionForPlayback" none="YES"/>
|
||||
<wkPreferences key="preferences"/>
|
||||
</wkWebViewConfiguration>
|
||||
|
||||
@@ -8,24 +8,32 @@
|
||||
import UIKit
|
||||
import WebKit
|
||||
|
||||
class PaymentWebViewVC: UIViewController {
|
||||
class PaymentWebViewVC: UIViewController,WKNavigationDelegate {
|
||||
|
||||
@IBOutlet weak var webView: WKWebView!
|
||||
var url : String?
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
DispatchQueue.main.async {
|
||||
Utilities.startProgressHUD()
|
||||
}
|
||||
|
||||
if let url {
|
||||
let link = URL(string:url)!
|
||||
let request = URLRequest(url: link)
|
||||
webView.load(request)
|
||||
}
|
||||
|
||||
webView.navigationDelegate = self
|
||||
//Observer to check the url changes
|
||||
webView.addObserver(self, forKeyPath: "URL", options: .new, context: nil)
|
||||
|
||||
}
|
||||
|
||||
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
||||
Utilities.dismissProgressHUD()
|
||||
}
|
||||
|
||||
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
||||
if let key = change?[NSKeyValueChangeKey.newKey] {
|
||||
print("observeValue \(key)") // url value
|
||||
|
||||
@@ -197,7 +197,13 @@ class AudioBookDetailsVC : UIViewController{
|
||||
}
|
||||
|
||||
shareView.addTapGesture {
|
||||
print("share")
|
||||
if let name = URL(string: "https://apps.apple.com/in/app/woka/id6465305185"), !name.absoluteString.isEmpty {
|
||||
let objectsToShare = [name]
|
||||
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
|
||||
self.present(activityVC, animated: true, completion: nil)
|
||||
} else {
|
||||
// show alert for not available
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -173,7 +173,13 @@ class GamesDetailVC: UIViewController {
|
||||
}
|
||||
|
||||
shareView.addTapGesture {
|
||||
print("share")
|
||||
if let name = URL(string: "https://apps.apple.com/in/app/woka/id6465305185"), !name.absoluteString.isEmpty {
|
||||
let objectsToShare = [name]
|
||||
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
|
||||
self.present(activityVC, animated: true, completion: nil)
|
||||
} else {
|
||||
// show alert for not available
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ class ExploreWokaVC: UIViewController {
|
||||
@IBOutlet weak var shopBtn: UIButton!
|
||||
|
||||
@IBOutlet weak var layerView: UIView!
|
||||
@IBOutlet weak var bottomView: UIView!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
@@ -198,5 +199,4 @@ extension UIView{
|
||||
|
||||
shapeLayer.path = path.cgPath
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -571,10 +571,10 @@
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-181" y="979"/>
|
||||
</scene>
|
||||
<!--Item-->
|
||||
<!--ExploreWokaVC-->
|
||||
<scene sceneID="ZJ9-YU-7B1">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="ExploreWokaVC" id="wHe-qy-JF8" customClass="ExploreWokaVC" customModule="WOKA" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<viewController storyboardIdentifier="ExploreWokaVC" id="wHe-qy-JF8" userLabel="ExploreWokaVC" customClass="ExploreWokaVC" customModule="WOKA" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="HLg-jy-523">
|
||||
<rect key="frame" x="0.0" y="0.0" width="430" height="932"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
@@ -587,209 +587,236 @@
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</view>
|
||||
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="DNc-fQ-fy8">
|
||||
<rect key="frame" x="105" y="385.66666666666674" width="220" height="440"/>
|
||||
<rect key="frame" x="105" y="345.66666666666674" width="220" height="480"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="iPr-OV-7V5">
|
||||
<rect key="frame" x="0.0" y="0.0" width="220" height="440"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="220" height="480"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="c2y-F6-AqI">
|
||||
<rect key="frame" x="0.0" y="0.0" width="220" height="55"/>
|
||||
<stackView opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="jcd-sH-5aO">
|
||||
<rect key="frame" x="0.0" y="0.0" width="220" height="440"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="nOR-gr-8Ab">
|
||||
<rect key="frame" x="10" y="2" width="200" height="51"/>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="15"/>
|
||||
<inset key="titleEdgeInsets" minX="40" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<inset key="imageEdgeInsets" minX="25" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="WOKA FM" image="WokaFmIcon">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="btnTapped:" destination="wHe-qy-JF8" eventType="touchUpInside" id="aqy-Ob-ieO"/>
|
||||
</connections>
|
||||
</button>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="c2y-F6-AqI">
|
||||
<rect key="frame" x="0.0" y="0.0" width="220" height="55"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="nOR-gr-8Ab">
|
||||
<rect key="frame" x="10" y="2" width="200" height="51"/>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="15"/>
|
||||
<inset key="titleEdgeInsets" minX="40" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<inset key="imageEdgeInsets" minX="25" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="WOKA FM" image="WokaFmIcon">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="btnTapped:" destination="wHe-qy-JF8" eventType="touchUpInside" id="aqy-Ob-ieO"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.78431372549019607" green="0.70588235294117641" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="nOR-gr-8Ab" firstAttribute="leading" secondItem="c2y-F6-AqI" secondAttribute="leading" constant="10" id="0d1-gu-9JD"/>
|
||||
<constraint firstItem="nOR-gr-8Ab" firstAttribute="top" secondItem="c2y-F6-AqI" secondAttribute="top" constant="2" id="9de-7W-fKm"/>
|
||||
<constraint firstAttribute="bottom" secondItem="nOR-gr-8Ab" secondAttribute="bottom" constant="2" id="Btq-ob-Tg6"/>
|
||||
<constraint firstAttribute="height" constant="55" id="DAq-Y8-V3k"/>
|
||||
<constraint firstAttribute="trailing" secondItem="nOR-gr-8Ab" secondAttribute="trailing" constant="10" id="Vtt-FU-GZa"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="aOq-F2-okk">
|
||||
<rect key="frame" x="0.0" y="55" width="220" height="55"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="pfM-e9-xeS">
|
||||
<rect key="frame" x="10" y="2" width="200" height="51"/>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="15"/>
|
||||
<inset key="titleEdgeInsets" minX="40" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<inset key="imageEdgeInsets" minX="25" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="LIVE TV" image="LiveTvIcon">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="btnTapped:" destination="wHe-qy-JF8" eventType="touchUpInside" id="PWm-Wo-tFp"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.63529411764705879" blue="0.87058823529411766" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="pfM-e9-xeS" secondAttribute="bottom" constant="2" id="Y6l-zl-LZs"/>
|
||||
<constraint firstItem="pfM-e9-xeS" firstAttribute="top" secondItem="aOq-F2-okk" secondAttribute="top" constant="2" id="hqx-nu-Wya"/>
|
||||
<constraint firstItem="pfM-e9-xeS" firstAttribute="leading" secondItem="aOq-F2-okk" secondAttribute="leading" constant="10" id="jg1-9k-bKr"/>
|
||||
<constraint firstAttribute="height" constant="55" id="q4E-5i-tfI"/>
|
||||
<constraint firstAttribute="trailing" secondItem="pfM-e9-xeS" secondAttribute="trailing" constant="10" id="qSC-Za-YgM"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="yWe-87-bOu">
|
||||
<rect key="frame" x="0.0" y="110" width="220" height="55"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="31D-NF-WIr">
|
||||
<rect key="frame" x="10" y="2" width="200" height="51"/>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="15"/>
|
||||
<inset key="titleEdgeInsets" minX="40" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<inset key="imageEdgeInsets" minX="25" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="WEB SERIES" image="WebSeriesIcon">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="btnTapped:" destination="wHe-qy-JF8" eventType="touchUpInside" id="9DX-4s-myd"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.36862745098039218" green="0.12156862745098039" blue="0.76862745098039209" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="31D-NF-WIr" secondAttribute="bottom" constant="2" id="4eT-nj-ca1"/>
|
||||
<constraint firstItem="31D-NF-WIr" firstAttribute="leading" secondItem="yWe-87-bOu" secondAttribute="leading" constant="10" id="DUr-4P-7N1"/>
|
||||
<constraint firstAttribute="trailing" secondItem="31D-NF-WIr" secondAttribute="trailing" constant="10" id="Gdd-O8-sQw"/>
|
||||
<constraint firstItem="31D-NF-WIr" firstAttribute="top" secondItem="yWe-87-bOu" secondAttribute="top" constant="2" id="YJb-T1-Ihr"/>
|
||||
<constraint firstAttribute="height" constant="55" id="vmm-f6-Jyd"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ClJ-4O-Ne4">
|
||||
<rect key="frame" x="0.0" y="165" width="220" height="55"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="5de-tc-WUV">
|
||||
<rect key="frame" x="10" y="1.9999999999999432" width="200" height="51"/>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="15"/>
|
||||
<inset key="titleEdgeInsets" minX="40" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<inset key="imageEdgeInsets" minX="25" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="GAMES" image="GamesIcon">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="btnTapped:" destination="wHe-qy-JF8" eventType="touchUpInside" id="jmS-bS-CSO"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.95294117647058818" green="0.52549019607843139" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="5de-tc-WUV" secondAttribute="bottom" constant="2" id="7cy-18-vvS"/>
|
||||
<constraint firstItem="5de-tc-WUV" firstAttribute="leading" secondItem="ClJ-4O-Ne4" secondAttribute="leading" constant="10" id="CQL-hg-cu4"/>
|
||||
<constraint firstAttribute="height" constant="55" id="ptl-vj-caT"/>
|
||||
<constraint firstAttribute="trailing" secondItem="5de-tc-WUV" secondAttribute="trailing" constant="10" id="vCd-nc-hRo"/>
|
||||
<constraint firstItem="5de-tc-WUV" firstAttribute="top" secondItem="ClJ-4O-Ne4" secondAttribute="top" constant="2" id="xIx-hR-rzH"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="EB0-q2-d6p">
|
||||
<rect key="frame" x="0.0" y="219.99999999999994" width="220" height="55"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Zxm-AD-QSC">
|
||||
<rect key="frame" x="10" y="2" width="200" height="51"/>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="15"/>
|
||||
<inset key="titleEdgeInsets" minX="40" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<inset key="imageEdgeInsets" minX="25" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="AUDIO BOOKS" image="AudioBookIcon">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="btnTapped:" destination="wHe-qy-JF8" eventType="touchUpInside" id="lQj-dm-0f2"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.47843137254901957" blue="0.75294117647058822" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="55" id="Bju-mN-nXR"/>
|
||||
<constraint firstItem="Zxm-AD-QSC" firstAttribute="top" secondItem="EB0-q2-d6p" secondAttribute="top" constant="2" id="GE7-mW-hev"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Zxm-AD-QSC" secondAttribute="trailing" constant="10" id="Poi-1j-PbX"/>
|
||||
<constraint firstItem="Zxm-AD-QSC" firstAttribute="leading" secondItem="EB0-q2-d6p" secondAttribute="leading" constant="10" id="YGw-Of-AnG"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Zxm-AD-QSC" secondAttribute="bottom" constant="2" id="hps-6c-5XM"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jjX-jF-HeM">
|
||||
<rect key="frame" x="0.0" y="274.99999999999994" width="220" height="55"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="rry-dK-R12">
|
||||
<rect key="frame" x="10" y="2" width="200" height="51"/>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="15"/>
|
||||
<inset key="titleEdgeInsets" minX="40" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<inset key="imageEdgeInsets" minX="25" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="BLOG" image="BlogsIcon">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="btnTapped:" destination="wHe-qy-JF8" eventType="touchUpInside" id="gxQ-oE-cfZ"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0039215686274509803" green="0.60392156862745094" blue="0.29019607843137252" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="rry-dK-R12" firstAttribute="top" secondItem="jjX-jF-HeM" secondAttribute="top" constant="2" id="3o2-9G-Vv4"/>
|
||||
<constraint firstAttribute="trailing" secondItem="rry-dK-R12" secondAttribute="trailing" constant="10" id="PrB-g3-br9"/>
|
||||
<constraint firstAttribute="height" constant="55" id="X6c-GK-0JP"/>
|
||||
<constraint firstAttribute="bottom" secondItem="rry-dK-R12" secondAttribute="bottom" constant="2" id="mpy-JJ-ym2"/>
|
||||
<constraint firstItem="rry-dK-R12" firstAttribute="leading" secondItem="jjX-jF-HeM" secondAttribute="leading" constant="10" id="nHz-sb-6rf"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="HXv-Ph-s5n">
|
||||
<rect key="frame" x="0.0" y="329.99999999999994" width="220" height="55"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="cDI-gA-Sfd">
|
||||
<rect key="frame" x="10" y="2" width="200" height="51"/>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="15"/>
|
||||
<inset key="titleEdgeInsets" minX="40" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<inset key="imageEdgeInsets" minX="25" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="KARAOKE" image="KaraokeIcon">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="btnTapped:" destination="wHe-qy-JF8" eventType="touchUpInside" id="3oM-d4-nYE"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.80000000000000004" green="0.29019607843137252" blue="0.10980392156862745" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="cDI-gA-Sfd" firstAttribute="leading" secondItem="HXv-Ph-s5n" secondAttribute="leading" constant="10" id="XxX-LE-mIL"/>
|
||||
<constraint firstAttribute="bottom" secondItem="cDI-gA-Sfd" secondAttribute="bottom" constant="2" id="Zaf-kd-GoG"/>
|
||||
<constraint firstItem="cDI-gA-Sfd" firstAttribute="top" secondItem="HXv-Ph-s5n" secondAttribute="top" constant="2" id="ggv-XX-fcC"/>
|
||||
<constraint firstAttribute="height" constant="55" id="k1i-dG-0Rw"/>
|
||||
<constraint firstAttribute="trailing" secondItem="cDI-gA-Sfd" secondAttribute="trailing" constant="10" id="qHT-Qb-Dbu"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="aug-R4-Sg7">
|
||||
<rect key="frame" x="0.0" y="384.99999999999994" width="220" height="55"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="HH9-9q-T6X">
|
||||
<rect key="frame" x="10" y="2" width="200" height="51"/>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="15"/>
|
||||
<inset key="titleEdgeInsets" minX="40" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<inset key="imageEdgeInsets" minX="25" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="SHOP" image="ShopIcon">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="btnTapped:" destination="wHe-qy-JF8" eventType="touchUpInside" id="gBv-U1-q7C"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.54509803921568623" green="0.67450980392156867" blue="0.17254901960784313" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="HH9-9q-T6X" firstAttribute="leading" secondItem="aug-R4-Sg7" secondAttribute="leading" constant="10" id="SI5-az-lZF"/>
|
||||
<constraint firstAttribute="height" constant="55" id="cPw-D2-Hx1"/>
|
||||
<constraint firstAttribute="bottom" secondItem="HH9-9q-T6X" secondAttribute="bottom" constant="2" id="hxM-uh-1bZ"/>
|
||||
<constraint firstItem="HH9-9q-T6X" firstAttribute="top" secondItem="aug-R4-Sg7" secondAttribute="top" constant="2" id="o2X-co-bqD"/>
|
||||
<constraint firstAttribute="trailing" secondItem="HH9-9q-T6X" secondAttribute="trailing" constant="10" id="wQS-oN-biG"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.78431372549019607" green="0.70588235294117641" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="nOR-gr-8Ab" firstAttribute="leading" secondItem="c2y-F6-AqI" secondAttribute="leading" constant="10" id="0d1-gu-9JD"/>
|
||||
<constraint firstItem="nOR-gr-8Ab" firstAttribute="top" secondItem="c2y-F6-AqI" secondAttribute="top" constant="2" id="9de-7W-fKm"/>
|
||||
<constraint firstAttribute="bottom" secondItem="nOR-gr-8Ab" secondAttribute="bottom" constant="2" id="Btq-ob-Tg6"/>
|
||||
<constraint firstAttribute="height" constant="55" id="DAq-Y8-V3k"/>
|
||||
<constraint firstAttribute="trailing" secondItem="nOR-gr-8Ab" secondAttribute="trailing" constant="10" id="Vtt-FU-GZa"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="aOq-F2-okk">
|
||||
<rect key="frame" x="0.0" y="55" width="220" height="55"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
|
||||
<integer key="value" value="10"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</stackView>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lbo-EC-m7h">
|
||||
<rect key="frame" x="0.0" y="439.99999999999994" width="220" height="40"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="pfM-e9-xeS">
|
||||
<rect key="frame" x="10" y="2" width="200" height="51"/>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="15"/>
|
||||
<inset key="titleEdgeInsets" minX="40" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<inset key="imageEdgeInsets" minX="25" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="LIVE TV" image="LiveTvIcon">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="btnTapped:" destination="wHe-qy-JF8" eventType="touchUpInside" id="PWm-Wo-tFp"/>
|
||||
</connections>
|
||||
</button>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="arrowtriangle.down.fill" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="8u2-TD-184">
|
||||
<rect key="frame" x="0.0" y="-6.6666666666666679" width="220" height="47.333333333333343"/>
|
||||
<color key="tintColor" red="0.54509803921568623" green="0.67450980392156867" blue="0.17254901960784313" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.63529411764705879" blue="0.87058823529411766" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="pfM-e9-xeS" secondAttribute="bottom" constant="2" id="Y6l-zl-LZs"/>
|
||||
<constraint firstItem="pfM-e9-xeS" firstAttribute="top" secondItem="aOq-F2-okk" secondAttribute="top" constant="2" id="hqx-nu-Wya"/>
|
||||
<constraint firstItem="pfM-e9-xeS" firstAttribute="leading" secondItem="aOq-F2-okk" secondAttribute="leading" constant="10" id="jg1-9k-bKr"/>
|
||||
<constraint firstAttribute="height" constant="55" id="q4E-5i-tfI"/>
|
||||
<constraint firstAttribute="trailing" secondItem="pfM-e9-xeS" secondAttribute="trailing" constant="10" id="qSC-Za-YgM"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="yWe-87-bOu">
|
||||
<rect key="frame" x="0.0" y="110" width="220" height="55"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="31D-NF-WIr">
|
||||
<rect key="frame" x="10" y="2" width="200" height="51"/>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="15"/>
|
||||
<inset key="titleEdgeInsets" minX="40" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<inset key="imageEdgeInsets" minX="25" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="WEB SERIES" image="WebSeriesIcon">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="btnTapped:" destination="wHe-qy-JF8" eventType="touchUpInside" id="9DX-4s-myd"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.36862745098039218" green="0.12156862745098039" blue="0.76862745098039209" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="31D-NF-WIr" secondAttribute="bottom" constant="2" id="4eT-nj-ca1"/>
|
||||
<constraint firstItem="31D-NF-WIr" firstAttribute="leading" secondItem="yWe-87-bOu" secondAttribute="leading" constant="10" id="DUr-4P-7N1"/>
|
||||
<constraint firstAttribute="trailing" secondItem="31D-NF-WIr" secondAttribute="trailing" constant="10" id="Gdd-O8-sQw"/>
|
||||
<constraint firstItem="31D-NF-WIr" firstAttribute="top" secondItem="yWe-87-bOu" secondAttribute="top" constant="2" id="YJb-T1-Ihr"/>
|
||||
<constraint firstAttribute="height" constant="55" id="vmm-f6-Jyd"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ClJ-4O-Ne4">
|
||||
<rect key="frame" x="0.0" y="164.99999999999994" width="220" height="55"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="5de-tc-WUV">
|
||||
<rect key="frame" x="10" y="2" width="200" height="51"/>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="15"/>
|
||||
<inset key="titleEdgeInsets" minX="40" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<inset key="imageEdgeInsets" minX="25" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="GAMES" image="GamesIcon">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="btnTapped:" destination="wHe-qy-JF8" eventType="touchUpInside" id="jmS-bS-CSO"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.95294117647058818" green="0.52549019607843139" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="5de-tc-WUV" secondAttribute="bottom" constant="2" id="7cy-18-vvS"/>
|
||||
<constraint firstItem="5de-tc-WUV" firstAttribute="leading" secondItem="ClJ-4O-Ne4" secondAttribute="leading" constant="10" id="CQL-hg-cu4"/>
|
||||
<constraint firstAttribute="height" constant="55" id="ptl-vj-caT"/>
|
||||
<constraint firstAttribute="trailing" secondItem="5de-tc-WUV" secondAttribute="trailing" constant="10" id="vCd-nc-hRo"/>
|
||||
<constraint firstItem="5de-tc-WUV" firstAttribute="top" secondItem="ClJ-4O-Ne4" secondAttribute="top" constant="2" id="xIx-hR-rzH"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="EB0-q2-d6p">
|
||||
<rect key="frame" x="0.0" y="219.99999999999994" width="220" height="55"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Zxm-AD-QSC">
|
||||
<rect key="frame" x="10" y="2" width="200" height="51"/>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="15"/>
|
||||
<inset key="titleEdgeInsets" minX="40" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<inset key="imageEdgeInsets" minX="25" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="AUDIO BOOKS" image="AudioBookIcon">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="btnTapped:" destination="wHe-qy-JF8" eventType="touchUpInside" id="lQj-dm-0f2"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.47843137254901957" blue="0.75294117647058822" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="55" id="Bju-mN-nXR"/>
|
||||
<constraint firstItem="Zxm-AD-QSC" firstAttribute="top" secondItem="EB0-q2-d6p" secondAttribute="top" constant="2" id="GE7-mW-hev"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Zxm-AD-QSC" secondAttribute="trailing" constant="10" id="Poi-1j-PbX"/>
|
||||
<constraint firstItem="Zxm-AD-QSC" firstAttribute="leading" secondItem="EB0-q2-d6p" secondAttribute="leading" constant="10" id="YGw-Of-AnG"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Zxm-AD-QSC" secondAttribute="bottom" constant="2" id="hps-6c-5XM"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jjX-jF-HeM">
|
||||
<rect key="frame" x="0.0" y="274.99999999999994" width="220" height="55"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="rry-dK-R12">
|
||||
<rect key="frame" x="10" y="2" width="200" height="51"/>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="15"/>
|
||||
<inset key="titleEdgeInsets" minX="40" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<inset key="imageEdgeInsets" minX="25" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="BLOG" image="BlogsIcon">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="btnTapped:" destination="wHe-qy-JF8" eventType="touchUpInside" id="gxQ-oE-cfZ"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0039215686274509803" green="0.60392156862745094" blue="0.29019607843137252" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="rry-dK-R12" firstAttribute="top" secondItem="jjX-jF-HeM" secondAttribute="top" constant="2" id="3o2-9G-Vv4"/>
|
||||
<constraint firstAttribute="trailing" secondItem="rry-dK-R12" secondAttribute="trailing" constant="10" id="PrB-g3-br9"/>
|
||||
<constraint firstAttribute="height" constant="55" id="X6c-GK-0JP"/>
|
||||
<constraint firstAttribute="bottom" secondItem="rry-dK-R12" secondAttribute="bottom" constant="2" id="mpy-JJ-ym2"/>
|
||||
<constraint firstItem="rry-dK-R12" firstAttribute="leading" secondItem="jjX-jF-HeM" secondAttribute="leading" constant="10" id="nHz-sb-6rf"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="HXv-Ph-s5n">
|
||||
<rect key="frame" x="0.0" y="329.99999999999994" width="220" height="55"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="cDI-gA-Sfd">
|
||||
<rect key="frame" x="10" y="2" width="200" height="51"/>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="15"/>
|
||||
<inset key="titleEdgeInsets" minX="40" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<inset key="imageEdgeInsets" minX="25" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="KARAOKE" image="KaraokeIcon">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="btnTapped:" destination="wHe-qy-JF8" eventType="touchUpInside" id="3oM-d4-nYE"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.80000000000000004" green="0.29019607843137252" blue="0.10980392156862745" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="cDI-gA-Sfd" firstAttribute="leading" secondItem="HXv-Ph-s5n" secondAttribute="leading" constant="10" id="XxX-LE-mIL"/>
|
||||
<constraint firstAttribute="bottom" secondItem="cDI-gA-Sfd" secondAttribute="bottom" constant="2" id="Zaf-kd-GoG"/>
|
||||
<constraint firstItem="cDI-gA-Sfd" firstAttribute="top" secondItem="HXv-Ph-s5n" secondAttribute="top" constant="2" id="ggv-XX-fcC"/>
|
||||
<constraint firstAttribute="height" constant="55" id="k1i-dG-0Rw"/>
|
||||
<constraint firstAttribute="trailing" secondItem="cDI-gA-Sfd" secondAttribute="trailing" constant="10" id="qHT-Qb-Dbu"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="aug-R4-Sg7">
|
||||
<rect key="frame" x="0.0" y="384.99999999999994" width="220" height="55"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="HH9-9q-T6X">
|
||||
<rect key="frame" x="10" y="2" width="200" height="51"/>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="15"/>
|
||||
<inset key="titleEdgeInsets" minX="40" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<inset key="imageEdgeInsets" minX="25" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="SHOP" image="ShopIcon">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="btnTapped:" destination="wHe-qy-JF8" eventType="touchUpInside" id="gBv-U1-q7C"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.54509803921568623" green="0.67450980392156867" blue="0.17254901960784313" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="HH9-9q-T6X" firstAttribute="leading" secondItem="aug-R4-Sg7" secondAttribute="leading" constant="10" id="SI5-az-lZF"/>
|
||||
<constraint firstAttribute="height" constant="55" id="cPw-D2-Hx1"/>
|
||||
<constraint firstAttribute="bottom" secondItem="HH9-9q-T6X" secondAttribute="bottom" constant="2" id="hxM-uh-1bZ"/>
|
||||
<constraint firstItem="HH9-9q-T6X" firstAttribute="top" secondItem="aug-R4-Sg7" secondAttribute="top" constant="2" id="o2X-co-bqD"/>
|
||||
<constraint firstAttribute="trailing" secondItem="HH9-9q-T6X" secondAttribute="trailing" constant="10" id="wQS-oN-biG"/>
|
||||
<constraint firstItem="8u2-TD-184" firstAttribute="leading" secondItem="lbo-EC-m7h" secondAttribute="leading" id="A0n-zf-yJK"/>
|
||||
<constraint firstItem="8u2-TD-184" firstAttribute="top" secondItem="lbo-EC-m7h" secondAttribute="top" constant="-9" id="Ryi-aG-8pd"/>
|
||||
<constraint firstAttribute="trailing" secondItem="8u2-TD-184" secondAttribute="trailing" id="Xhf-8L-KgJ"/>
|
||||
<constraint firstAttribute="bottom" secondItem="8u2-TD-184" secondAttribute="bottom" constant="-3" id="a3g-ZQ-Nbk"/>
|
||||
<constraint firstAttribute="height" constant="40" id="cvQ-8z-jcj"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
@@ -847,6 +874,7 @@
|
||||
<outlet property="audioBookBtn" destination="Zxm-AD-QSC" id="98B-Bx-uwL"/>
|
||||
<outlet property="blogBtn" destination="rry-dK-R12" id="Xhf-0D-FAU"/>
|
||||
<outlet property="blurView" destination="bkq-AU-CNT" id="0nM-J2-yrv"/>
|
||||
<outlet property="bottomView" destination="lbo-EC-m7h" id="4iQ-qD-bgE"/>
|
||||
<outlet property="customView" destination="DNc-fQ-fy8" id="zKU-Vc-wBz"/>
|
||||
<outlet property="extraView" destination="lxy-WU-CSd" id="ba7-wu-ZGj"/>
|
||||
<outlet property="gamesBtn" destination="5de-tc-WUV" id="osP-zC-RwD"/>
|
||||
@@ -1355,6 +1383,7 @@
|
||||
<image name="Theme2" width="106" height="160"/>
|
||||
<image name="WebSeriesIcon" width="33.333332061767578" height="30.333333969116211"/>
|
||||
<image name="WokaFmIcon" width="35" height="35"/>
|
||||
<image name="arrowtriangle.down.fill" catalog="system" width="128" height="120"/>
|
||||
<image name="xmark" catalog="system" width="128" height="113"/>
|
||||
<image name="xmark.circle" catalog="system" width="128" height="123"/>
|
||||
<namedColor name="TextDarkBlue">
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
//
|
||||
// AVPlayerTesting.swift
|
||||
// WOKA
|
||||
//
|
||||
// Created by Bilal on 12/07/2024.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import AVKit
|
||||
|
||||
class AVPlayerTesting: AVPlayerViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
let videoURL = URL(string: "https://content.jwplatform.com/videos/699dmCGz-Ysj2G4DQ.mp4")!
|
||||
let player = AVPlayer(url: videoURL)
|
||||
self.player = player
|
||||
player.play()
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,265 +0,0 @@
|
||||
//
|
||||
// AVPlayerVC.swift
|
||||
// WOKA
|
||||
//
|
||||
// Created by Bilal on 05/07/2024.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import AVFoundation
|
||||
|
||||
class AVPlayerVC: UIViewController {
|
||||
|
||||
@IBOutlet weak var viewControll: UIView!
|
||||
@IBOutlet weak var stackCtrView: UIStackView!
|
||||
@IBOutlet weak var loadingIndicator: UIActivityIndicatorView!
|
||||
|
||||
@IBOutlet weak var sliderStack: UIStackView!
|
||||
@IBOutlet weak var tintView: UIView!
|
||||
@IBOutlet weak var videoTitle: UILabel!
|
||||
|
||||
@IBOutlet weak var karaokeStack: UIStackView!
|
||||
@IBOutlet weak var playPauseRecordStack: UIStackView!
|
||||
@IBOutlet weak var karaokeLoading: UIActivityIndicatorView!
|
||||
@IBOutlet weak var reloadBtn: UIButton!
|
||||
|
||||
@IBOutlet weak var img10SecBack: UIImageView! {
|
||||
didSet {
|
||||
self.img10SecBack.isUserInteractionEnabled = true
|
||||
self.img10SecBack.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(onTap10SecBack)))
|
||||
}
|
||||
}
|
||||
@IBOutlet weak var imgPlay: UIImageView! {
|
||||
didSet {
|
||||
self.imgPlay.isUserInteractionEnabled = true
|
||||
self.imgPlay.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(onTapPlayPause)))
|
||||
}
|
||||
}
|
||||
@IBOutlet weak var img10SecFor: UIImageView! {
|
||||
didSet {
|
||||
self.img10SecFor.isUserInteractionEnabled = true
|
||||
self.img10SecFor.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(onTap10SecNext)))
|
||||
}
|
||||
}
|
||||
|
||||
@IBOutlet weak var lbCurrentTime: UILabel!
|
||||
@IBOutlet weak var lbTotalTime: UILabel!
|
||||
|
||||
|
||||
@IBOutlet weak var seekSlider: UISlider! {
|
||||
didSet {
|
||||
self.seekSlider.addTarget(self, action: #selector(onTapToSlide), for: .valueChanged)
|
||||
}
|
||||
}
|
||||
|
||||
var videoURL : String?
|
||||
var titleVideo : String?
|
||||
var vm = AVPlayerVM()
|
||||
|
||||
// MARK: - LifeCycle
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
vm.vc = self
|
||||
vm.initView()
|
||||
hideShowIndicator(isLoading: true)
|
||||
|
||||
viewControll.addTapGesture {
|
||||
self.vm.timer?.invalidate()
|
||||
self.vm.showHideControls()
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
self.vm.setVideoPlayer()
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
self.vm.player?.pause()
|
||||
self.vm.player = nil
|
||||
}
|
||||
|
||||
deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
self.vm.player?.currentItem?.removeObserver(self, forKeyPath: "status")
|
||||
|
||||
vm.player?.removeObserver(self, forKeyPath: "rate")
|
||||
if let playerItem = vm.player?.currentItem {
|
||||
playerItem.removeObserver(self, forKeyPath: "isPlaybackBufferEmpty")
|
||||
playerItem.removeObserver(self, forKeyPath: "isPlaybackLikelyToKeepUp")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Button Clicks & Tap Handler
|
||||
|
||||
@IBAction func reloadBtnTapped(_ sender: UIButton) {
|
||||
vm.isFinished = false
|
||||
|
||||
vm.reloadVideo()
|
||||
}
|
||||
|
||||
@IBAction func closeBtnTapped(_ sender: UIButton) {
|
||||
self.dismiss(animated: true)
|
||||
}
|
||||
|
||||
@IBAction func startStopRecording(_ sender: LocalisedElementsButton) {
|
||||
}
|
||||
|
||||
@IBAction func playPauseBtn(_ sender: LocalisedElementsButton) {
|
||||
}
|
||||
|
||||
@objc func onTap10SecNext() {
|
||||
guard let currentTime = self.vm.player?.currentTime() else { return }
|
||||
let seekTime10Sec = CMTimeGetSeconds(currentTime).advanced(by: 10)
|
||||
let seekTime = CMTime(value: CMTimeValue(seekTime10Sec), timescale: 1)
|
||||
vm.timer?.invalidate()
|
||||
vm.timer = nil
|
||||
hideShowIndicator(isLoading: true)
|
||||
|
||||
self.vm.player?.seek(to: seekTime, completionHandler: { [weak self] completed in
|
||||
if completed{
|
||||
guard let self else{return}
|
||||
hideShowIndicator(isLoading: false)
|
||||
vm.startTimer()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@objc func onTap10SecBack() {
|
||||
guard let currentTime = self.vm.player?.currentTime() else { return }
|
||||
vm.timer?.invalidate()
|
||||
vm.timer = nil
|
||||
hideShowIndicator(isLoading: true)
|
||||
|
||||
let seekTime10Sec = CMTimeGetSeconds(currentTime).advanced(by: -10)
|
||||
let seekTime = CMTime(value: CMTimeValue(seekTime10Sec), timescale: 1)
|
||||
self.vm.player?.seek(to: seekTime, completionHandler: { [weak self] completed in
|
||||
if completed{
|
||||
guard let self else{return}
|
||||
hideShowIndicator(isLoading: false)
|
||||
vm.startTimer()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func hideShowIndicator(isLoading : Bool){
|
||||
if isLoading{
|
||||
self.imgPlay.isHidden = true
|
||||
self.loadingIndicator.startAnimating()
|
||||
}else{
|
||||
self.imgPlay.isHidden = false
|
||||
self.loadingIndicator.stopAnimating()
|
||||
self.loadingIndicator.hidesWhenStopped = true
|
||||
}
|
||||
}
|
||||
|
||||
@objc func onTapPlayPause() {
|
||||
if self.vm.player?.timeControlStatus == .playing {
|
||||
self.imgPlay.image = UIImage(systemName: "play.circle")
|
||||
self.vm.player?.pause()
|
||||
} else {
|
||||
self.imgPlay.image = UIImage(systemName: "pause.circle")
|
||||
self.vm.player?.play()
|
||||
}
|
||||
}
|
||||
|
||||
@objc func onTapToSlide() {
|
||||
if vm.timer != nil{
|
||||
vm.timer?.invalidate()
|
||||
vm.timer = nil
|
||||
}
|
||||
self.vm.isThumbSeek = true
|
||||
guard let duration = self.vm.player?.currentItem?.duration else { return }
|
||||
let value = Float64(self.seekSlider.value) * CMTimeGetSeconds(duration)
|
||||
if value.isNaN == false {
|
||||
let seekTime = CMTime(value: CMTimeValue(value), timescale: 1)
|
||||
self.vm.player?.seek(to: seekTime, completionHandler: { completed in
|
||||
if completed {
|
||||
self.vm.isThumbSeek = false
|
||||
self.vm.startTimer()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
||||
if keyPath == "rate" {
|
||||
if let player = object as? AVPlayer {
|
||||
if player.rate == 0 {
|
||||
print("Player is paused")
|
||||
} else {
|
||||
print("Player is playing")
|
||||
hideShowIndicator(isLoading: false)
|
||||
imgPlay.image = UIImage(systemName: "pause.circle")
|
||||
}
|
||||
}
|
||||
} else if let playerItem = object as? AVPlayerItem {
|
||||
if keyPath == "isPlaybackBufferEmpty" {
|
||||
if playerItem.isPlaybackBufferEmpty {
|
||||
print("Loading")
|
||||
hideShowIndicator(isLoading: true)
|
||||
}
|
||||
} else if keyPath == "isPlaybackLikelyToKeepUp" {
|
||||
if playerItem.isPlaybackLikelyToKeepUp {
|
||||
print("finished")
|
||||
hideShowIndicator(isLoading: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// // Observe for player item status changes
|
||||
// override func observeValue(forKeyPath keyPath: String?,
|
||||
// of object: Any?,
|
||||
// change: [NSKeyValueChangeKey : Any]?,
|
||||
// context: UnsafeMutableRawPointer?) {
|
||||
// if keyPath == "status" {
|
||||
// if let playerItem = object as? AVPlayerItem {
|
||||
// switch playerItem.status {
|
||||
// case .readyToPlay:
|
||||
// // Ready to play
|
||||
// print("Player item is ready to play.")
|
||||
// vm.player?.play()
|
||||
// hideShowIndicator(isLoading: false)
|
||||
// imgPlay.image = UIImage(systemName: "pause.circle")
|
||||
// case .failed:
|
||||
// // Failed
|
||||
// if let error = playerItem.error {
|
||||
// print("Player item error: \(error.localizedDescription)")
|
||||
// vm.handlePlayerError(error)
|
||||
// }
|
||||
// case .unknown:
|
||||
// // Unknown status
|
||||
// print("Player item status is unknown.")
|
||||
// @unknown default:
|
||||
// // Handle unexpected cases
|
||||
// print("Player item status is unknown.")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// @objc private func onTapToggleScreen() {
|
||||
// if #available(iOS 16.0, *) {
|
||||
// guard let windowSceen = self.view.window?.windowScene else { return }
|
||||
// if windowSceen.interfaceOrientation == .portrait {
|
||||
// windowSceen.requestGeometryUpdate(.iOS(interfaceOrientations: .landscape)) { error in
|
||||
// print(error.localizedDescription)
|
||||
// }
|
||||
// } else {
|
||||
// windowSceen.requestGeometryUpdate(.iOS(interfaceOrientations: .portrait)) { error in
|
||||
// print(error.localizedDescription)
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// if UIDevice.current.orientation == .portrait {
|
||||
// let orientation = UIInterfaceOrientation.landscapeRight.rawValue
|
||||
// UIDevice.current.setValue(orientation, forKey: "orientation")
|
||||
// } else {
|
||||
// let orientation = UIInterfaceOrientation.portrait.rawValue
|
||||
// UIDevice.current.setValue(orientation, forKey: "orientation")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@@ -197,7 +197,13 @@ class KaraokeDetailsVC: UIViewController {
|
||||
}
|
||||
|
||||
shareView.addTapGesture {
|
||||
print("share")
|
||||
if let name = URL(string: "https://apps.apple.com/in/app/woka/id6465305185"), !name.absoluteString.isEmpty {
|
||||
let objectsToShare = [name]
|
||||
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
|
||||
self.present(activityVC, animated: true, completion: nil)
|
||||
} else {
|
||||
// show alert for not available
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
//
|
||||
// TestingKaraokeVC.swift
|
||||
// WOKA
|
||||
//
|
||||
// Created by MacBook Pro on 09/07/24.
|
||||
//
|
||||
|
||||
import AVFAudio
|
||||
import UIKit
|
||||
import AVFoundation
|
||||
|
||||
class TestingKaraokeVC : UIViewController{
|
||||
|
||||
var player: AVPlayer!
|
||||
var audioEngine: AVAudioEngine!
|
||||
var micInput: AVAudioInputNode!
|
||||
var playerNode: AVAudioPlayerNode!
|
||||
var audioFile: AVAudioFile!
|
||||
var fileURL: URL!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
let videoURL = URL(string: "https://content.jwplatform.com/videos/DOhtETio-Ysj2G4DQ.mp4")!
|
||||
setupPlayer(with: videoURL)
|
||||
setupAudioEngine()
|
||||
setupAudioFile()
|
||||
}
|
||||
|
||||
func setupPlayer(with url: URL) {
|
||||
player = AVPlayer(url: url)
|
||||
let playerLayer = AVPlayerLayer(player: player)
|
||||
playerLayer.frame = view.bounds
|
||||
view.layer.addSublayer(playerLayer)
|
||||
player.play()
|
||||
}
|
||||
|
||||
func setupAudioEngine() {
|
||||
audioEngine = AVAudioEngine()
|
||||
micInput = audioEngine.inputNode
|
||||
playerNode = AVAudioPlayerNode()
|
||||
|
||||
audioEngine.attach(playerNode)
|
||||
let format = micInput.inputFormat(forBus: 0)
|
||||
|
||||
audioEngine.connect(micInput, to: audioEngine.mainMixerNode, format: format)
|
||||
audioEngine.connect(playerNode, to: audioEngine.mainMixerNode, format: format)
|
||||
|
||||
try! audioEngine.start()
|
||||
}
|
||||
|
||||
func setupAudioFile() {
|
||||
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
||||
fileURL = documentsDirectory.appendingPathComponent("output.m4a")
|
||||
let format = audioEngine.mainMixerNode.outputFormat(forBus: 0)
|
||||
|
||||
do {
|
||||
audioFile = try AVAudioFile(forWriting: fileURL, settings: format.settings)
|
||||
} catch {
|
||||
print("Error creating audio file: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func startRecording() {
|
||||
let mixer = audioEngine.mainMixerNode
|
||||
let format = mixer.outputFormat(forBus: 0)
|
||||
|
||||
mixer.installTap(onBus: 0, bufferSize: 1024, format: format) { (buffer, time) in
|
||||
do {
|
||||
try self.audioFile.write(from: buffer)
|
||||
} catch {
|
||||
print("Error writing audio buffer: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func stopRecording() {
|
||||
let mixer = audioEngine.mainMixerNode
|
||||
mixer.removeTap(onBus: 0)
|
||||
|
||||
// Save the file to Files app
|
||||
presentDocumentPicker()
|
||||
}
|
||||
|
||||
func presentDocumentPicker() {
|
||||
// let documentPicker = UIDocumentPickerViewController(forExporting: [fileURL])
|
||||
// documentPicker.delegate = self
|
||||
// present(documentPicker, animated: true, completion: nil)
|
||||
|
||||
guard let mixedAudioURL = fileURL else { return }
|
||||
DispatchQueue.main.async {
|
||||
let documentPicker = UIDocumentPickerViewController(url: mixedAudioURL, in: .exportToService)
|
||||
documentPicker.delegate = self
|
||||
self.present(documentPicker, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func startButtonPressed(_ sender: UIButton) {
|
||||
startRecording()
|
||||
}
|
||||
|
||||
@IBAction func stopButtonPressed(_ sender: UIButton) {
|
||||
stopRecording()
|
||||
}
|
||||
}
|
||||
|
||||
extension TestingKaraokeVC: UIDocumentPickerDelegate {
|
||||
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
|
||||
guard let selectedURL = urls.first else { return }
|
||||
do {
|
||||
try FileManager.default.moveItem(at: fileURL, to: selectedURL)
|
||||
} catch {
|
||||
print("Error saving file to Files app: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
|
||||
print("Document picker was cancelled")
|
||||
}
|
||||
}
|
||||
22
WOKA/Karaoke/DumpFiles/AVPlayerTesting.swift
Normal file
22
WOKA/Karaoke/DumpFiles/AVPlayerTesting.swift
Normal file
@@ -0,0 +1,22 @@
|
||||
////
|
||||
//// AVPlayerTesting.swift
|
||||
//// WOKA
|
||||
////
|
||||
//// Created by Bilal on 12/07/2024.
|
||||
////
|
||||
//
|
||||
//import UIKit
|
||||
//import AVKit
|
||||
//
|
||||
//class AVPlayerTesting: AVPlayerViewController {
|
||||
//
|
||||
// override func viewDidLoad() {
|
||||
// super.viewDidLoad()
|
||||
// let videoURL = URL(string: "https://content.jwplatform.com/videos/699dmCGz-Ysj2G4DQ.mp4")!
|
||||
// let player = AVPlayer(url: videoURL)
|
||||
// self.player = player
|
||||
// player.play()
|
||||
// // Do any additional setup after loading the view.
|
||||
// }
|
||||
//
|
||||
//}
|
||||
265
WOKA/Karaoke/DumpFiles/AVPlayerVC.swift
Normal file
265
WOKA/Karaoke/DumpFiles/AVPlayerVC.swift
Normal file
@@ -0,0 +1,265 @@
|
||||
////
|
||||
//// AVPlayerVC.swift
|
||||
//// WOKA
|
||||
////
|
||||
//// Created by Bilal on 05/07/2024.
|
||||
////
|
||||
//
|
||||
//import UIKit
|
||||
//import AVFoundation
|
||||
//
|
||||
//class AVPlayerVC: UIViewController {
|
||||
//
|
||||
// @IBOutlet weak var viewControll: UIView!
|
||||
// @IBOutlet weak var stackCtrView: UIStackView!
|
||||
// @IBOutlet weak var loadingIndicator: UIActivityIndicatorView!
|
||||
//
|
||||
// @IBOutlet weak var sliderStack: UIStackView!
|
||||
// @IBOutlet weak var tintView: UIView!
|
||||
// @IBOutlet weak var videoTitle: UILabel!
|
||||
//
|
||||
// @IBOutlet weak var karaokeStack: UIStackView!
|
||||
// @IBOutlet weak var playPauseRecordStack: UIStackView!
|
||||
// @IBOutlet weak var karaokeLoading: UIActivityIndicatorView!
|
||||
// @IBOutlet weak var reloadBtn: UIButton!
|
||||
//
|
||||
// @IBOutlet weak var img10SecBack: UIImageView! {
|
||||
// didSet {
|
||||
// self.img10SecBack.isUserInteractionEnabled = true
|
||||
// self.img10SecBack.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(onTap10SecBack)))
|
||||
// }
|
||||
// }
|
||||
// @IBOutlet weak var imgPlay: UIImageView! {
|
||||
// didSet {
|
||||
// self.imgPlay.isUserInteractionEnabled = true
|
||||
// self.imgPlay.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(onTapPlayPause)))
|
||||
// }
|
||||
// }
|
||||
// @IBOutlet weak var img10SecFor: UIImageView! {
|
||||
// didSet {
|
||||
// self.img10SecFor.isUserInteractionEnabled = true
|
||||
// self.img10SecFor.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(onTap10SecNext)))
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @IBOutlet weak var lbCurrentTime: UILabel!
|
||||
// @IBOutlet weak var lbTotalTime: UILabel!
|
||||
//
|
||||
//
|
||||
// @IBOutlet weak var seekSlider: UISlider! {
|
||||
// didSet {
|
||||
// self.seekSlider.addTarget(self, action: #selector(onTapToSlide), for: .valueChanged)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// var videoURL : String?
|
||||
// var titleVideo : String?
|
||||
// var vm = AVPlayerVM()
|
||||
//
|
||||
// // MARK: - LifeCycle
|
||||
//
|
||||
// override func viewDidLoad() {
|
||||
// super.viewDidLoad()
|
||||
// vm.vc = self
|
||||
// vm.initView()
|
||||
// hideShowIndicator(isLoading: true)
|
||||
//
|
||||
// viewControll.addTapGesture {
|
||||
// self.vm.timer?.invalidate()
|
||||
// self.vm.showHideControls()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override func viewDidAppear(_ animated: Bool) {
|
||||
// self.vm.setVideoPlayer()
|
||||
// }
|
||||
//
|
||||
// override func viewWillDisappear(_ animated: Bool) {
|
||||
// super.viewWillDisappear(animated)
|
||||
// self.vm.player?.pause()
|
||||
// self.vm.player = nil
|
||||
// }
|
||||
//
|
||||
// deinit {
|
||||
// NotificationCenter.default.removeObserver(self)
|
||||
// self.vm.player?.currentItem?.removeObserver(self, forKeyPath: "status")
|
||||
//
|
||||
// vm.player?.removeObserver(self, forKeyPath: "rate")
|
||||
// if let playerItem = vm.player?.currentItem {
|
||||
// playerItem.removeObserver(self, forKeyPath: "isPlaybackBufferEmpty")
|
||||
// playerItem.removeObserver(self, forKeyPath: "isPlaybackLikelyToKeepUp")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // MARK: - Button Clicks & Tap Handler
|
||||
//
|
||||
// @IBAction func reloadBtnTapped(_ sender: UIButton) {
|
||||
// vm.isFinished = false
|
||||
//
|
||||
// vm.reloadVideo()
|
||||
// }
|
||||
//
|
||||
// @IBAction func closeBtnTapped(_ sender: UIButton) {
|
||||
// self.dismiss(animated: true)
|
||||
// }
|
||||
//
|
||||
// @IBAction func startStopRecording(_ sender: LocalisedElementsButton) {
|
||||
// }
|
||||
//
|
||||
// @IBAction func playPauseBtn(_ sender: LocalisedElementsButton) {
|
||||
// }
|
||||
//
|
||||
// @objc func onTap10SecNext() {
|
||||
// guard let currentTime = self.vm.player?.currentTime() else { return }
|
||||
// let seekTime10Sec = CMTimeGetSeconds(currentTime).advanced(by: 10)
|
||||
// let seekTime = CMTime(value: CMTimeValue(seekTime10Sec), timescale: 1)
|
||||
// vm.timer?.invalidate()
|
||||
// vm.timer = nil
|
||||
// hideShowIndicator(isLoading: true)
|
||||
//
|
||||
// self.vm.player?.seek(to: seekTime, completionHandler: { [weak self] completed in
|
||||
// if completed{
|
||||
// guard let self else{return}
|
||||
// hideShowIndicator(isLoading: false)
|
||||
// vm.startTimer()
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// @objc func onTap10SecBack() {
|
||||
// guard let currentTime = self.vm.player?.currentTime() else { return }
|
||||
// vm.timer?.invalidate()
|
||||
// vm.timer = nil
|
||||
// hideShowIndicator(isLoading: true)
|
||||
//
|
||||
// let seekTime10Sec = CMTimeGetSeconds(currentTime).advanced(by: -10)
|
||||
// let seekTime = CMTime(value: CMTimeValue(seekTime10Sec), timescale: 1)
|
||||
// self.vm.player?.seek(to: seekTime, completionHandler: { [weak self] completed in
|
||||
// if completed{
|
||||
// guard let self else{return}
|
||||
// hideShowIndicator(isLoading: false)
|
||||
// vm.startTimer()
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// func hideShowIndicator(isLoading : Bool){
|
||||
// if isLoading{
|
||||
// self.imgPlay.isHidden = true
|
||||
// self.loadingIndicator.startAnimating()
|
||||
// }else{
|
||||
// self.imgPlay.isHidden = false
|
||||
// self.loadingIndicator.stopAnimating()
|
||||
// self.loadingIndicator.hidesWhenStopped = true
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @objc func onTapPlayPause() {
|
||||
// if self.vm.player?.timeControlStatus == .playing {
|
||||
// self.imgPlay.image = UIImage(systemName: "play.circle")
|
||||
// self.vm.player?.pause()
|
||||
// } else {
|
||||
// self.imgPlay.image = UIImage(systemName: "pause.circle")
|
||||
// self.vm.player?.play()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @objc func onTapToSlide() {
|
||||
// if vm.timer != nil{
|
||||
// vm.timer?.invalidate()
|
||||
// vm.timer = nil
|
||||
// }
|
||||
// self.vm.isThumbSeek = true
|
||||
// guard let duration = self.vm.player?.currentItem?.duration else { return }
|
||||
// let value = Float64(self.seekSlider.value) * CMTimeGetSeconds(duration)
|
||||
// if value.isNaN == false {
|
||||
// let seekTime = CMTime(value: CMTimeValue(value), timescale: 1)
|
||||
// self.vm.player?.seek(to: seekTime, completionHandler: { completed in
|
||||
// if completed {
|
||||
// self.vm.isThumbSeek = false
|
||||
// self.vm.startTimer()
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
||||
// if keyPath == "rate" {
|
||||
// if let player = object as? AVPlayer {
|
||||
// if player.rate == 0 {
|
||||
// print("Player is paused")
|
||||
// } else {
|
||||
// print("Player is playing")
|
||||
// hideShowIndicator(isLoading: false)
|
||||
// imgPlay.image = UIImage(systemName: "pause.circle")
|
||||
// }
|
||||
// }
|
||||
// } else if let playerItem = object as? AVPlayerItem {
|
||||
// if keyPath == "isPlaybackBufferEmpty" {
|
||||
// if playerItem.isPlaybackBufferEmpty {
|
||||
// print("Loading")
|
||||
// hideShowIndicator(isLoading: true)
|
||||
// }
|
||||
// } else if keyPath == "isPlaybackLikelyToKeepUp" {
|
||||
// if playerItem.isPlaybackLikelyToKeepUp {
|
||||
// print("finished")
|
||||
// hideShowIndicator(isLoading: false)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//// // Observe for player item status changes
|
||||
//// override func observeValue(forKeyPath keyPath: String?,
|
||||
//// of object: Any?,
|
||||
//// change: [NSKeyValueChangeKey : Any]?,
|
||||
//// context: UnsafeMutableRawPointer?) {
|
||||
//// if keyPath == "status" {
|
||||
//// if let playerItem = object as? AVPlayerItem {
|
||||
//// switch playerItem.status {
|
||||
//// case .readyToPlay:
|
||||
//// // Ready to play
|
||||
//// print("Player item is ready to play.")
|
||||
//// vm.player?.play()
|
||||
//// hideShowIndicator(isLoading: false)
|
||||
//// imgPlay.image = UIImage(systemName: "pause.circle")
|
||||
//// case .failed:
|
||||
//// // Failed
|
||||
//// if let error = playerItem.error {
|
||||
//// print("Player item error: \(error.localizedDescription)")
|
||||
//// vm.handlePlayerError(error)
|
||||
//// }
|
||||
//// case .unknown:
|
||||
//// // Unknown status
|
||||
//// print("Player item status is unknown.")
|
||||
//// @unknown default:
|
||||
//// // Handle unexpected cases
|
||||
//// print("Player item status is unknown.")
|
||||
//// }
|
||||
//// }
|
||||
//// }
|
||||
//// }
|
||||
//
|
||||
//// @objc private func onTapToggleScreen() {
|
||||
//// if #available(iOS 16.0, *) {
|
||||
//// guard let windowSceen = self.view.window?.windowScene else { return }
|
||||
//// if windowSceen.interfaceOrientation == .portrait {
|
||||
//// windowSceen.requestGeometryUpdate(.iOS(interfaceOrientations: .landscape)) { error in
|
||||
//// print(error.localizedDescription)
|
||||
//// }
|
||||
//// } else {
|
||||
//// windowSceen.requestGeometryUpdate(.iOS(interfaceOrientations: .portrait)) { error in
|
||||
//// print(error.localizedDescription)
|
||||
//// }
|
||||
//// }
|
||||
//// } else {
|
||||
//// if UIDevice.current.orientation == .portrait {
|
||||
//// let orientation = UIInterfaceOrientation.landscapeRight.rawValue
|
||||
//// UIDevice.current.setValue(orientation, forKey: "orientation")
|
||||
//// } else {
|
||||
//// let orientation = UIInterfaceOrientation.portrait.rawValue
|
||||
//// UIDevice.current.setValue(orientation, forKey: "orientation")
|
||||
//// }
|
||||
//// }
|
||||
//// }
|
||||
//}
|
||||
247
WOKA/Karaoke/DumpFiles/AVPlayerVM.swift
Normal file
247
WOKA/Karaoke/DumpFiles/AVPlayerVM.swift
Normal file
@@ -0,0 +1,247 @@
|
||||
////
|
||||
//// AVPlayerVM.swift
|
||||
//// WOKA
|
||||
////
|
||||
//// Created by Bilal on 05/07/2024.
|
||||
////
|
||||
//
|
||||
//import UIKit
|
||||
//import AVKit
|
||||
//
|
||||
//class AVPlayerVM{
|
||||
//
|
||||
// weak var vc : AVPlayerVC!
|
||||
//
|
||||
// var player : AVPlayer? = nil
|
||||
// var isThumbSeek : Bool = false
|
||||
// var timer : Timer?
|
||||
// var isFinished = false{
|
||||
// didSet{
|
||||
// if isFinished{
|
||||
// timer?.invalidate()
|
||||
// timer = nil
|
||||
// vc.reloadBtn.isHidden = false
|
||||
// vc.stackCtrView.isHidden = true
|
||||
// vc.tintView.isHidden = false
|
||||
// vc.sliderStack.isHidden = true
|
||||
// }else{
|
||||
// vc.reloadBtn.isHidden = true
|
||||
// vc.stackCtrView.isHidden = false
|
||||
// vc.sliderStack.isHidden = false
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private var playerLayer : AVPlayerLayer? = nil
|
||||
// private var timeObserver : Any? = nil
|
||||
//
|
||||
// func initView(){
|
||||
// vc.seekSlider.transform = CGAffineTransform(scaleX: 0.85, y: 0.85)
|
||||
//
|
||||
// self.vc.videoTitle.text = vc.titleVideo
|
||||
// setupKaraoke()
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @objc func videoDidFinish() {
|
||||
// self.isFinished = true
|
||||
//
|
||||
// }
|
||||
//
|
||||
// func setupKaraoke(){
|
||||
// guard let url = vc.videoURL else{return}
|
||||
// hideShowKaraoke(isLoading: true)
|
||||
// let avURL = URL(string: url)!
|
||||
// let asset = AVAsset(url: avURL)
|
||||
//
|
||||
// let outputURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("\(vc.titleVideo?.trimmingCharacters(in: .whitespaces) ?? "extractedAudio").m4a")
|
||||
// FileManager.default.clearTmpDirectory()
|
||||
// asset.writeAudioTrackToURL(outputURL) { [weak self] isDone, error,url in
|
||||
// guard let self else{return}
|
||||
// print(isDone, error , url)
|
||||
// if error == nil{
|
||||
// hideShowKaraoke(isLoading: false)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// func hideShowKaraoke(isLoading : Bool){
|
||||
// DispatchQueue.main.async { [weak self] in
|
||||
// guard let self else{return}
|
||||
// if isLoading{
|
||||
// vc.karaokeLoading.startAnimating()
|
||||
// vc.karaokeStack.isHidden = false
|
||||
// vc.playPauseRecordStack.isHidden = true
|
||||
// }else{
|
||||
// vc.karaokeLoading.stopAnimating()
|
||||
// vc.karaokeLoading.hidesWhenStopped = true
|
||||
// vc.karaokeStack.isHidden = true
|
||||
// vc.playPauseRecordStack.isHidden = false
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // MARK: - Setup Video Player
|
||||
//
|
||||
// func setVideoPlayer() {
|
||||
// guard let videoURL = vc.videoURL, let url = URL(string: videoURL) else { return }
|
||||
//
|
||||
// if self.player == nil {
|
||||
//
|
||||
// // Create a subview for the video player
|
||||
// let playerView = UIView(frame: vc.viewControll.bounds)
|
||||
// playerView.backgroundColor = .clear // Make sure the background is clear
|
||||
// vc.viewControll.addSubview(playerView)
|
||||
// vc.viewControll.sendSubviewToBack(playerView) // Ensure the player view is below other UI elements
|
||||
//
|
||||
// // Initialize the player
|
||||
// let playerItem = AVPlayerItem(url: url)
|
||||
// player = AVPlayer(playerItem: playerItem)
|
||||
//
|
||||
// // Add observer for AVPlayerItemFailedToPlayToEndTimeNotification
|
||||
// NotificationCenter.default.addObserver(self,
|
||||
// selector: #selector(playerItemFailedToPlayToEndTime(_:)),
|
||||
// name: .AVPlayerItemFailedToPlayToEndTime,
|
||||
// object: playerItem)
|
||||
//
|
||||
// // Add observer for AVPlayerItem's status
|
||||
// playerItem.addObserver(self.vc,
|
||||
// forKeyPath: "status",
|
||||
// options: [.new, .initial],
|
||||
// context: nil)
|
||||
//
|
||||
// // Set up the player layer
|
||||
// playerLayer = AVPlayerLayer(player: player)
|
||||
// playerLayer?.videoGravity = .resizeAspectFill
|
||||
// playerLayer?.frame = playerView.bounds
|
||||
//
|
||||
// if let playerLayer = playerLayer {
|
||||
// playerView.layer.addSublayer(playerLayer)
|
||||
// }
|
||||
//
|
||||
// // Add observer for play/pause
|
||||
// player?.addObserver(self.vc, forKeyPath: "rate", options: [.new, .initial], context: nil)
|
||||
//
|
||||
// // Add observer for buffering
|
||||
// playerItem.addObserver(self.vc, forKeyPath: "isPlaybackBufferEmpty", options: [.new, .initial], context: nil)
|
||||
// playerItem.addObserver(self.vc, forKeyPath: "isPlaybackLikelyToKeepUp", options: [.new, .initial], context: nil)
|
||||
//
|
||||
// // Add observer for video finished playing
|
||||
// NotificationCenter.default.addObserver(self, selector: #selector(videoDidFinish), name: .AVPlayerItemDidPlayToEndTime, object: playerItem)
|
||||
// self.setObserverToPlayer()
|
||||
// startTimer()
|
||||
// player?.play()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// func reloadVideo() {
|
||||
// guard let videoURL = vc.videoURL, let url = URL(string: videoURL) else { return }
|
||||
//
|
||||
// // Remove existing observers
|
||||
// NotificationCenter.default.removeObserver(self, name: .AVPlayerItemDidPlayToEndTime, object: player?.currentItem)
|
||||
// player?.currentItem?.removeObserver(vc, forKeyPath: "status")
|
||||
// player?.currentItem?.removeObserver(vc, forKeyPath: "isPlaybackBufferEmpty")
|
||||
// player?.currentItem?.removeObserver(vc, forKeyPath: "isPlaybackLikelyToKeepUp")
|
||||
//
|
||||
// // Create a new player item
|
||||
// let playerItem = AVPlayerItem(url: url)
|
||||
// player?.replaceCurrentItem(with: playerItem)
|
||||
//
|
||||
// // Add observers again
|
||||
// NotificationCenter.default.addObserver(self, selector: #selector(videoDidFinish), name: .AVPlayerItemDidPlayToEndTime, object: playerItem)
|
||||
// playerItem.addObserver(vc, forKeyPath: "status", options: [.new, .initial], context: nil)
|
||||
// playerItem.addObserver(vc, forKeyPath: "isPlaybackBufferEmpty", options: [.new, .initial], context: nil)
|
||||
// playerItem.addObserver(vc, forKeyPath: "isPlaybackLikelyToKeepUp", options: [.new, .initial], context: nil)
|
||||
//
|
||||
// player?.play()
|
||||
// }
|
||||
//
|
||||
// func setObserverToPlayer() {
|
||||
// let interval = CMTime(seconds: 0.3, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
|
||||
// timeObserver = player?.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main, using: { elapsed in
|
||||
// self.updatePlayerTime()
|
||||
// })
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // Handle notification
|
||||
// @objc func playerItemFailedToPlayToEndTime(_ notification: Notification) {
|
||||
// if let error = notification.userInfo?[AVPlayerItemFailedToPlayToEndTimeErrorKey] as? Error {
|
||||
// print("Error: \(error.localizedDescription)")
|
||||
// handlePlayerError(error)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// func handlePlayerError(_ error: Error) {
|
||||
// // Update the UI or show an alert to the user
|
||||
// Utilities.alertWithBtnCompletion(title: "Error", msgBody: error.localizedDescription, okBtnStr: "Retry?", vc: vc.self) { [weak self] isDone in
|
||||
// guard let self else{return}
|
||||
// player?.play()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // MARK: - ShowHideControls
|
||||
// func startTimer(){
|
||||
// timer = Timer.scheduledTimer(withTimeInterval: 4.5, repeats: false) { _ in
|
||||
// self.showHideControls()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// func showHideControls(){
|
||||
// if isFinished{
|
||||
// vc.stackCtrView.isHidden = true
|
||||
// vc.reloadBtn.isHidden.toggle()
|
||||
// vc.sliderStack.isHidden = true
|
||||
// }else{
|
||||
// vc.reloadBtn.isHidden = true
|
||||
// vc.stackCtrView.isHidden.toggle()
|
||||
// vc.sliderStack.isHidden.toggle()
|
||||
// }
|
||||
//
|
||||
// vc.tintView.isHidden.toggle()
|
||||
//
|
||||
// if !vc.stackCtrView.isHidden{
|
||||
// startTimer()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // MARK: - Update the player time Label with Slider
|
||||
//
|
||||
// private func updatePlayerTime() {
|
||||
// guard let currentTime = self.player?.currentTime() else { return }
|
||||
// guard let duration = self.player?.currentItem?.duration else { return }
|
||||
//
|
||||
// let currentTimeInSecond = CMTimeGetSeconds(currentTime)
|
||||
// let durationTimeInSecond = CMTimeGetSeconds(duration)
|
||||
//
|
||||
// if self.isThumbSeek == false {
|
||||
// self.vc.seekSlider.value = Float(currentTimeInSecond/durationTimeInSecond)
|
||||
// }
|
||||
//
|
||||
// let value = Float64(self.vc.seekSlider.value) * CMTimeGetSeconds(duration)
|
||||
//
|
||||
// var hours = value / 3600
|
||||
// var mins = (value / 60).truncatingRemainder(dividingBy: 60)
|
||||
// var secs = value.truncatingRemainder(dividingBy: 60)
|
||||
// var timeformatter = NumberFormatter()
|
||||
// timeformatter.minimumIntegerDigits = 2
|
||||
// timeformatter.minimumFractionDigits = 0
|
||||
// timeformatter.roundingMode = .down
|
||||
// guard let hoursStr = timeformatter.string(from: NSNumber(value: hours)), let minsStr = timeformatter.string(from: NSNumber(value: mins)), let secsStr = timeformatter.string(from: NSNumber(value: secs)) else {
|
||||
// return
|
||||
// }
|
||||
// self.vc.lbCurrentTime.text = "\(hoursStr):\(minsStr):\(secsStr)"
|
||||
//
|
||||
// hours = durationTimeInSecond / 3600
|
||||
// mins = (durationTimeInSecond / 60).truncatingRemainder(dividingBy: 60)
|
||||
// secs = durationTimeInSecond.truncatingRemainder(dividingBy: 60)
|
||||
// timeformatter = NumberFormatter()
|
||||
// timeformatter.minimumIntegerDigits = 2
|
||||
// timeformatter.minimumFractionDigits = 0
|
||||
// timeformatter.roundingMode = .down
|
||||
// guard let hoursStr = timeformatter.string(from: NSNumber(value: hours)), let minsStr = timeformatter.string(from: NSNumber(value: mins)), let secsStr = timeformatter.string(from: NSNumber(value: secs)) else {
|
||||
// return
|
||||
// }
|
||||
// self.vc.lbTotalTime.text = "\(hoursStr):\(minsStr):\(secsStr)"
|
||||
// }
|
||||
//}
|
||||
120
WOKA/Karaoke/DumpFiles/TestingKaraokeVC.swift
Normal file
120
WOKA/Karaoke/DumpFiles/TestingKaraokeVC.swift
Normal file
@@ -0,0 +1,120 @@
|
||||
////
|
||||
//// TestingKaraokeVC.swift
|
||||
//// WOKA
|
||||
////
|
||||
//// Created by MacBook Pro on 09/07/24.
|
||||
////
|
||||
//
|
||||
//import AVFAudio
|
||||
//import UIKit
|
||||
//import AVFoundation
|
||||
//
|
||||
//class TestingKaraokeVC : UIViewController{
|
||||
//
|
||||
// var player: AVPlayer!
|
||||
// var audioEngine: AVAudioEngine!
|
||||
// var micInput: AVAudioInputNode!
|
||||
// var playerNode: AVAudioPlayerNode!
|
||||
// var audioFile: AVAudioFile!
|
||||
// var fileURL: URL!
|
||||
//
|
||||
// override func viewDidLoad() {
|
||||
// super.viewDidLoad()
|
||||
//
|
||||
// let videoURL = URL(string: "https://content.jwplatform.com/videos/DOhtETio-Ysj2G4DQ.mp4")!
|
||||
// setupPlayer(with: videoURL)
|
||||
// setupAudioEngine()
|
||||
// setupAudioFile()
|
||||
// }
|
||||
//
|
||||
// func setupPlayer(with url: URL) {
|
||||
// player = AVPlayer(url: url)
|
||||
// let playerLayer = AVPlayerLayer(player: player)
|
||||
// playerLayer.frame = view.bounds
|
||||
// view.layer.addSublayer(playerLayer)
|
||||
// player.play()
|
||||
// }
|
||||
//
|
||||
// func setupAudioEngine() {
|
||||
// audioEngine = AVAudioEngine()
|
||||
// micInput = audioEngine.inputNode
|
||||
// playerNode = AVAudioPlayerNode()
|
||||
//
|
||||
// audioEngine.attach(playerNode)
|
||||
// let format = micInput.inputFormat(forBus: 0)
|
||||
//
|
||||
// audioEngine.connect(micInput, to: audioEngine.mainMixerNode, format: format)
|
||||
// audioEngine.connect(playerNode, to: audioEngine.mainMixerNode, format: format)
|
||||
//
|
||||
// try! audioEngine.start()
|
||||
// }
|
||||
//
|
||||
// func setupAudioFile() {
|
||||
// let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
||||
// fileURL = documentsDirectory.appendingPathComponent("output.m4a")
|
||||
// let format = audioEngine.mainMixerNode.outputFormat(forBus: 0)
|
||||
//
|
||||
// do {
|
||||
// audioFile = try AVAudioFile(forWriting: fileURL, settings: format.settings)
|
||||
// } catch {
|
||||
// print("Error creating audio file: \(error)")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// func startRecording() {
|
||||
// let mixer = audioEngine.mainMixerNode
|
||||
// let format = mixer.outputFormat(forBus: 0)
|
||||
//
|
||||
// mixer.installTap(onBus: 0, bufferSize: 1024, format: format) { (buffer, time) in
|
||||
// do {
|
||||
// try self.audioFile.write(from: buffer)
|
||||
// } catch {
|
||||
// print("Error writing audio buffer: \(error)")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// func stopRecording() {
|
||||
// let mixer = audioEngine.mainMixerNode
|
||||
// mixer.removeTap(onBus: 0)
|
||||
//
|
||||
// // Save the file to Files app
|
||||
// presentDocumentPicker()
|
||||
// }
|
||||
//
|
||||
// func presentDocumentPicker() {
|
||||
// // let documentPicker = UIDocumentPickerViewController(forExporting: [fileURL])
|
||||
// // documentPicker.delegate = self
|
||||
// // present(documentPicker, animated: true, completion: nil)
|
||||
//
|
||||
// guard let mixedAudioURL = fileURL else { return }
|
||||
// DispatchQueue.main.async {
|
||||
// let documentPicker = UIDocumentPickerViewController(url: mixedAudioURL, in: .exportToService)
|
||||
// documentPicker.delegate = self
|
||||
// self.present(documentPicker, animated: true, completion: nil)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @IBAction func startButtonPressed(_ sender: UIButton) {
|
||||
// startRecording()
|
||||
// }
|
||||
//
|
||||
// @IBAction func stopButtonPressed(_ sender: UIButton) {
|
||||
// stopRecording()
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//extension TestingKaraokeVC: UIDocumentPickerDelegate {
|
||||
// func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
|
||||
// guard let selectedURL = urls.first else { return }
|
||||
// do {
|
||||
// try FileManager.default.moveItem(at: fileURL, to: selectedURL)
|
||||
// } catch {
|
||||
// print("Error saving file to Files app: \(error)")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
|
||||
// print("Document picker was cancelled")
|
||||
// }
|
||||
//}
|
||||
@@ -13,9 +13,6 @@
|
||||
<array key="Exo2-Bold.ttf">
|
||||
<string>Exo2-Bold</string>
|
||||
</array>
|
||||
<array key="Exo2-Medium.ttf">
|
||||
<string>Exo2-Medium</string>
|
||||
</array>
|
||||
<array key="Exo2-Regular.ttf">
|
||||
<string>Exo2-Regular</string>
|
||||
</array>
|
||||
@@ -582,318 +579,6 @@
|
||||
</objects>
|
||||
<point key="canvasLocation" x="900" y="-27"/>
|
||||
</scene>
|
||||
<!--PlayerVC-->
|
||||
<scene sceneID="Lao-sU-GdG">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="AVPlayerVC" id="kQu-aO-Siv" customClass="AVPlayerVC" customModule="WOKA" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="yFi-ud-U3v">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" translatesAutoresizingMaskIntoConstraints="NO" id="s55-L0-QBA" userLabel="PlayerView">
|
||||
<rect key="frame" x="0.0" y="330" width="414" height="250"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" translatesAutoresizingMaskIntoConstraints="NO" id="l7y-7N-uz2">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="250"/>
|
||||
<subviews>
|
||||
<view alpha="0.5" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7Lc-Yp-x8G">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="250"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</view>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" spacing="6" translatesAutoresizingMaskIntoConstraints="NO" id="Mhh-bR-zKm" userLabel="SliderStack">
|
||||
<rect key="frame" x="5" y="218" width="404" height="30"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="00:00:00" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="PZq-WO-H32">
|
||||
<rect key="frame" x="0.0" y="0.0" width="50" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="50" id="nYl-FL-Ois"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" name="Exo2-Medium" family="Exo 2" pointSize="11"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<slider toolTip="Slide" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="VKq-Xn-4Nn">
|
||||
<rect key="frame" x="54" y="0.0" width="296" height="31"/>
|
||||
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="minimumTrackTintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="maximumTrackTintColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="thumbTintColor" systemColor="systemRedColor"/>
|
||||
</slider>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" usesAttributedText="YES" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="0xZ-En-mzk">
|
||||
<rect key="frame" x="354" y="0.0" width="50" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="50" id="13R-ht-Ooc"/>
|
||||
</constraints>
|
||||
<attributedString key="attributedText">
|
||||
<fragment content="00:00:00">
|
||||
<attributes>
|
||||
<color key="NSColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<font key="NSFont" size="11" name="Exo2-Medium"/>
|
||||
<paragraphStyle key="NSParagraphStyle" alignment="center" lineBreakMode="truncatingTail" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
|
||||
</attributes>
|
||||
</fragment>
|
||||
</attributedString>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</stackView>
|
||||
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="bfi-XW-XRq">
|
||||
<rect key="frame" x="187" y="105" width="40" height="40"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="40" id="ZgN-fk-hLp"/>
|
||||
<constraint firstAttribute="width" constant="40" id="sNR-VY-L1S"/>
|
||||
</constraints>
|
||||
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
|
||||
<state key="normal" image="Reload"/>
|
||||
<connections>
|
||||
<action selector="reloadBtnTapped:" destination="kQu-aO-Siv" eventType="touchUpInside" id="WGb-aJ-m6E"/>
|
||||
</connections>
|
||||
</button>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="6xv-b4-3da">
|
||||
<rect key="frame" x="102" y="100" width="210" height="50"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="M0h-b5-LXf">
|
||||
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.80000000000000004" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="gobackward.10" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="IKL-qY-FkR">
|
||||
<rect key="frame" x="10" y="8.5" width="30" height="31"/>
|
||||
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="fYi-bd-7Oh"/>
|
||||
<constraint firstAttribute="width" secondItem="IKL-qY-FkR" secondAttribute="height" multiplier="1:1" id="pb2-c9-VEp"/>
|
||||
<constraint firstAttribute="width" constant="30" id="qsk-r1-nkf"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="IKL-qY-FkR" firstAttribute="centerY" secondItem="M0h-b5-LXf" secondAttribute="centerY" id="Qan-Kc-atl"/>
|
||||
<constraint firstItem="IKL-qY-FkR" firstAttribute="centerX" secondItem="M0h-b5-LXf" secondAttribute="centerX" id="TLc-gj-6lL"/>
|
||||
<constraint firstAttribute="width" secondItem="M0h-b5-LXf" secondAttribute="height" multiplier="1:1" id="sg0-5u-jyP"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="TPR-zt-HTV">
|
||||
<rect key="frame" x="70" y="0.0" width="70" height="50"/>
|
||||
<subviews>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="medium" translatesAutoresizingMaskIntoConstraints="NO" id="sBj-K5-TGW">
|
||||
<rect key="frame" x="0.0" y="0.0" width="20" height="50"/>
|
||||
<color key="color" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</activityIndicatorView>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="play.circle" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="IXg-pG-vEl">
|
||||
<rect key="frame" x="20" y="0.5" width="50" height="49"/>
|
||||
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="IXg-pG-vEl" secondAttribute="height" multiplier="1:1" id="HvT-nI-eDI"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
</subviews>
|
||||
</stackView>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Odf-qx-Pl1">
|
||||
<rect key="frame" x="160" y="0.0" width="50" height="50"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" alpha="0.80000000000000004" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="goforward.10" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="5Xm-AY-vbf">
|
||||
<rect key="frame" x="10" y="8.5" width="30" height="31"/>
|
||||
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="30" id="W0I-ls-sHd"/>
|
||||
<constraint firstAttribute="height" constant="30" id="fsd-FR-ina"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="5Xm-AY-vbf" firstAttribute="centerY" secondItem="Odf-qx-Pl1" secondAttribute="centerY" id="GaV-xD-TS9"/>
|
||||
<constraint firstItem="5Xm-AY-vbf" firstAttribute="centerX" secondItem="Odf-qx-Pl1" secondAttribute="centerX" id="Qdx-Kz-QQD"/>
|
||||
<constraint firstAttribute="width" secondItem="Odf-qx-Pl1" secondAttribute="height" multiplier="1:1" id="Yan-Ab-Yql"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="Jgh-NB-a3z"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="6xv-b4-3da" firstAttribute="centerY" secondItem="l7y-7N-uz2" secondAttribute="centerY" id="7EU-vQ-24M"/>
|
||||
<constraint firstItem="7Lc-Yp-x8G" firstAttribute="top" secondItem="l7y-7N-uz2" secondAttribute="top" id="CKx-0J-Lhi"/>
|
||||
<constraint firstItem="Mhh-bR-zKm" firstAttribute="leading" secondItem="l7y-7N-uz2" secondAttribute="leading" constant="5" id="FqT-om-cEo"/>
|
||||
<constraint firstAttribute="bottom" secondItem="7Lc-Yp-x8G" secondAttribute="bottom" id="Rm8-TM-tAn"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Mhh-bR-zKm" secondAttribute="bottom" constant="2" id="ZKX-ak-gaz"/>
|
||||
<constraint firstAttribute="trailing" secondItem="7Lc-Yp-x8G" secondAttribute="trailing" id="bNn-ua-lIq"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Mhh-bR-zKm" secondAttribute="trailing" constant="5" id="cOg-cb-irB"/>
|
||||
<constraint firstItem="7Lc-Yp-x8G" firstAttribute="leading" secondItem="l7y-7N-uz2" secondAttribute="leading" id="fLe-ch-yLB"/>
|
||||
<constraint firstItem="6xv-b4-3da" firstAttribute="centerX" secondItem="l7y-7N-uz2" secondAttribute="centerX" id="wM7-r1-Oob"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="l7y-7N-uz2" firstAttribute="leading" secondItem="s55-L0-QBA" secondAttribute="leading" id="4Hy-iL-uA7"/>
|
||||
<constraint firstAttribute="bottom" secondItem="l7y-7N-uz2" secondAttribute="bottom" id="BPP-v5-npt"/>
|
||||
<constraint firstAttribute="bottom" secondItem="l7y-7N-uz2" secondAttribute="bottom" id="Dpu-H8-UIT"/>
|
||||
<constraint firstAttribute="trailing" secondItem="l7y-7N-uz2" secondAttribute="trailing" id="Mgf-Yb-iW1"/>
|
||||
<constraint firstItem="l7y-7N-uz2" firstAttribute="leading" secondItem="s55-L0-QBA" secondAttribute="leading" id="Ppx-0A-xU4"/>
|
||||
<constraint firstAttribute="height" constant="250" id="VSu-g6-K76"/>
|
||||
<constraint firstItem="l7y-7N-uz2" firstAttribute="top" secondItem="s55-L0-QBA" secondAttribute="top" id="mcF-Rx-XSf"/>
|
||||
<constraint firstItem="bfi-XW-XRq" firstAttribute="centerX" secondItem="s55-L0-QBA" secondAttribute="centerX" id="o9m-rv-reu"/>
|
||||
<constraint firstAttribute="trailing" secondItem="l7y-7N-uz2" secondAttribute="trailing" id="r6B-rl-7Kz"/>
|
||||
<constraint firstItem="bfi-XW-XRq" firstAttribute="centerY" secondItem="s55-L0-QBA" secondAttribute="centerY" id="wKu-hs-VYd"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="hXe-Fv-Zk9">
|
||||
<rect key="frame" x="10" y="58" width="394" height="30"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="NA" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="alm-nS-A2I">
|
||||
<rect key="frame" x="0.0" y="0.0" width="354" height="30"/>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="18"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="jlb-0g-59l">
|
||||
<rect key="frame" x="364" y="0.0" width="30" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="jlb-0g-59l" secondAttribute="height" multiplier="1:1" id="9KW-Ku-fD3"/>
|
||||
<constraint firstAttribute="width" secondItem="jlb-0g-59l" secondAttribute="height" multiplier="1:1" id="Ig1-El-cep"/>
|
||||
</constraints>
|
||||
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
|
||||
<state key="normal" image="CloseIconEmpty"/>
|
||||
<connections>
|
||||
<action selector="closeBtnTapped:" destination="kQu-aO-Siv" eventType="touchUpInside" id="Muc-ee-FGZ"/>
|
||||
<action selector="closeBtnTapped:" destination="fax-bi-Mb9" eventType="touchUpInside" id="jMq-CG-juV"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</stackView>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="15" translatesAutoresizingMaskIntoConstraints="NO" id="jTd-8Q-0y7">
|
||||
<rect key="frame" x="25" y="658" width="364" height="86"/>
|
||||
<subviews>
|
||||
<stackView hidden="YES" opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="vq6-xr-Jba">
|
||||
<rect key="frame" x="0.0" y="0.0" width="364" height="10"/>
|
||||
<subviews>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="medium" translatesAutoresizingMaskIntoConstraints="NO" id="Yr0-AW-uh9">
|
||||
<rect key="frame" x="0.0" y="0.0" width="364" height="0.0"/>
|
||||
<color key="color" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</activityIndicatorView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Loading Karaoke..." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Jww-Ym-BQw">
|
||||
<rect key="frame" x="0.0" y="10" width="364" height="0.0"/>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="15"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</stackView>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="15" translatesAutoresizingMaskIntoConstraints="NO" id="MVs-Fv-8PY">
|
||||
<rect key="frame" x="0.0" y="0.0" width="364" height="86"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="gLz-mh-ln0">
|
||||
<rect key="frame" x="0.0" y="0.0" width="364" height="50"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4KA-5y-qg7" customClass="LocalisedElementsButton" customModule="WOKA" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="172" height="50"/>
|
||||
<color key="backgroundColor" red="1" green="0.23137254901960785" blue="0.18823529411764706" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="3ZS-GJ-VKY"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="14"/>
|
||||
<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="0.0" minY="0.0" maxX="5" maxY="0.0"/>
|
||||
<state key="normal" title="Start Recording" image="Microphone"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
|
||||
<integer key="value" value="25"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="playNowBtnTapped:" destination="fax-bi-Mb9" eventType="touchUpInside" id="dwL-Ob-ZbF"/>
|
||||
<action selector="startStopRecording:" destination="kQu-aO-Siv" eventType="touchUpInside" id="Ac4-9o-mfd"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="249" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dz2-DJ-auS" customClass="LocalisedElementsButton" customModule="WOKA" customModuleProvider="target">
|
||||
<rect key="frame" x="192" y="0.0" width="172" height="50"/>
|
||||
<color key="backgroundColor" name="TextDarkBlue"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="7d9-YY-TdQ"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="16"/>
|
||||
<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="Play" image="PlayButtonSmall"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
|
||||
<integer key="value" value="25"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="playNowBtnTapped:" destination="fax-bi-Mb9" eventType="touchUpInside" id="hwK-OY-rQq"/>
|
||||
<action selector="playPauseBtn:" destination="kQu-aO-Siv" eventType="touchUpInside" id="cI8-j7-ILD"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</stackView>
|
||||
<button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="k45-7s-jnN" customClass="LocalisedElementsButton" customModule="WOKA" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="65" width="364" height="21"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<fontDescription key="fontDescription" name=".AppleSystemUIFont" family=".AppleSystemUIFont" pointSize="16"/>
|
||||
<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="0.0" minY="0.0" maxX="5" maxY="0.0"/>
|
||||
<state key="normal" title="Download Recording" image="icloud.and.arrow.down.fill" catalog="system"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
|
||||
<integer key="value" value="25"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="playNowBtnTapped:" destination="fax-bi-Mb9" eventType="touchUpInside" id="owb-s2-DxU"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</stackView>
|
||||
</subviews>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<viewLayoutGuide key="safeArea" id="oGN-nm-I6a"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="s55-L0-QBA" firstAttribute="centerY" secondItem="oGN-nm-I6a" secondAttribute="centerY" id="3PR-ix-bDs"/>
|
||||
<constraint firstItem="s55-L0-QBA" firstAttribute="leading" secondItem="yFi-ud-U3v" secondAttribute="leading" id="4XW-Wj-pXp"/>
|
||||
<constraint firstItem="jTd-8Q-0y7" firstAttribute="leading" secondItem="oGN-nm-I6a" secondAttribute="leading" constant="25" id="9KV-Cx-Hoq"/>
|
||||
<constraint firstItem="oGN-nm-I6a" firstAttribute="trailing" secondItem="hXe-Fv-Zk9" secondAttribute="trailing" constant="10" id="BHo-KM-sod"/>
|
||||
<constraint firstItem="hXe-Fv-Zk9" firstAttribute="leading" secondItem="oGN-nm-I6a" secondAttribute="leading" constant="10" id="FLp-pS-iEw"/>
|
||||
<constraint firstItem="oGN-nm-I6a" firstAttribute="trailing" secondItem="jTd-8Q-0y7" secondAttribute="trailing" constant="25" id="UbH-Km-hc2"/>
|
||||
<constraint firstItem="hXe-Fv-Zk9" firstAttribute="top" secondItem="oGN-nm-I6a" secondAttribute="top" constant="10" id="ZyD-u6-icH"/>
|
||||
<constraint firstItem="oGN-nm-I6a" firstAttribute="trailing" secondItem="s55-L0-QBA" secondAttribute="trailing" id="bEp-Tx-cmK"/>
|
||||
<constraint firstItem="jTd-8Q-0y7" firstAttribute="top" secondItem="s55-L0-QBA" secondAttribute="bottom" constant="78" id="qj9-jV-aGM"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="img10SecBack" destination="IKL-qY-FkR" id="GuA-TX-UHu"/>
|
||||
<outlet property="img10SecFor" destination="5Xm-AY-vbf" id="LPy-C0-Twz"/>
|
||||
<outlet property="imgPlay" destination="IXg-pG-vEl" id="L33-Hc-mGN"/>
|
||||
<outlet property="karaokeLoading" destination="Yr0-AW-uh9" id="iRc-FO-gPb"/>
|
||||
<outlet property="karaokeStack" destination="vq6-xr-Jba" id="bZf-Re-O9f"/>
|
||||
<outlet property="lbCurrentTime" destination="PZq-WO-H32" id="n5q-bm-hVP"/>
|
||||
<outlet property="lbTotalTime" destination="0xZ-En-mzk" id="g1U-2U-svw"/>
|
||||
<outlet property="loadingIndicator" destination="sBj-K5-TGW" id="pAc-Hh-x7o"/>
|
||||
<outlet property="playPauseRecordStack" destination="MVs-Fv-8PY" id="l9s-Hj-0yj"/>
|
||||
<outlet property="reloadBtn" destination="bfi-XW-XRq" id="Rj3-kP-JxK"/>
|
||||
<outlet property="seekSlider" destination="VKq-Xn-4Nn" id="ims-DY-5HR"/>
|
||||
<outlet property="sliderStack" destination="Mhh-bR-zKm" id="Noa-Nd-AK4"/>
|
||||
<outlet property="stackCtrView" destination="6xv-b4-3da" id="BbF-dD-Iek"/>
|
||||
<outlet property="tintView" destination="7Lc-Yp-x8G" id="bOc-mG-HwG"/>
|
||||
<outlet property="videoTitle" destination="alm-nS-A2I" id="RQN-Uc-WgF"/>
|
||||
<outlet property="viewControll" destination="l7y-7N-uz2" id="zly-5u-1kS"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="4Za-1C-I6p" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1657.9710144927537" y="-27.455357142857142"/>
|
||||
</scene>
|
||||
<!--Karaoke PlayerVC-->
|
||||
<scene sceneID="76g-qy-5ia">
|
||||
<objects>
|
||||
@@ -959,7 +644,6 @@
|
||||
<connections>
|
||||
<action selector="playNowBtnTapped:" destination="fax-bi-Mb9" eventType="touchUpInside" id="ru7-Wv-EJr"/>
|
||||
<action selector="startRecordingBtnTapped:" destination="9gy-Qq-XHU" eventType="touchUpInside" id="2bh-Cr-Joy"/>
|
||||
<action selector="startStopRecording:" destination="kQu-aO-Siv" eventType="touchUpInside" id="7pG-pk-Hk5"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="249" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4rT-nK-Wb6" customClass="LocalisedElementsButton" customModule="WOKA" customModuleProvider="target">
|
||||
@@ -981,7 +665,6 @@
|
||||
<connections>
|
||||
<action selector="playBtnTapped:" destination="9gy-Qq-XHU" eventType="touchUpInside" id="WZm-M9-WLE"/>
|
||||
<action selector="playNowBtnTapped:" destination="fax-bi-Mb9" eventType="touchUpInside" id="NX9-0v-D3v"/>
|
||||
<action selector="playPauseBtn:" destination="kQu-aO-Siv" eventType="touchUpInside" id="bpF-JM-8Dq"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
@@ -1032,74 +715,7 @@
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="s0j-fC-RFe" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="2443" y="-27"/>
|
||||
</scene>
|
||||
<!--Testing KaraokeVC-->
|
||||
<scene sceneID="ISg-0i-f5X">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="TestingKaraokeVC" id="Ixs-R0-bqs" customClass="TestingKaraokeVC" customModule="WOKA" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="SEn-mb-vM4">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="ApB-WQ-WAf">
|
||||
<rect key="frame" x="20" y="712" width="374" height="50"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="K2c-bI-iaW" customClass="LocalisedElementsButton" customModule="WOKA" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="177" height="50"/>
|
||||
<color key="backgroundColor" red="1" green="0.044904738159999999" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="uXi-mu-IQ8"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="14"/>
|
||||
<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="0.0" minY="0.0" maxX="5" maxY="0.0"/>
|
||||
<state key="normal" title="Start Recording" image="Microphone"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
|
||||
<integer key="value" value="25"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="startButtonPressed:" destination="Ixs-R0-bqs" eventType="touchUpInside" id="zGF-yq-0o2"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="249" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="srX-WU-cle" customClass="LocalisedElementsButton" customModule="WOKA" customModuleProvider="target">
|
||||
<rect key="frame" x="197" y="0.0" width="177" height="50"/>
|
||||
<color key="backgroundColor" name="TextDarkBlue"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="wwk-CU-vet"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="16"/>
|
||||
<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="Play" image="PlayButtonSmall"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
|
||||
<integer key="value" value="25"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="stopButtonPressed:" destination="Ixs-R0-bqs" eventType="touchUpInside" id="TlD-dh-StE"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<viewLayoutGuide key="safeArea" id="t9O-c6-dcl"/>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||
<constraints>
|
||||
<constraint firstItem="ApB-WQ-WAf" firstAttribute="leading" secondItem="SEn-mb-vM4" secondAttribute="leading" constant="20" id="aa2-wO-FVT"/>
|
||||
<constraint firstItem="t9O-c6-dcl" firstAttribute="trailing" secondItem="ApB-WQ-WAf" secondAttribute="trailing" constant="20" id="cV0-l6-keq"/>
|
||||
<constraint firstItem="t9O-c6-dcl" firstAttribute="bottom" secondItem="ApB-WQ-WAf" secondAttribute="bottom" constant="100" id="cxI-Ia-Ggd"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="2b3-eU-9bD" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="3207" y="-27"/>
|
||||
<point key="canvasLocation" x="1672" y="-27"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
@@ -1109,14 +725,10 @@
|
||||
<image name="LikeRemove" width="42.5" height="42.5"/>
|
||||
<image name="Microphone" width="31" height="31"/>
|
||||
<image name="PlayButtonSmall" width="28.333333969116211" height="28.333333969116211"/>
|
||||
<image name="Reload" width="42.5" height="42.5"/>
|
||||
<image name="ShareImage" width="18" height="18"/>
|
||||
<image name="WebSeriesSeasonsBackground" width="142.66667175292969" height="187.33332824707031"/>
|
||||
<image name="gobackward.10" catalog="system" width="119" height="128"/>
|
||||
<image name="goforward.10" catalog="system" width="119" height="128"/>
|
||||
<image name="hand.thumbsup.fill" catalog="system" width="128" height="121"/>
|
||||
<image name="icloud.and.arrow.down.fill" catalog="system" width="128" height="111"/>
|
||||
<image name="play.circle" catalog="system" width="128" height="123"/>
|
||||
<namedColor name="ImageDarkBlue">
|
||||
<color red="0.035000000149011612" green="0.0" blue="0.36500000953674316" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</namedColor>
|
||||
@@ -1129,8 +741,5 @@
|
||||
<systemColor name="systemBackgroundColor">
|
||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</systemColor>
|
||||
<systemColor name="systemRedColor">
|
||||
<color red="1" green="0.23137254900000001" blue="0.18823529410000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
</resources>
|
||||
</document>
|
||||
|
||||
@@ -1,247 +0,0 @@
|
||||
//
|
||||
// AVPlayerVM.swift
|
||||
// WOKA
|
||||
//
|
||||
// Created by Bilal on 05/07/2024.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import AVKit
|
||||
|
||||
class AVPlayerVM{
|
||||
|
||||
weak var vc : AVPlayerVC!
|
||||
|
||||
var player : AVPlayer? = nil
|
||||
var isThumbSeek : Bool = false
|
||||
var timer : Timer?
|
||||
var isFinished = false{
|
||||
didSet{
|
||||
if isFinished{
|
||||
timer?.invalidate()
|
||||
timer = nil
|
||||
vc.reloadBtn.isHidden = false
|
||||
vc.stackCtrView.isHidden = true
|
||||
vc.tintView.isHidden = false
|
||||
vc.sliderStack.isHidden = true
|
||||
}else{
|
||||
vc.reloadBtn.isHidden = true
|
||||
vc.stackCtrView.isHidden = false
|
||||
vc.sliderStack.isHidden = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var playerLayer : AVPlayerLayer? = nil
|
||||
private var timeObserver : Any? = nil
|
||||
|
||||
func initView(){
|
||||
vc.seekSlider.transform = CGAffineTransform(scaleX: 0.85, y: 0.85)
|
||||
|
||||
self.vc.videoTitle.text = vc.titleVideo
|
||||
setupKaraoke()
|
||||
|
||||
}
|
||||
|
||||
@objc func videoDidFinish() {
|
||||
self.isFinished = true
|
||||
|
||||
}
|
||||
|
||||
func setupKaraoke(){
|
||||
guard let url = vc.videoURL else{return}
|
||||
hideShowKaraoke(isLoading: true)
|
||||
let avURL = URL(string: url)!
|
||||
let asset = AVAsset(url: avURL)
|
||||
|
||||
let outputURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("\(vc.titleVideo?.trimmingCharacters(in: .whitespaces) ?? "extractedAudio").m4a")
|
||||
FileManager.default.clearTmpDirectory()
|
||||
asset.writeAudioTrackToURL(outputURL) { [weak self] isDone, error,url in
|
||||
guard let self else{return}
|
||||
print(isDone, error , url)
|
||||
if error == nil{
|
||||
hideShowKaraoke(isLoading: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hideShowKaraoke(isLoading : Bool){
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self else{return}
|
||||
if isLoading{
|
||||
vc.karaokeLoading.startAnimating()
|
||||
vc.karaokeStack.isHidden = false
|
||||
vc.playPauseRecordStack.isHidden = true
|
||||
}else{
|
||||
vc.karaokeLoading.stopAnimating()
|
||||
vc.karaokeLoading.hidesWhenStopped = true
|
||||
vc.karaokeStack.isHidden = true
|
||||
vc.playPauseRecordStack.isHidden = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Setup Video Player
|
||||
|
||||
func setVideoPlayer() {
|
||||
guard let videoURL = vc.videoURL, let url = URL(string: videoURL) else { return }
|
||||
|
||||
if self.player == nil {
|
||||
|
||||
// Create a subview for the video player
|
||||
let playerView = UIView(frame: vc.viewControll.bounds)
|
||||
playerView.backgroundColor = .clear // Make sure the background is clear
|
||||
vc.viewControll.addSubview(playerView)
|
||||
vc.viewControll.sendSubviewToBack(playerView) // Ensure the player view is below other UI elements
|
||||
|
||||
// Initialize the player
|
||||
let playerItem = AVPlayerItem(url: url)
|
||||
player = AVPlayer(playerItem: playerItem)
|
||||
|
||||
// Add observer for AVPlayerItemFailedToPlayToEndTimeNotification
|
||||
NotificationCenter.default.addObserver(self,
|
||||
selector: #selector(playerItemFailedToPlayToEndTime(_:)),
|
||||
name: .AVPlayerItemFailedToPlayToEndTime,
|
||||
object: playerItem)
|
||||
|
||||
// Add observer for AVPlayerItem's status
|
||||
playerItem.addObserver(self.vc,
|
||||
forKeyPath: "status",
|
||||
options: [.new, .initial],
|
||||
context: nil)
|
||||
|
||||
// Set up the player layer
|
||||
playerLayer = AVPlayerLayer(player: player)
|
||||
playerLayer?.videoGravity = .resizeAspectFill
|
||||
playerLayer?.frame = playerView.bounds
|
||||
|
||||
if let playerLayer = playerLayer {
|
||||
playerView.layer.addSublayer(playerLayer)
|
||||
}
|
||||
|
||||
// Add observer for play/pause
|
||||
player?.addObserver(self.vc, forKeyPath: "rate", options: [.new, .initial], context: nil)
|
||||
|
||||
// Add observer for buffering
|
||||
playerItem.addObserver(self.vc, forKeyPath: "isPlaybackBufferEmpty", options: [.new, .initial], context: nil)
|
||||
playerItem.addObserver(self.vc, forKeyPath: "isPlaybackLikelyToKeepUp", options: [.new, .initial], context: nil)
|
||||
|
||||
// Add observer for video finished playing
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(videoDidFinish), name: .AVPlayerItemDidPlayToEndTime, object: playerItem)
|
||||
self.setObserverToPlayer()
|
||||
startTimer()
|
||||
player?.play()
|
||||
}
|
||||
}
|
||||
|
||||
func reloadVideo() {
|
||||
guard let videoURL = vc.videoURL, let url = URL(string: videoURL) else { return }
|
||||
|
||||
// Remove existing observers
|
||||
NotificationCenter.default.removeObserver(self, name: .AVPlayerItemDidPlayToEndTime, object: player?.currentItem)
|
||||
player?.currentItem?.removeObserver(vc, forKeyPath: "status")
|
||||
player?.currentItem?.removeObserver(vc, forKeyPath: "isPlaybackBufferEmpty")
|
||||
player?.currentItem?.removeObserver(vc, forKeyPath: "isPlaybackLikelyToKeepUp")
|
||||
|
||||
// Create a new player item
|
||||
let playerItem = AVPlayerItem(url: url)
|
||||
player?.replaceCurrentItem(with: playerItem)
|
||||
|
||||
// Add observers again
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(videoDidFinish), name: .AVPlayerItemDidPlayToEndTime, object: playerItem)
|
||||
playerItem.addObserver(vc, forKeyPath: "status", options: [.new, .initial], context: nil)
|
||||
playerItem.addObserver(vc, forKeyPath: "isPlaybackBufferEmpty", options: [.new, .initial], context: nil)
|
||||
playerItem.addObserver(vc, forKeyPath: "isPlaybackLikelyToKeepUp", options: [.new, .initial], context: nil)
|
||||
|
||||
player?.play()
|
||||
}
|
||||
|
||||
func setObserverToPlayer() {
|
||||
let interval = CMTime(seconds: 0.3, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
|
||||
timeObserver = player?.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main, using: { elapsed in
|
||||
self.updatePlayerTime()
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// Handle notification
|
||||
@objc func playerItemFailedToPlayToEndTime(_ notification: Notification) {
|
||||
if let error = notification.userInfo?[AVPlayerItemFailedToPlayToEndTimeErrorKey] as? Error {
|
||||
print("Error: \(error.localizedDescription)")
|
||||
handlePlayerError(error)
|
||||
}
|
||||
}
|
||||
|
||||
func handlePlayerError(_ error: Error) {
|
||||
// Update the UI or show an alert to the user
|
||||
Utilities.alertWithBtnCompletion(title: "Error", msgBody: error.localizedDescription, okBtnStr: "Retry?", vc: vc.self) { [weak self] isDone in
|
||||
guard let self else{return}
|
||||
player?.play()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ShowHideControls
|
||||
func startTimer(){
|
||||
timer = Timer.scheduledTimer(withTimeInterval: 4.5, repeats: false) { _ in
|
||||
self.showHideControls()
|
||||
}
|
||||
}
|
||||
|
||||
func showHideControls(){
|
||||
if isFinished{
|
||||
vc.stackCtrView.isHidden = true
|
||||
vc.reloadBtn.isHidden.toggle()
|
||||
vc.sliderStack.isHidden = true
|
||||
}else{
|
||||
vc.reloadBtn.isHidden = true
|
||||
vc.stackCtrView.isHidden.toggle()
|
||||
vc.sliderStack.isHidden.toggle()
|
||||
}
|
||||
|
||||
vc.tintView.isHidden.toggle()
|
||||
|
||||
if !vc.stackCtrView.isHidden{
|
||||
startTimer()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Update the player time Label with Slider
|
||||
|
||||
private func updatePlayerTime() {
|
||||
guard let currentTime = self.player?.currentTime() else { return }
|
||||
guard let duration = self.player?.currentItem?.duration else { return }
|
||||
|
||||
let currentTimeInSecond = CMTimeGetSeconds(currentTime)
|
||||
let durationTimeInSecond = CMTimeGetSeconds(duration)
|
||||
|
||||
if self.isThumbSeek == false {
|
||||
self.vc.seekSlider.value = Float(currentTimeInSecond/durationTimeInSecond)
|
||||
}
|
||||
|
||||
let value = Float64(self.vc.seekSlider.value) * CMTimeGetSeconds(duration)
|
||||
|
||||
var hours = value / 3600
|
||||
var mins = (value / 60).truncatingRemainder(dividingBy: 60)
|
||||
var secs = value.truncatingRemainder(dividingBy: 60)
|
||||
var timeformatter = NumberFormatter()
|
||||
timeformatter.minimumIntegerDigits = 2
|
||||
timeformatter.minimumFractionDigits = 0
|
||||
timeformatter.roundingMode = .down
|
||||
guard let hoursStr = timeformatter.string(from: NSNumber(value: hours)), let minsStr = timeformatter.string(from: NSNumber(value: mins)), let secsStr = timeformatter.string(from: NSNumber(value: secs)) else {
|
||||
return
|
||||
}
|
||||
self.vc.lbCurrentTime.text = "\(hoursStr):\(minsStr):\(secsStr)"
|
||||
|
||||
hours = durationTimeInSecond / 3600
|
||||
mins = (durationTimeInSecond / 60).truncatingRemainder(dividingBy: 60)
|
||||
secs = durationTimeInSecond.truncatingRemainder(dividingBy: 60)
|
||||
timeformatter = NumberFormatter()
|
||||
timeformatter.minimumIntegerDigits = 2
|
||||
timeformatter.minimumFractionDigits = 0
|
||||
timeformatter.roundingMode = .down
|
||||
guard let hoursStr = timeformatter.string(from: NSNumber(value: hours)), let minsStr = timeformatter.string(from: NSNumber(value: mins)), let secsStr = timeformatter.string(from: NSNumber(value: secs)) else {
|
||||
return
|
||||
}
|
||||
self.vc.lbTotalTime.text = "\(hoursStr):\(minsStr):\(secsStr)"
|
||||
}
|
||||
}
|
||||
@@ -107,10 +107,10 @@ class ProductDetailsVM{
|
||||
Utilities.alert(title: "Error", message: data.message ?? K.ConstantString.unRecognised, viewController: self.vc)
|
||||
case 1:
|
||||
Utilities.dismissProgressHUD()
|
||||
self.vc.addToCartBtn.setTitle("Remove", for: .normal)
|
||||
self.vc.toast(msg: data.message ?? "Added to cart", time: 1) {
|
||||
if let productDetails = self.productDetails{
|
||||
CartDataCache.cartListData.append(CartListingDM.ResultData(id: productDetails.id, skuID: productDetails.skuID, productName: productDetails.productName, categoryMasterID: productDetails.categoryMasterID, subCategoryMasterID: productDetails.subCategoryMasterID, productPrice: productDetails.productPrice, remainStockQuantity: productDetails.remainStockQuantity, stockStatus: productDetails.stockStatus, taxValue: productDetails.taxValue, productQuantity: productDetails.remainStockQuantity, shopMasterDetail: productDetails.shopMasterDetail, shopImage: productDetails.shopImage, productFinalPrice: productDetails.productFinalPrice))
|
||||
self.vc.addToCartBtn.setTitle("Remove", for: .normal)
|
||||
self.updateCartIcon()
|
||||
}
|
||||
}
|
||||
@@ -149,13 +149,12 @@ class ProductDetailsVM{
|
||||
Utilities.alert(title: "Error", message: data.message ?? K.ConstantString.unRecognised, viewController: self.vc)
|
||||
case 1:
|
||||
Utilities.dismissProgressHUD()
|
||||
self.vc.addToCartBtn.setTitle("Add to Cart", for: .normal)
|
||||
self.vc.toast(msg: data.message ?? "Removed from cart", time: 1) {
|
||||
self.productDetails?.addedToCart = false
|
||||
|
||||
if let index = CartDataCache.cartListData.firstIndex(where: {$0.id == self.productDetails?.id}){
|
||||
CartDataCache.cartListData.remove(at: index)
|
||||
self.updateCartIcon()
|
||||
self.vc.addToCartBtn.setTitle("Add to Cart", for: .normal)
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -43,7 +43,7 @@ class WebSeriesSeasonVM{
|
||||
if AuthFunc.shareInstance.guestUserLoginPopUp() { return}
|
||||
|
||||
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}
|
||||
|
||||
|
||||
if isFav {
|
||||
//remove
|
||||
LikeFavCommonFunc.shareInstance.removeFavourite(postID: showID, postType: postType, categoryID: categoryID, vc: self.vc) { isDone in
|
||||
@@ -78,7 +78,7 @@ class WebSeriesSeasonVM{
|
||||
K.GVar.myListSoftReload = true
|
||||
}else{ // english
|
||||
guard let showData = self.showData else{return}
|
||||
MyListDataTemp.shareInstance.webSeriesHindi.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, categoryMasterID: showData.categoryMasterID, ageRangeMasterID: showData.ageRangeMasterID, genderMasterID: showData.genderMasterID, contentMoreDetails: showData.contentMoreDetails, markAsFavourite: showData.markAsFavourite, isLiked: showData.isLiked, likesCount: showData.likesCount, viewsCount: showData.viewsCount, bookmarkCount: showData.bookmarkCount, bookmarkCategoryIDS: "1"))
|
||||
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, categoryMasterID: showData.categoryMasterID, ageRangeMasterID: showData.ageRangeMasterID, genderMasterID: showData.genderMasterID, contentMoreDetails: showData.contentMoreDetails, markAsFavourite: showData.markAsFavourite, isLiked: showData.isLiked, likesCount: showData.likesCount, viewsCount: showData.viewsCount, bookmarkCount: showData.bookmarkCount, bookmarkCategoryIDS: "1"))
|
||||
K.GVar.myListSoftReload = true
|
||||
}
|
||||
}
|
||||
@@ -136,7 +136,13 @@ class WebSeriesSeasonVM{
|
||||
}
|
||||
|
||||
vc.shareView.addTapGesture {
|
||||
print("share")
|
||||
if let name = URL(string: "https://apps.apple.com/in/app/woka/id6465305185"), !name.absoluteString.isEmpty {
|
||||
let objectsToShare = [name]
|
||||
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
|
||||
self.vc.present(activityVC, animated: true, completion: nil)
|
||||
} else {
|
||||
// show alert for not available
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user