- Working on Song listing, Reworked

- Added a global handling of timer and cell reuse.
- Fixed the issue of song timer. Made the AvPlayer Optional to handle multiple instances
- Made a logic to handle the player stop. matched the current time with the total time.
This commit is contained in:
2024-06-12 19:47:40 +05:30
parent 5164f2fe10
commit 4887db2d4a
8 changed files with 266 additions and 163 deletions

View File

@@ -38,6 +38,7 @@
</dict>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
<string>remote-notification</string>
</array>
</dict>

View File

@@ -9,6 +9,7 @@ import UIKit
import Lottie
import IQKeyboardManagerSwift
import JWPlayerKit
import AVFAudio
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
@@ -40,10 +41,21 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
configureSideBar()
JWPlayerKitLicense.setLicenseKey("Lgok1t7H4PKY+M8FZqmCx54ibUF+NeCTn+xgd+/LVTaRdc+L")
setupAudioSession()
return true
}
func setupAudioSession() {
let session = AVAudioSession.sharedInstance()
do {
try session.setCategory(.playback, mode: .default)
try session.setActive(true)
} catch {
print("Failed to set up audio session")
}
}
// var myOrientation: UIInterfaceOrientationMask = .portrait
//
// func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {

View File

@@ -131,7 +131,7 @@
<rect key="frame" x="0.0" y="58" width="414" height="729"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="49" translatesAutoresizingMaskIntoConstraints="NO" id="5wC-Rc-bx0">
<rect key="frame" x="0.0" y="0.0" width="414" height="567"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="569"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="WokaLogo" translatesAutoresizingMaskIntoConstraints="NO" id="qyO-EY-Xz8">
<rect key="frame" x="15" y="10" width="384" height="50"/>
@@ -225,16 +225,16 @@
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="SlR-If-pxh" userLabel="Subject">
<rect key="frame" x="15" y="278" width="384" height="76"/>
<rect key="frame" x="15" y="278" width="384" height="77"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Subject" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="k7q-3i-LMr">
<rect key="frame" x="0.0" y="0.0" width="384" height="21"/>
<rect key="frame" x="0.0" y="0.0" width="384" height="22"/>
<fontDescription key="fontDescription" name="Exo2-Regular" family="Exo 2" pointSize="18"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3td-Os-A3X">
<rect key="frame" x="0.0" y="26" width="384" height="50"/>
<rect key="frame" x="0.0" y="27" width="384" height="50"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Select Subject" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="CoP-oH-nkk">
<rect key="frame" x="15" y="10" width="329" height="30"/>
@@ -259,16 +259,16 @@
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="gXQ-Yb-IGC" userLabel="Message">
<rect key="frame" x="15" y="403" width="384" height="154"/>
<rect key="frame" x="15" y="404" width="384" height="155"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Message" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="csz-ff-Kvd">
<rect key="frame" x="0.0" y="0.0" width="384" height="21"/>
<rect key="frame" x="0.0" y="0.0" width="384" height="22"/>
<fontDescription key="fontDescription" name="Exo2-Regular" family="Exo 2" pointSize="18"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="PNw-eT-0fE" customClass="RSKPlaceholderTextView" customModule="RSKPlaceholderTextView">
<rect key="frame" x="0.0" y="26" width="384" height="128"/>
<rect key="frame" x="0.0" y="27" width="384" height="128"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" name="TextDarkBlue"/>
<constraints>
@@ -378,10 +378,10 @@
<rect key="frame" x="0.0" y="48" width="414" height="726"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="35" translatesAutoresizingMaskIntoConstraints="NO" id="uGa-bS-ctr">
<rect key="frame" x="0.0" y="30" width="414" height="726.5"/>
<rect key="frame" x="0.0" y="30" width="414" height="730.5"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="Hvk-Z2-3ji">
<rect key="frame" x="20" y="0.0" width="374" height="115.5"/>
<rect key="frame" x="20" y="0.0" width="374" height="116.5"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="rbx-B4-wDn">
<rect key="frame" x="0.0" y="0.0" width="374" height="80"/>
@@ -403,7 +403,7 @@
</constraints>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="USER" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="clP-p2-fQj">
<rect key="frame" x="0.0" y="85" width="374" height="30.5"/>
<rect key="frame" x="0.0" y="85" width="374" height="31.5"/>
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="26"/>
<color key="textColor" red="0.035294117649999998" green="0.0" blue="0.36470588240000001" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
@@ -411,16 +411,16 @@
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="15" translatesAutoresizingMaskIntoConstraints="NO" id="GK8-Ov-3Lf" userLabel="NAME">
<rect key="frame" x="20" y="150.5" width="374" height="99"/>
<rect key="frame" x="20" y="151.5" width="374" height="99.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="FULL NAME" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dWX-YE-TV0" customClass="LocalisedElementsLabel" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="374" height="19"/>
<rect key="frame" x="0.0" y="0.0" width="374" height="19.5"/>
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="16"/>
<color key="textColor" red="0.035294117649999998" green="0.0" blue="0.36470588240000001" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" horizontalHuggingPriority="248" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Enter your name" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="arD-av-w7V" customClass="TextFieldShadow" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="0.0" y="34" width="374" height="50"/>
<rect key="frame" x="0.0" y="34.5" width="374" height="50"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" name="TextDarkBlue"/>
<constraints>
@@ -439,7 +439,7 @@
</userDefinedRuntimeAttributes>
</textField>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Avp-CK-Tfh">
<rect key="frame" x="0.0" y="99" width="374" height="0.0"/>
<rect key="frame" x="0.0" y="99.5" width="374" height="0.0"/>
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="16"/>
<color key="textColor" red="0.035294117649999998" green="0.0" blue="0.36470588240000001" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
@@ -447,16 +447,16 @@
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="15" translatesAutoresizingMaskIntoConstraints="NO" id="mF6-Ik-pdq" userLabel="EMAIL">
<rect key="frame" x="20" y="284.5" width="374" height="99"/>
<rect key="frame" x="20" y="286" width="374" height="99.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="EMAIL" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lss-KC-4LQ" customClass="LocalisedElementsLabel" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="374" height="19"/>
<rect key="frame" x="0.0" y="0.0" width="374" height="19.5"/>
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="16"/>
<color key="textColor" red="0.035294117649999998" green="0.0" blue="0.36470588240000001" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<textField opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="248" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Enter your email" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="fZS-d6-t0h" customClass="TextFieldShadow" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="0.0" y="34" width="374" height="50"/>
<rect key="frame" x="0.0" y="34.5" width="374" height="50"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" name="TextDarkBlue"/>
<constraints>
@@ -475,7 +475,7 @@
</userDefinedRuntimeAttributes>
</textField>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JVa-mg-KVN">
<rect key="frame" x="0.0" y="99" width="374" height="0.0"/>
<rect key="frame" x="0.0" y="99.5" width="374" height="0.0"/>
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="16"/>
<color key="textColor" red="0.035294117649999998" green="0.0" blue="0.36470588240000001" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
@@ -483,28 +483,28 @@
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="dTX-xS-I84" userLabel="GENDER">
<rect key="frame" x="20" y="418.5" width="374" height="137"/>
<rect key="frame" x="20" y="420.5" width="374" height="138"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="YOUR GENDER" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DEA-gr-l2e" customClass="LocalisedElementsLabel" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="374" height="21"/>
<rect key="frame" x="0.0" y="0.0" width="374" height="22"/>
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="18"/>
<color key="textColor" red="0.035294117649999998" green="0.0" blue="0.36470588240000001" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="60" translatesAutoresizingMaskIntoConstraints="NO" id="KhR-hP-jeC">
<rect key="frame" x="0.0" y="37" width="374" height="100"/>
<rect key="frame" x="0.0" y="38" width="374" height="100"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hhf-2M-dfy">
<rect key="frame" x="30" y="0.0" width="127" height="100"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="evt-gm-S0p">
<rect key="frame" x="39" y="10" width="49.5" height="76"/>
<rect key="frame" x="39" y="10" width="49.5" height="77"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Boy" translatesAutoresizingMaskIntoConstraints="NO" id="bty-6i-uBA">
<rect key="frame" x="0.0" y="0.0" width="49.5" height="50"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="BOY" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="y4t-AQ-VlC" customClass="LocalisedElementsLabel" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="0.0" y="55" width="49.5" height="21"/>
<rect key="frame" x="0.0" y="55" width="49.5" height="22"/>
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="18"/>
<color key="textColor" red="0.035294117649999998" green="0.0" blue="0.36470588240000001" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
@@ -522,13 +522,13 @@
<rect key="frame" x="217" y="0.0" width="127" height="100"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="9Tk-3P-f19">
<rect key="frame" x="39.5" y="10" width="48.5" height="76"/>
<rect key="frame" x="39.5" y="10" width="48.5" height="77"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Girl" translatesAutoresizingMaskIntoConstraints="NO" id="m4x-et-VAb">
<rect key="frame" x="0.0" y="0.0" width="48.5" height="50"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="GIRL" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="225-qf-t1b" customClass="LocalisedElementsLabel" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="0.0" y="55" width="48.5" height="21"/>
<rect key="frame" x="0.0" y="55" width="48.5" height="22"/>
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="18"/>
<color key="textColor" red="0.035294117649999998" green="0.0" blue="0.36470588240000001" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
@@ -551,16 +551,16 @@
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="15" translatesAutoresizingMaskIntoConstraints="NO" id="tlL-6r-4eb" userLabel="DOB">
<rect key="frame" x="20" y="590.5" width="374" height="136"/>
<rect key="frame" x="20" y="593.5" width="374" height="137"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="WHEN IS YOUR BIRTHDAY?" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="b73-2Y-tGO" customClass="LocalisedElementsLabel" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="374" height="21"/>
<rect key="frame" x="0.0" y="0.0" width="374" height="22"/>
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="18"/>
<color key="textColor" red="0.035294117649999998" green="0.0" blue="0.36470588240000001" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<datePicker contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" datePickerMode="date" style="wheels" translatesAutoresizingMaskIntoConstraints="NO" id="kau-8K-eQs">
<rect key="frame" x="0.0" y="36" width="374" height="100"/>
<rect key="frame" x="0.0" y="37" width="374" height="100"/>
<constraints>
<constraint firstAttribute="height" constant="100" id="QOf-a4-wdZ"/>
</constraints>
@@ -687,16 +687,16 @@
</scenes>
<designables>
<designable name="arD-av-w7V">
<size key="intrinsicContentSize" width="168" height="20.5"/>
<size key="intrinsicContentSize" width="169.5" height="21"/>
</designable>
<designable name="fZS-d6-t0h">
<size key="intrinsicContentSize" width="166" height="20.5"/>
<size key="intrinsicContentSize" width="169" height="21"/>
</designable>
<designable name="fiK-Gg-JDj">
<size key="intrinsicContentSize" width="168" height="20.5"/>
<size key="intrinsicContentSize" width="169.5" height="21"/>
</designable>
<designable name="zMI-2r-pRQ">
<size key="intrinsicContentSize" width="166" height="20.5"/>
<size key="intrinsicContentSize" width="169" height="21"/>
</designable>
</designables>
<resources>

View File

@@ -481,16 +481,16 @@
</constraints>
</view>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="U0W-18-4oe">
<rect key="frame" x="0.0" y="45" width="393" height="224"/>
<rect key="frame" x="0.0" y="45" width="393" height="214"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" text="Coming Soon on WOKA" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="D2p-c5-usH" customClass="LocalisedElementsLabel" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="10" y="10" width="373" height="24"/>
<rect key="frame" x="10" y="10" width="373" height="14"/>
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="20"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="UKc-92-GPa">
<rect key="frame" x="10" y="44" width="373" height="180"/>
<rect key="frame" x="10" y="34" width="373" height="180"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstAttribute="height" constant="180" id="gwN-aD-t1t"/>
@@ -500,7 +500,7 @@
<edgeInsets key="layoutMargins" top="10" left="10" bottom="0.0" right="10"/>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="Qcq-yj-AzB">
<rect key="frame" x="0.0" y="269" width="393" height="189"/>
<rect key="frame" x="0.0" y="259" width="393" height="199"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" text="BLOGS" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lW0-W4-2hl" customClass="LocalisedElementsLabel" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="10" y="10" width="373" height="24"/>
@@ -509,10 +509,10 @@
<nil key="highlightedColor"/>
</label>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="xup-gW-Kjh">
<rect key="frame" x="10" y="39" width="373" height="150"/>
<rect key="frame" x="10" y="39" width="373" height="160"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="150" id="fTZ-PQ-nXX"/>
<constraint firstAttribute="height" constant="160" id="fTZ-PQ-nXX"/>
</constraints>
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="6G1-Uh-Pwt">
<size key="itemSize" width="128" height="128"/>
@@ -757,7 +757,7 @@
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
<systemColor name="systemGreenColor">
<color red="0.20392156859999999" green="0.78039215689999997" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color red="0.20392156862745098" green="0.7803921568627451" blue="0.34901960784313724" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
</resources>
</document>

View File

@@ -16,7 +16,8 @@ class MoreVC: UIViewController {
@IBOutlet weak var songTableView: UITableView!
var vm = MoreVM()
var timeObserverToken: Any?
override func viewDidLoad() {
super.viewDidLoad()
vm.vc = self
@@ -24,7 +25,7 @@ class MoreVC: UIViewController {
}
override func viewWillDisappear(_ animated: Bool) {
vm.player.pause()
vm.player?.pause()
}
}
@@ -36,22 +37,16 @@ extension MoreVC : TableViewSRC{
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: K.CellIdentifier.Home.songListCell) as! SongListCell
let data = vm.songData[indexPath.row]
cell.setData(data: data,playerStatus: vm.playerStatus)
// if let playingIndex = vm.currentIndexPlayingSong {
// if indexPath.row == playingIndex{
// if vm.onGoingTime != nil{ // if index is nil that means its just paused
// cell.setData(data: data,playerStatus: vm.playerStatus,onGoingTime: vm.onGoingTime)
// }else{ // if index is there it means song is playing and needs to be paused
// cell.setData(data: data,playerStatus: .resume,onGoingTime: vm.onGoingTime)
// }
// }else{
// cell.setData(data: data,playerStatus: vm.playerStatus,onGoingTime: nil)
// }
// }else{
// cell.setData(data: data,playerStatus: .stopped ,onGoingTime: nil)
// }
let cell = tableView.dequeueReusableCell(withIdentifier: "SongListCell", for: indexPath) as! SongListCell
let songData = vm.songData[indexPath.row]
let isActive = (indexPath.row == vm.currentIndexPlayingSong)
if let index = vm.currentIndexPlayingSong , index == indexPath.row{
cell.setData(data: songData,playerStatus: vm.playerStatus, active: true, currentTime: currentTimePlayer)
}else{
cell.setData(data: songData,playerStatus: .stopped , active: false, currentTime: 0)
}
return cell
}
@@ -85,11 +80,15 @@ extension MoreVC : TableViewSRC{
if indexPath.row == playingIndex{ // if same row is selected pause the row
print(vm.playerStatus)
switch vm.playerStatus{
case .play:
case .play: // if player is playing pause it.
print("Player is playing")
vm.player.pause()
vm.player?.pause()
vm.playerStatus = .pause
tableView.reloadRows(at: [IndexPath(row: vm.currentIndexPlayingSong!, section: 0)], with: .none)
case .pause:
print("Player is pause")
vm.player?.play()
vm.playerStatus = .resume
tableView.reloadRows(at: [IndexPath(row: vm.currentIndexPlayingSong!, section: 0)], with: .none)
case .loading:
print("Player is loading")
case .resume:
@@ -102,16 +101,27 @@ extension MoreVC : TableViewSRC{
this means other cell was playing now stop it and play this new cell
first reload the playing cell and pause the audio
*/
//Reset Old Cell
vm.playerStatus = .stopped
tableView.reloadRows(at: [IndexPath(row: vm.currentIndexPlayingSong!, section: 0)], with: .none)
//Update new cell
vm.currentIndexPlayingSong = indexPath.row
vm.playerStatus = .loading
currentTimePlayer = 0
tableView.reloadRows(at: [indexPath], with: .none)
let data = vm.songData[indexPath.row]
startPlaying(song: data, at: indexPath)
print("Other cell playing")
}
}else{
// if there is no playing audio before
vm.playerStatus = .play
vm.playerStatus = .loading
vm.currentIndexPlayingSong = indexPath.row
currentTimePlayer = 0
tableView.reloadRows(at: [indexPath], with: .none)
let data = vm.songData[indexPath.row]
playSong(url: data.contentMoreDetails?.first?.url)
startPlaying(song: data, at: indexPath)
print("First Play")
}
}
@@ -130,11 +140,46 @@ extension MoreVC : TableViewSRC{
})
}
func playSong(url : String?){
if let url {
vm.player = AVPlayer(url: URL(string: url)!)
func startPlaying(song: SongBlogDM.PaintDatum, at indexPath: IndexPath) {
// Set up and start the player
stopPlaying()
if let urlString = song.contentMoreDetails?.first?.url , let url = URL(string: urlString){
vm.player = AVPlayer(url: url)
vm.player?.play()
vm.playerStatus = .play
vm.currentIndexPlayingSong = indexPath.row
addPeriodicTimeObserver()
vm.observePlayer()
vm.player.play()
}
}
func stopPlaying() {
// Remove the periodic time observer
removePeriodicTimeObserver()
// Stop the player
vm.player?.pause()
// vm.player = nil
vm.playerStatus = .stopped
vm.currentIndexPlayingSong = nil
}
func removePeriodicTimeObserver() {
if let token = timeObserverToken {
vm.player?.removeTimeObserver(token)
timeObserverToken = nil
}
}
func addPeriodicTimeObserver() {
let interval = CMTime(seconds: 1, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
timeObserverToken = vm.player?.addPeriodicTimeObserver(forInterval: interval, queue: .main) { [weak self] time in
guard let self = self else { return }
currentTimePlayer = Int(CMTimeGetSeconds(time))
if let currentPlayingIndex = self.vm.currentIndexPlayingSong,
let cell = self.songTableView.cellForRow(at: IndexPath(row: vm.currentIndexPlayingSong ?? 0, section: 0)) as? SongListCell {
cell.updateCurrentTime()
}
}
}

View File

@@ -29,14 +29,14 @@
<rect key="frame" x="10" y="10" width="204" height="170"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="5yh-us-azT">
<rect key="frame" x="0.0" y="0.0" width="204" height="100"/>
<rect key="frame" x="0.0" y="0.0" width="204" height="90"/>
<color key="backgroundColor" red="0.5450980392" green="0.67450980390000004" blue="0.17254901959999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="100" id="jAA-Oz-JN4"/>
<constraint firstAttribute="height" constant="90" id="LZS-Hb-uCN"/>
</constraints>
</imageView>
<stackView opaque="NO" contentMode="scaleToFill" alignment="top" translatesAutoresizingMaskIntoConstraints="NO" id="qgR-zD-wKz">
<rect key="frame" x="0.0" y="105" width="204" height="65"/>
<rect key="frame" x="0.0" y="95" width="204" height="75"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FXy-A6-Huz">
<rect key="frame" x="0.0" y="0.0" width="204" height="47"/>

View File

@@ -16,27 +16,11 @@ class SongListCell: UITableViewCell {
@IBOutlet weak var playPauseImage: UIImageView!
@IBOutlet weak var indicatorView: UIView!
// typealias btnTappedBlock = (String?) -> Void
// var btnTapped : btnTappedBlock!
var timer: Timer?
private var currentTime: Int = 0
var totalTime: Int = 0
// var timer: Timer?
override func awakeFromNib() {
super.awakeFromNib()
// self.addTapGesture { [weak self] in
// guard let self else{return}
// UIView.animate(withDuration: 0.1, animations: {
// self.outerStack.transform = CGAffineTransform(scaleX: 0.95, y: 0.95)
// }) { _ in
// UIView.animate(withDuration: 0.1) {
// self.outerStack.transform = .identity
// self.btnTapped(self.ongoingTimeLabel.text)
// }
// }
// }
}
override func setSelected(_ selected: Bool, animated: Bool) {
@@ -47,89 +31,57 @@ class SongListCell: UITableViewCell {
override func prepareForReuse() {
super.prepareForReuse()
// Invalidate the timer when the cell is reused
timer?.invalidate()
timer = nil
ongoingTimeLabel.text = "0:00"
currentTimePlayer = 0
// self.timer?.invalidate()
// self.timer = nil
}
func setData(data: SongBlogDM.PaintDatum, playerStatus: PlayerStatus) {
ongoingTimeLabel.text = "00:00"
totalTime = 0
currentTime = 0
func setData(data: SongBlogDM.PaintDatum, playerStatus: PlayerStatus, active: Bool, currentTime: Int) {
totalTime = data.songDuration?.timeStringToSeconds() ?? 0
ongoingTimeLabel.text = formatTime(currentTime)
playPauseImage.image = UIImage(systemName: "play.fill")
switch playerStatus{
case .stopped:
playPauseImage.image = UIImage(systemName: "play.fill")
case .pause:
playPauseImage.image = UIImage(systemName: "play.fill")
case .play:
playPauseImage.image = UIImage(systemName: "pause.fill")
totalTime = data.songDuration?.timeStringToSeconds() ?? 0
// if let onGoingTime{
// currentTime = onGoingTime.timeStringToSeconds() ?? 0
// ongoingTimeLabel.text = onGoingTime
// }else{
// currentTime = 0
// }
startCountdown()
case .resume:
playPauseImage.image = UIImage(systemName: "pause.fill")
totalTime = data.songDuration?.timeStringToSeconds() ?? 0
// if let onGoingTime{
// currentTime = onGoingTime.timeStringToSeconds() ?? 0
// ongoingTimeLabel.text = onGoingTime
// }else{
// currentTime = 0
// }
startCountdown()
case .loading:
break
if active {
ongoingTimeLabel.text = formatTime(currentTime)
switch playerStatus {
case .stopped:
showHideLoading(show: false)
playPauseImage.image = UIImage(systemName: "play.fill")
case .pause:
showHideLoading(show: false)
playPauseImage.image = UIImage(systemName: "play.fill")
case .play, .resume:
showHideLoading(show: false)
playPauseImage.image = UIImage(systemName: "pause.fill")
case .loading:
showHideLoading(show: true)
break
}
} else {
showHideLoading(show: false)
}
// Set total time label and song title
if let totalDuration = data.songDuration{
//Check of the hour is zero removing it
if let totalDuration = data.songDuration {
let totalTimeFiltered = totalDuration.checkHourZero()
totalTimeLabel.text = "/" + totalTimeFiltered
}else{
} else {
totalTimeLabel.text = "/" + (data.songDuration ?? "00:00")
}
songTitle.text = data.title ?? "Unknown Title"
}
private func startCountdown() {
// Invalidate any existing timer
timer?.invalidate()
// Schedule a new timer
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateCountdown), userInfo: nil, repeats: true)
func showHideLoading(show : Bool){
show ? self.indicatorView.showLoading() : self.indicatorView.hideLoading()
self.indicatorView.isHidden = !show
self.playPauseImage.isHidden = show
}
@objc private func updateCountdown() {
// Update the timer label
if currentTime < totalTime {
currentTime += 1
ongoingTimeLabel.text = formatTime(currentTime)
} else {
timer?.invalidate()
timer = nil
}
func updateCurrentTime() {
let timeInSeconds = Int(currentTimePlayer)
currentTimePlayer = timeInSeconds
ongoingTimeLabel.text = formatTime(currentTimePlayer)
}
// @objc private func updateCountdown() {
// // Update countdown label
// if totalTime > 0 {
// totalTime -= 1
// ongoingTimeLabel.text = formatTime(totalTime)
// } else {
// timer?.invalidate()
// timer = nil
// ongoingTimeLabel.text = "0:00"
// }
// }
private func formatTime(_ seconds: Int) -> String {
// Format time as MM:SS

View File

@@ -15,6 +15,10 @@ enum PlayerStatus{
case resume
case stopped
}
var currentTimePlayer = Int()
var totalTime = Int()
class MoreVM{
weak var vc : MoreVC!
@@ -23,7 +27,7 @@ class MoreVM{
var songData = [SongBlogDM.PaintDatum]()
var player = AVPlayer()
var player : AVPlayer?
var playerObserver: NSKeyValueObservation?
var playerStatus = PlayerStatus.loading
@@ -38,28 +42,37 @@ class MoreVM{
vc.homeBtn.addTapGesture {
self.vc.dismiss(animated: true)
}
}
func observePlayer() {
playerObserver = self.player.observe(\.timeControlStatus, options: [.new, .old], changeHandler: { [weak self] player, change in
playerObserver = self.player?.observe(\.timeControlStatus, options: [.new, .old], changeHandler: { [weak self] player, change in
guard let self = self else { return }
switch player.timeControlStatus {
case .playing:
print("Player is playing")
print("Player is playing OOO")
self.playerStatus = .play
vc.songTableView.reloadRows(at: [IndexPath(row: currentIndexPlayingSong ?? 0, section: 0)], with: .none)
case .paused:
print("Player is paused")
self.playerStatus = .pause
print("Player is paused OOO")
// self.playerStatus = .pause
if self.player?.currentTime() == self.player?.currentItem?.duration {
print("Player finished playing")
self.playerStatus = .stopped
self.vc.songTableView.reloadRows(at: [IndexPath(row: currentIndexPlayingSong!, section: 0)], with: .none)
currentIndexPlayingSong = nil
} else {
print("Player is paused")
self.playerStatus = .pause
}
case .waitingToPlayAtSpecifiedRate:
print("Player is waiting to play at specified rate")
print("Player is waiting to play at specified rate OOO")
self.playerStatus = .loading
@unknown default:
print("Unknown player status")
print("Unknown player status OOO")
}
})
}
//
// func playSong(urlString: String) {
// guard let url = URL(string: urlString) else {
@@ -141,3 +154,83 @@ class MoreVM{
}
}
}
import UIKit
extension UIView {
private struct AssociatedKeys {
static var loadingView = "loadingView"
}
private var loadingView: LoadingView? {
get {
return objc_getAssociatedObject(self, AssociatedKeys.loadingView) as? LoadingView
}
set {
objc_setAssociatedObject(self, AssociatedKeys.loadingView, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
func showLoading() {
if loadingView == nil {
let newLoadingView = LoadingView(frame: self.bounds)
newLoadingView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(newLoadingView)
NSLayoutConstraint.activate([
newLoadingView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
newLoadingView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
newLoadingView.topAnchor.constraint(equalTo: self.topAnchor),
newLoadingView.bottomAnchor.constraint(equalTo: self.bottomAnchor)
])
loadingView = newLoadingView
}
loadingView?.startLoading()
}
func hideLoading() {
loadingView?.stopLoading()
}
}
class LoadingView: UIView {
private var activityIndicator: UIActivityIndicatorView!
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupView()
}
private func setupView() {
self.backgroundColor = .clear
activityIndicator = UIActivityIndicatorView(style: .medium)
activityIndicator.translatesAutoresizingMaskIntoConstraints = false
activityIndicator.color = .white
self.addSubview(activityIndicator)
NSLayoutConstraint.activate([
activityIndicator.centerXAnchor.constraint(equalTo: self.centerXAnchor),
activityIndicator.centerYAnchor.constraint(equalTo: self.centerYAnchor),
activityIndicator.heightAnchor.constraint(equalToConstant: self.frame.height - 10),
activityIndicator.widthAnchor.constraint(equalToConstant: self.frame.width - 10)
])
}
func startLoading() {
activityIndicator.startAnimating()
self.isHidden = false
}
func stopLoading() {
activityIndicator.stopAnimating()
self.isHidden = true
}
}