competed user video view

This commit is contained in:
Bilal
2024-08-17 01:34:28 +05:30
parent c6ed16cad2
commit 9ca7c1e4b0
35 changed files with 857 additions and 344 deletions

View File

@@ -103,7 +103,6 @@
527AC6FD2C173A5100434FB7 /* SongListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 527AC6FB2C173A5100434FB7 /* SongListCell.swift */; }; 527AC6FD2C173A5100434FB7 /* SongListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 527AC6FB2C173A5100434FB7 /* SongListCell.swift */; };
527AC6FE2C173A5100434FB7 /* SongListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 527AC6FC2C173A5100434FB7 /* SongListCell.xib */; }; 527AC6FE2C173A5100434FB7 /* SongListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 527AC6FC2C173A5100434FB7 /* SongListCell.xib */; };
527AC7012C182DCE00434FB7 /* TimeStringToSeconds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 527AC7002C182DCE00434FB7 /* TimeStringToSeconds.swift */; }; 527AC7012C182DCE00434FB7 /* TimeStringToSeconds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 527AC7002C182DCE00434FB7 /* TimeStringToSeconds.swift */; };
527CA43A2C6C7FBF00EEDD91 /* WOKA.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 527CA4382C6C7FBE00EEDD91 /* WOKA.xcdatamodeld */; };
528BEF602C2C372900FFDAB8 /* ContinueWatchingVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 528BEF5F2C2C372900FFDAB8 /* ContinueWatchingVC.swift */; }; 528BEF602C2C372900FFDAB8 /* ContinueWatchingVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 528BEF5F2C2C372900FFDAB8 /* ContinueWatchingVC.swift */; };
528E5F1B2C24531200E33E4E /* SeasonListingDM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 528E5F1A2C24531200E33E4E /* SeasonListingDM.swift */; }; 528E5F1B2C24531200E33E4E /* SeasonListingDM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 528E5F1A2C24531200E33E4E /* SeasonListingDM.swift */; };
528E5F222C24660F00E33E4E /* SeasonCategoryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 528E5F202C24660F00E33E4E /* SeasonCategoryCell.swift */; }; 528E5F222C24660F00E33E4E /* SeasonCategoryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 528E5F202C24660F00E33E4E /* SeasonCategoryCell.swift */; };
@@ -338,6 +337,9 @@
9CBE1B432C0F37B300CA6E61 /* DropDown.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CBE1B382C0F37B200CA6E61 /* DropDown.swift */; }; 9CBE1B432C0F37B300CA6E61 /* DropDown.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CBE1B382C0F37B200CA6E61 /* DropDown.swift */; };
9CBE1B442C0F37B300CA6E61 /* DropDown+Appearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CBE1B392C0F37B200CA6E61 /* DropDown+Appearance.swift */; }; 9CBE1B442C0F37B300CA6E61 /* DropDown+Appearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CBE1B392C0F37B200CA6E61 /* DropDown+Appearance.swift */; };
9CBE1B452C0F37B300CA6E61 /* DropDownCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CBE1B3A2C0F37B200CA6E61 /* DropDownCell.swift */; }; 9CBE1B452C0F37B300CA6E61 /* DropDownCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CBE1B3A2C0F37B200CA6E61 /* DropDownCell.swift */; };
9CC0D2F82C6F339D0019DF73 /* WOKA.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 9CC0D2F62C6F339D0019DF73 /* WOKA.xcdatamodeld */; };
9CC0D2FA2C6F33BE0019DF73 /* AuthFuncUserVideoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CC0D2F92C6F33BE0019DF73 /* AuthFuncUserVideoView.swift */; };
9CC0D2FC2C6F5CAE0019DF73 /* PlayerVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CC0D2FB2C6F5CAE0019DF73 /* PlayerVM.swift */; };
9CDAEB032C53B97B00890C47 /* VersionTexts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CDAEB022C53B97B00890C47 /* VersionTexts.swift */; }; 9CDAEB032C53B97B00890C47 /* VersionTexts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CDAEB022C53B97B00890C47 /* VersionTexts.swift */; };
9CDAEB052C53DB2900890C47 /* ProductDetailsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CDAEB042C53DB2900890C47 /* ProductDetailsVC.swift */; }; 9CDAEB052C53DB2900890C47 /* ProductDetailsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CDAEB042C53DB2900890C47 /* ProductDetailsVC.swift */; };
9CDAEB072C53E42900890C47 /* ProductDetailsVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CDAEB062C53E42900890C47 /* ProductDetailsVM.swift */; }; 9CDAEB072C53E42900890C47 /* ProductDetailsVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CDAEB062C53E42900890C47 /* ProductDetailsVM.swift */; };
@@ -494,7 +496,6 @@
527AC6FB2C173A5100434FB7 /* SongListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SongListCell.swift; sourceTree = "<group>"; }; 527AC6FB2C173A5100434FB7 /* SongListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SongListCell.swift; sourceTree = "<group>"; };
527AC6FC2C173A5100434FB7 /* SongListCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SongListCell.xib; sourceTree = "<group>"; }; 527AC6FC2C173A5100434FB7 /* SongListCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SongListCell.xib; sourceTree = "<group>"; };
527AC7002C182DCE00434FB7 /* TimeStringToSeconds.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeStringToSeconds.swift; sourceTree = "<group>"; }; 527AC7002C182DCE00434FB7 /* TimeStringToSeconds.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeStringToSeconds.swift; sourceTree = "<group>"; };
527CA4392C6C7FBE00EEDD91 /* WOKA.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = WOKA.xcdatamodel; sourceTree = "<group>"; };
528BEF5F2C2C372900FFDAB8 /* ContinueWatchingVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContinueWatchingVC.swift; sourceTree = "<group>"; }; 528BEF5F2C2C372900FFDAB8 /* ContinueWatchingVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContinueWatchingVC.swift; sourceTree = "<group>"; };
528E5F1A2C24531200E33E4E /* SeasonListingDM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeasonListingDM.swift; sourceTree = "<group>"; }; 528E5F1A2C24531200E33E4E /* SeasonListingDM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeasonListingDM.swift; sourceTree = "<group>"; };
528E5F202C24660F00E33E4E /* SeasonCategoryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeasonCategoryCell.swift; sourceTree = "<group>"; }; 528E5F202C24660F00E33E4E /* SeasonCategoryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeasonCategoryCell.swift; sourceTree = "<group>"; };
@@ -719,6 +720,9 @@
9CBE1B392C0F37B200CA6E61 /* DropDown+Appearance.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DropDown+Appearance.swift"; sourceTree = "<group>"; }; 9CBE1B392C0F37B200CA6E61 /* DropDown+Appearance.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DropDown+Appearance.swift"; sourceTree = "<group>"; };
9CBE1B3A2C0F37B200CA6E61 /* DropDownCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropDownCell.swift; sourceTree = "<group>"; }; 9CBE1B3A2C0F37B200CA6E61 /* DropDownCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropDownCell.swift; sourceTree = "<group>"; };
9CBE1B3C2C0F37B200CA6E61 /* DropDown.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DropDown.h; sourceTree = "<group>"; }; 9CBE1B3C2C0F37B200CA6E61 /* DropDown.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DropDown.h; sourceTree = "<group>"; };
9CC0D2F72C6F339D0019DF73 /* WOKA.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = WOKA.xcdatamodel; sourceTree = "<group>"; };
9CC0D2F92C6F33BE0019DF73 /* AuthFuncUserVideoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthFuncUserVideoView.swift; sourceTree = "<group>"; };
9CC0D2FB2C6F5CAE0019DF73 /* PlayerVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerVM.swift; sourceTree = "<group>"; };
9CDAEB022C53B97B00890C47 /* VersionTexts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionTexts.swift; sourceTree = "<group>"; }; 9CDAEB022C53B97B00890C47 /* VersionTexts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionTexts.swift; sourceTree = "<group>"; };
9CDAEB042C53DB2900890C47 /* ProductDetailsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductDetailsVC.swift; sourceTree = "<group>"; }; 9CDAEB042C53DB2900890C47 /* ProductDetailsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductDetailsVC.swift; sourceTree = "<group>"; };
9CDAEB062C53E42900890C47 /* ProductDetailsVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductDetailsVM.swift; sourceTree = "<group>"; }; 9CDAEB062C53E42900890C47 /* ProductDetailsVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductDetailsVM.swift; sourceTree = "<group>"; };
@@ -930,7 +934,7 @@
9C535DC82C00C34000DA6DCD /* Theme */, 9C535DC82C00C34000DA6DCD /* Theme */,
52DAC6462C21761700E2F85B /* WebSeries */, 52DAC6462C21761700E2F85B /* WebSeries */,
9C834ED92C1C20EC00B29A9C /* WOKA.entitlements */, 9C834ED92C1C20EC00B29A9C /* WOKA.entitlements */,
527CA4382C6C7FBE00EEDD91 /* WOKA.xcdatamodeld */, 9CC0D2F62C6F339D0019DF73 /* WOKA.xcdatamodeld */,
52ACC1292C610EC900791528 /* PersistentStorage.swift */, 52ACC1292C610EC900791528 /* PersistentStorage.swift */,
); );
path = WOKA; path = WOKA;
@@ -1656,6 +1660,7 @@
9C27E1622BDB6F1900EC1DA9 /* AuthFunc.swift */, 9C27E1622BDB6F1900EC1DA9 /* AuthFunc.swift */,
525327D82BFCDDF700F64283 /* AuthFuncStartupSoundHandling.swift */, 525327D82BFCDDF700F64283 /* AuthFuncStartupSoundHandling.swift */,
52FDBA7A2BFF2712009D7AC7 /* AuthFuncTimeHandling.swift */, 52FDBA7A2BFF2712009D7AC7 /* AuthFuncTimeHandling.swift */,
9CC0D2F92C6F33BE0019DF73 /* AuthFuncUserVideoView.swift */,
); );
path = AuthFunc; path = AuthFunc;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -1731,6 +1736,7 @@
524C422A2C04781B0016A11C /* ThemeTwoVM.swift */, 524C422A2C04781B0016A11C /* ThemeTwoVM.swift */,
52BC3BF12C170264002FACA6 /* MoreVM.swift */, 52BC3BF12C170264002FACA6 /* MoreVM.swift */,
529CFEED2C60F49000B0B380 /* UserNotificationVM.swift */, 529CFEED2C60F49000B0B380 /* UserNotificationVM.swift */,
9CC0D2FB2C6F5CAE0019DF73 /* PlayerVM.swift */,
); );
path = ViewModel; path = ViewModel;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -2314,7 +2320,7 @@
52A6DCA02C4E3AA600F63C51 /* ShopListingCell.swift in Sources */, 52A6DCA02C4E3AA600F63C51 /* ShopListingCell.swift in Sources */,
525954192BE8CC3400191286 /* ConstantString.swift in Sources */, 525954192BE8CC3400191286 /* ConstantString.swift in Sources */,
52D774EB2BDFC0BF001D87DE /* OTPVC.swift in Sources */, 52D774EB2BDFC0BF001D87DE /* OTPVC.swift in Sources */,
527CA43A2C6C7FBF00EEDD91 /* WOKA.xcdatamodeld in Sources */, 9CC0D2F82C6F339D0019DF73 /* WOKA.xcdatamodeld in Sources */,
9C8446872C40FC6E003E3E53 /* AVPlayerTesting.swift in Sources */, 9C8446872C40FC6E003E3E53 /* AVPlayerTesting.swift in Sources */,
52AF71F42C36C40B00BC5972 /* GamesWebViewVC.swift in Sources */, 52AF71F42C36C40B00BC5972 /* GamesWebViewVC.swift in Sources */,
9C007F202C255DF200F798C2 /* EpisodeListingDM.swift in Sources */, 9C007F202C255DF200F798C2 /* EpisodeListingDM.swift in Sources */,
@@ -2327,6 +2333,7 @@
525861DE2C4FE7A100C33C79 /* CouponCell.swift in Sources */, 525861DE2C4FE7A100C33C79 /* CouponCell.swift in Sources */,
9C27E1632BDB6F1900EC1DA9 /* AuthFunc.swift in Sources */, 9C27E1632BDB6F1900EC1DA9 /* AuthFunc.swift in Sources */,
9C0A85412BEE35670093783D /* ResetPassUserNameVM.swift in Sources */, 9C0A85412BEE35670093783D /* ResetPassUserNameVM.swift in Sources */,
9CC0D2FA2C6F33BE0019DF73 /* AuthFuncUserVideoView.swift in Sources */,
52C6E0292BE3B52500E22D59 /* SelectAvatarVM.swift in Sources */, 52C6E0292BE3B52500E22D59 /* SelectAvatarVM.swift in Sources */,
9CDAEB032C53B97B00890C47 /* VersionTexts.swift in Sources */, 9CDAEB032C53B97B00890C47 /* VersionTexts.swift in Sources */,
52C8B0592BDA57FA003B51D0 /* StaticFilesString.swift in Sources */, 52C8B0592BDA57FA003B51D0 /* StaticFilesString.swift in Sources */,
@@ -2493,6 +2500,7 @@
5258464F2C491829004F074B /* connectedness.swift in Sources */, 5258464F2C491829004F074B /* connectedness.swift in Sources */,
9CBE1B452C0F37B300CA6E61 /* DropDownCell.swift in Sources */, 9CBE1B452C0F37B300CA6E61 /* DropDownCell.swift in Sources */,
9C27E16D2BDB852F00EC1DA9 /* GVar.swift in Sources */, 9C27E16D2BDB852F00EC1DA9 /* GVar.swift in Sources */,
9CC0D2FC2C6F5CAE0019DF73 /* PlayerVM.swift in Sources */,
52B8D4E02C04A25E00ED65F3 /* UIView+Container.swift in Sources */, 52B8D4E02C04A25E00ED65F3 /* UIView+Container.swift in Sources */,
527A2BCA2C57776A0080DF9B /* AddNewAddressVC.swift in Sources */, 527A2BCA2C57776A0080DF9B /* AddNewAddressVC.swift in Sources */,
9C56E8462BDBEE6400E4CA14 /* EmailVC.swift in Sources */, 9C56E8462BDBEE6400E4CA14 /* EmailVC.swift in Sources */,
@@ -3070,14 +3078,14 @@
/* End XCSwiftPackageProductDependency section */ /* End XCSwiftPackageProductDependency section */
/* Begin XCVersionGroup section */ /* Begin XCVersionGroup section */
527CA4382C6C7FBE00EEDD91 /* WOKA.xcdatamodeld */ = { 9CC0D2F62C6F339D0019DF73 /* WOKA.xcdatamodeld */ = {
isa = XCVersionGroup; isa = XCVersionGroup;
children = ( children = (
527CA4392C6C7FBE00EEDD91 /* WOKA.xcdatamodel */, 9CC0D2F72C6F339D0019DF73 /* WOKA.xcdatamodel */,
); );
currentVersion = 527CA4392C6C7FBE00EEDD91 /* WOKA.xcdatamodel */; currentVersion = 9CC0D2F72C6F339D0019DF73 /* WOKA.xcdatamodel */;
name = WOKA.xcdatamodeld; name = WOKA.xcdatamodeld;
path = /Users/macbookpro/Desktop/WOKA/WOKA/WOKA.xcdatamodeld; path = /Users/bilal/Desktop/woka_native_ios_swift/WOKA/WOKA.xcdatamodeld;
sourceTree = "<group>"; sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel; versionGroupType = wrapper.xcdatamodel;
}; };

View File

@@ -549,19 +549,36 @@
</userDefinedRuntimeAttribute> </userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
</view> </view>
<stackView hidden="YES" opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="n6H-pw-g1w">
<rect key="frame" x="118.66666666666669" y="290.66666666666669" width="177" height="200"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="SupportGirlImage" translatesAutoresizingMaskIntoConstraints="NO" id="Rnc-CS-DVv">
<rect key="frame" x="0.0" y="0.0" width="177" height="166"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="No Address Found!" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SR8-rF-46h" customClass="LocalisedElementsLabel" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="0.0" y="176" width="177" height="24"/>
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="20"/>
<color key="textColor" name="TextDarkBlue"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
</subviews> </subviews>
<viewLayoutGuide key="safeArea" id="37x-el-mdR"/> <viewLayoutGuide key="safeArea" id="37x-el-mdR"/>
<color key="backgroundColor" systemColor="systemGreenColor"/> <color key="backgroundColor" systemColor="systemGreenColor"/>
<constraints> <constraints>
<constraint firstItem="n6H-pw-g1w" firstAttribute="centerY" secondItem="w05-l0-ALY" secondAttribute="centerY" id="bbS-Lc-ZsW"/>
<constraint firstItem="37x-el-mdR" firstAttribute="bottom" secondItem="Ry1-Ll-tvj" secondAttribute="bottom" constant="5" id="g8o-D8-sxQ"/> <constraint firstItem="37x-el-mdR" firstAttribute="bottom" secondItem="Ry1-Ll-tvj" secondAttribute="bottom" constant="5" id="g8o-D8-sxQ"/>
<constraint firstItem="37x-el-mdR" firstAttribute="trailing" secondItem="Ry1-Ll-tvj" secondAttribute="trailing" constant="10" id="hfh-kM-3II"/> <constraint firstItem="37x-el-mdR" firstAttribute="trailing" secondItem="Ry1-Ll-tvj" secondAttribute="trailing" constant="10" id="hfh-kM-3II"/>
<constraint firstItem="Ry1-Ll-tvj" firstAttribute="top" secondItem="37x-el-mdR" secondAttribute="top" constant="5" id="nXO-UI-rOM"/> <constraint firstItem="Ry1-Ll-tvj" firstAttribute="top" secondItem="37x-el-mdR" secondAttribute="top" constant="5" id="nXO-UI-rOM"/>
<constraint firstItem="n6H-pw-g1w" firstAttribute="centerX" secondItem="w05-l0-ALY" secondAttribute="centerX" id="vdb-8x-PwN"/>
<constraint firstItem="Ry1-Ll-tvj" firstAttribute="leading" secondItem="37x-el-mdR" secondAttribute="leading" constant="10" id="zid-rU-Ovk"/> <constraint firstItem="Ry1-Ll-tvj" firstAttribute="leading" secondItem="37x-el-mdR" secondAttribute="leading" constant="10" id="zid-rU-Ovk"/>
</constraints> </constraints>
</view> </view>
<connections> <connections>
<outlet property="addNewAddressBtn" destination="02u-58-7FW" id="eWv-38-GfZ"/> <outlet property="addNewAddressBtn" destination="02u-58-7FW" id="eWv-38-GfZ"/>
<outlet property="innerView" destination="JAF-kY-lUa" id="cM7-cm-pqy"/> <outlet property="innerView" destination="JAF-kY-lUa" id="cM7-cm-pqy"/>
<outlet property="noDataStack" destination="n6H-pw-g1w" id="EMJ-ob-Dr1"/>
<outlet property="tableView" destination="w05-l0-ALY" id="J15-i9-ySS"/> <outlet property="tableView" destination="w05-l0-ALY" id="J15-i9-ySS"/>
<outlet property="useSelectedAddBtn" destination="ZNs-65-Cqv" id="hYN-Nc-H8h"/> <outlet property="useSelectedAddBtn" destination="ZNs-65-Cqv" id="hYN-Nc-H8h"/>
</connections> </connections>
@@ -582,7 +599,7 @@
<rect key="frame" x="0.0" y="44" width="414" height="852"/> <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"/> <color key="backgroundColor" red="0.36078431370000003" green="0.38823529410000002" blue="0.4039215686" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<wkWebViewConfiguration key="configuration" allowsAirPlayForMediaPlayback="NO" allowsPictureInPictureMediaPlayback="NO"> <wkWebViewConfiguration key="configuration" allowsAirPlayForMediaPlayback="NO" allowsPictureInPictureMediaPlayback="NO">
<dataDetectorTypes key="dataDetectorTypes"/> <dataDetectorTypes key="dataDetectorTypes" none="YES"/>
<audiovisualMediaTypes key="mediaTypesRequiringUserActionForPlayback" none="YES"/> <audiovisualMediaTypes key="mediaTypesRequiringUserActionForPlayback" none="YES"/>
<wkPreferences key="preferences"/> <wkPreferences key="preferences"/>
</wkWebViewConfiguration> </wkWebViewConfiguration>
@@ -636,6 +653,7 @@
</designable> </designable>
</designables> </designables>
<resources> <resources>
<image name="SupportGirlImage" width="166" height="166"/>
<namedColor name="TextDarkBlue"> <namedColor name="TextDarkBlue">
<color red="0.10599999874830246" green="0.050999999046325684" blue="0.60399997234344482" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color red="0.10599999874830246" green="0.050999999046325684" blue="0.60399997234344482" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor> </namedColor>
@@ -643,7 +661,7 @@
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor> </systemColor>
<systemColor name="systemGreenColor"> <systemColor name="systemGreenColor">
<color red="0.20392156862745098" green="0.7803921568627451" blue="0.34901960784313724" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color red="0.20392156859999999" green="0.78039215689999997" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor> </systemColor>
</resources> </resources>
</document> </document>

View File

@@ -13,6 +13,7 @@ class AddressListVC: UIViewController {
@IBOutlet weak var tableView: UITableView! @IBOutlet weak var tableView: UITableView!
@IBOutlet weak var useSelectedAddBtn : LocalisedElementsButton! @IBOutlet weak var useSelectedAddBtn : LocalisedElementsButton!
@IBOutlet weak var addNewAddressBtn : LocalisedElementsButton! @IBOutlet weak var addNewAddressBtn : LocalisedElementsButton!
@IBOutlet weak var noDataStack: UIStackView!
var vm = AddressListVM() var vm = AddressListVM()
@@ -61,6 +62,10 @@ class AddressListVC: UIViewController {
switch sender{ switch sender{
case useSelectedAddBtn: case useSelectedAddBtn:
if CartDataCache.addressData.count == 0{
self.toast(msg: "Please add address", time: 1.5)
return
}
if let addressID = CartDataCache.addressData.filter({$0.isDefault == true}).first?.id{ if let addressID = CartDataCache.addressData.filter({$0.isDefault == true}).first?.id{
vm.createOrder(addressID: addressID, couponCode: vm.couponCodeApplied) vm.createOrder(addressID: addressID, couponCode: vm.couponCodeApplied)
} }

View File

@@ -64,6 +64,7 @@ class AddressListVM{
Error Error
*/ */
Utilities.dismissProgressHUD() Utilities.dismissProgressHUD()
self.checkForNoData()
case 1: case 1:
Utilities.dismissProgressHUD() Utilities.dismissProgressHUD()
guard let data = data.data else{return} guard let data = data.data else{return}
@@ -73,6 +74,7 @@ class AddressListVM{
CartDataCache.addressData[0].isAnimating = true CartDataCache.addressData[0].isAnimating = true
} }
self.vc.tableView.reloadData() self.vc.tableView.reloadData()
self.checkForNoData()
if let pincode = CartDataCache.addressData.first?.pincode , let id = CartDataCache.addressData.first?.id{ if let pincode = CartDataCache.addressData.first?.pincode , let id = CartDataCache.addressData.first?.id{
checkEstimatedDeliveryData(pinCode: pincode, id: id) checkEstimatedDeliveryData(pinCode: pincode, id: id)
} }
@@ -83,9 +85,11 @@ class AddressListVM{
case .failure(let error): case .failure(let error):
guard let self else{ guard let self else{
Utilities.dismissProgressHUD() Utilities.dismissProgressHUD()
self?.checkForNoData()
return return
} }
Utilities.dismissProgressHUD() Utilities.dismissProgressHUD()
checkForNoData()
Utilities.alertWithBtnCompletion(title: "Error", msgBody: error.localizedDescription, okBtnStr: "Retry?", vc: self.vc) { isDone in Utilities.alertWithBtnCompletion(title: "Error", msgBody: error.localizedDescription, okBtnStr: "Retry?", vc: self.vc) { isDone in
if isDone{ if isDone{
self.getAddressListing() self.getAddressListing()
@@ -95,6 +99,14 @@ class AddressListVM{
} }
} }
func checkForNoData(){
if CartDataCache.addressData.count == 0{
vc.noDataStack.isHidden = false
}else{
vc.noDataStack.isHidden = true
}
}
func checkEstimatedDeliveryData(pinCode : String, id : Int){ func checkEstimatedDeliveryData(pinCode : String, id : Int){
let headers : HTTPHeaders = ["access-token" : AuthFunc.shareInstance.getAccessToken()] let headers : HTTPHeaders = ["access-token" : AuthFunc.shareInstance.getAccessToken()]
let params : Parameters = ["pincode" : pinCode] let params : Parameters = ["pincode" : pinCode]

View File

@@ -361,7 +361,9 @@ class AudioBookDetailsVC : UIViewController{
// } // }
// } // }
// } // }
JWPlayerManager.shared.presentPlayer(from: self, playerItems: playerItems, startIndex: 0, contentType: .audioBooks) if let audioID = audioData?.id{
JWPlayerManager.shared.presentPlayer(from: self, playerItems: playerItems, startIndex: 0, contentType: .audioBooks,videoIDs: [audioID])
}
} }
@IBAction func closeBtnTapped(_ sender: UIButton) { @IBAction func closeBtnTapped(_ sender: UIButton) {

View File

@@ -66,6 +66,13 @@ class AudioBookHomeVC: UIViewController {
} }
} }
override func viewDidAppear(_ animated: Bool) {
if K.GVar.reloadContinueAudioBooks{
K.GVar.reloadContinueAudioBooks = false
vm.getContinueWatching()
}
}
override func viewDidLayoutSubviews() { override func viewDidLayoutSubviews() {
vm.updateTableHeight() vm.updateTableHeight()
} }
@@ -78,10 +85,8 @@ class AudioBookHomeVC: UIViewController {
} }
@IBAction func listenAudioBtnTapped(_ sender: LocalisedElementsButton) { @IBAction func listenAudioBtnTapped(_ sender: LocalisedElementsButton) {
guard let data = vm.headerData else{return} guard let data = vm.headerData, let postID = data.id else{return}
if let postID = data.id{ PersistentStorage.shared.addAudioCount(postID: postID)
PersistentStorage.shared.addAudioCount(postID: postID)
}
var playerItems = [JwPlayerItemCreate]() var playerItems = [JwPlayerItemCreate]()
if AuthFunc.shareInstance.getDefaultLanguage() == .english{ if AuthFunc.shareInstance.getDefaultLanguage() == .english{
if let englishData = data.contentMoreDetails?.filter({$0.languageMasterID == 1}).first, let url = englishData.url{ if let englishData = data.contentMoreDetails?.filter({$0.languageMasterID == 1}).first, let url = englishData.url{
@@ -92,7 +97,7 @@ class AudioBookHomeVC: UIViewController {
playerItems.append(JwPlayerItemCreate(url: url, poster: data.thumbnailPath, titles: hindiData.title)) playerItems.append(JwPlayerItemCreate(url: url, poster: data.thumbnailPath, titles: hindiData.title))
} }
} }
JWPlayerManager.shared.presentPlayer(from: self, playerItems: playerItems, startIndex: 0, contentType: .audioBooks) JWPlayerManager.shared.presentPlayer(from: self, playerItems: playerItems, startIndex: 0, contentType: .audioBooks, videoIDs: [postID])
} }
} }

View File

@@ -33,5 +33,7 @@ extension K{
static let error = "Error" static let error = "Error"
static let rupeeSign = "" static let rupeeSign = ""
static let sync = "Syncing..."
} }
} }

View File

@@ -24,5 +24,9 @@ extension K{
static var reloadMyListAll = 0 // 0 - null, 1 - add , 2- remove static var reloadMyListAll = 0 // 0 - null, 1 - add , 2- remove
static var reloadMyListAllID = 0 static var reloadMyListAllID = 0
static var reloadContinueKaraoke = false
static var reloadContinueAudioBooks = false
static var reloadContinueWebSeries = false
} }
} }

View File

@@ -205,7 +205,11 @@ class GamesDetailVC: UIViewController {
} }
} }
shareView.addTapGesture { shareView.addTapGesture { [weak self] in
guard let self else{return}
if let postID = gameData?.id{
PersistentStorage.shared.addGamesCount(postID: postID)
}
if let name = URL(string: "https://apps.apple.com/in/app/woka/id6465305185"), !name.absoluteString.isEmpty { if let name = URL(string: "https://apps.apple.com/in/app/woka/id6465305185"), !name.absoluteString.isEmpty {
let objectsToShare = [name] let objectsToShare = [name]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil) let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)

View File

@@ -14,12 +14,20 @@ class GamesWebViewVC: UIViewController, WKNavigationDelegate,UIGestureRecognizer
var orientation : ScreenOrientation? var orientation : ScreenOrientation?
var count = 0 var count = 0
var postID : Int? var postID : Int?
@IBOutlet weak var clickView: UIView! @IBOutlet weak var clickView: UIView!
@IBOutlet weak var webView: WKWebView! @IBOutlet weak var webView: WKWebView!
var startTimeStamp = Date()
typealias btnTappedBlock = () -> Void
var btnTapped : btnTappedBlock?
deinit{ deinit{
// print("Deinit Game") NotificationCenter.default.removeObserver(self,name: UIApplication.didEnterBackgroundNotification, object: nil)
NotificationCenter.default.removeObserver(self,name: UIApplication.willEnterForegroundNotification, object: nil)
if let postID = self.postID{ if let postID = self.postID{
PersistentStorage.shared.addGamesCount(postID: postID,count: count) PersistentStorage.shared.addGamesCount(postID: postID,count: count)
} }
@@ -49,6 +57,10 @@ class GamesWebViewVC: UIViewController, WKNavigationDelegate,UIGestureRecognizer
// Add the gesture recognizer to the web view // Add the gesture recognizer to the web view
clickView.addGestureRecognizer(tap) clickView.addGestureRecognizer(tap)
// Add observers
NotificationCenter.default.addObserver(self,selector: #selector(appDidEnterBackground),name: UIApplication.didEnterBackgroundNotification,object: nil)
NotificationCenter.default.addObserver(self,selector: #selector(appWillEnterForeground),name: UIApplication.willEnterForegroundNotification,object: nil)
} }
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
@@ -61,9 +73,7 @@ class GamesWebViewVC: UIViewController, WKNavigationDelegate,UIGestureRecognizer
} }
@IBAction func backBtnTapped(_ sender: UIButton) { @IBAction func backBtnTapped(_ sender: UIButton) {
if let postID = self.postID{ PersistentStorage.shared.addOthersCount()
PersistentStorage.shared.addOthersCount()
}
let sb = UIStoryboard(name: K.StoryBoard.customAlerts, bundle: nil) let sb = UIStoryboard(name: K.StoryBoard.customAlerts, bundle: nil)
let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.CustomAlerts.yesNoAlertVC) as! YesNoAlertVC let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.CustomAlerts.yesNoAlertVC) as! YesNoAlertVC
@@ -75,7 +85,8 @@ class GamesWebViewVC: UIViewController, WKNavigationDelegate,UIGestureRecognizer
guard let self else{return} guard let self else{return}
switch mode{ switch mode{
case .yes: case .yes:
// update continue watching
self.updateGamesView()
if orientation == .landscape{ if orientation == .landscape{
appDelegate.deviceOrientation = .portrait appDelegate.deviceOrientation = .portrait
let value = UIInterfaceOrientation.portrait.rawValue let value = UIInterfaceOrientation.portrait.rawValue
@@ -85,7 +96,6 @@ class GamesWebViewVC: UIViewController, WKNavigationDelegate,UIGestureRecognizer
self.dismiss(animated: true) self.dismiss(animated: true)
} }
} }
case .no: case .no:
if let postID = self.postID{ if let postID = self.postID{
PersistentStorage.shared.addGamesCount(postID: postID) PersistentStorage.shared.addGamesCount(postID: postID)
@@ -98,6 +108,26 @@ class GamesWebViewVC: UIViewController, WKNavigationDelegate,UIGestureRecognizer
self.present(vcPush, animated: true) self.present(vcPush, animated: true)
} }
// MARK: - App LifeCycle HAndler
@objc func appDidEnterBackground() {
//when app goes in background make a count
updateGamesView()
}
@objc func appWillEnterForeground() {
//reset the start time
startTimeStamp = Date()
}
func updateGamesView(){
if let postID {
let duration = DateFormatterLib.dateDifferenceINT(date1: startTimeStamp, date2: Date())
AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.game.rawValue, duration: duration, catID: 0) { _ in}
}
}
// MARK: - Handle Screen Transition // MARK: - Handle Screen Transition
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {

View File

@@ -191,6 +191,22 @@ class DateFormatterLib{
} }
} }
static func dateDifferenceINT(date1 : Date, date2 : Date) -> Int{
// Calculate the difference in seconds
let timeInterval = date2.timeIntervalSince(date1)
// Convert the time interval to an integer representing the difference in seconds
let differenceInSeconds = Int(timeInterval)
// If you want the difference in minutes, divide by 60
// let differenceInMinutes = Int(timeInterval / 60)
// If you want the difference in hours, divide by 3600
// let differenceInHours = Int(timeInterval / 3600)
return differenceInSeconds
}
} }
extension Date { extension Date {

View File

@@ -37,6 +37,10 @@ class MyListVC: UIViewController{
@IBOutlet weak var gamesBtn: LocalisedElementsButton! @IBOutlet weak var gamesBtn: LocalisedElementsButton!
@IBOutlet weak var karaokeViewBtn: LocalisedElementsButton! @IBOutlet weak var karaokeViewBtn: LocalisedElementsButton!
@IBOutlet weak var shimmerStack: UIStackView!
@IBOutlet var shimmerView: [ShimmerEffectView]!
var vm = MyListVM() var vm = MyListVM()
deinit{ deinit{

View File

@@ -1461,6 +1461,49 @@
</userDefinedRuntimeAttribute> </userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
</stackView> </stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="n3b-MP-wOW">
<rect key="frame" x="0.0" y="126" width="430" height="660"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="zVG-vD-Pa9" customClass="ShimmerEffectView" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="15" y="10" width="400" height="200"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstAttribute="height" constant="200" id="BOv-Or-mtr"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
<integer key="value" value="10"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5PD-9x-fXz" customClass="ShimmerEffectView" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="15" y="230" width="400" height="200"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstAttribute="height" constant="200" id="1Hd-rU-zAi"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
<integer key="value" value="10"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LMU-lo-nNz" customClass="ShimmerEffectView" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="15" y="450" width="400" height="200"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstAttribute="height" constant="200" id="xlu-qi-KIb"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
<integer key="value" value="10"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<edgeInsets key="layoutMargins" top="10" left="15" bottom="10" right="15"/>
</stackView>
</subviews> </subviews>
<viewLayoutGuide key="safeArea" id="fPD-rO-ZgU"/> <viewLayoutGuide key="safeArea" id="fPD-rO-ZgU"/>
<color key="backgroundColor" red="0.82745098039215681" green="0.93725490196078431" blue="0.97254901960784312" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="0.82745098039215681" green="0.93725490196078431" blue="0.97254901960784312" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -1469,6 +1512,8 @@
<constraint firstItem="fPD-rO-ZgU" firstAttribute="trailing" secondItem="a7Y-B6-f0Q" secondAttribute="trailing" constant="15" id="1TC-Nf-fdz"/> <constraint firstItem="fPD-rO-ZgU" firstAttribute="trailing" secondItem="a7Y-B6-f0Q" secondAttribute="trailing" constant="15" id="1TC-Nf-fdz"/>
<constraint firstItem="jbL-QO-JJl" firstAttribute="leading" secondItem="5ML-g4-686" secondAttribute="trailing" constant="15" id="5bI-AA-E64"/> <constraint firstItem="jbL-QO-JJl" firstAttribute="leading" secondItem="5ML-g4-686" secondAttribute="trailing" constant="15" id="5bI-AA-E64"/>
<constraint firstItem="SyC-Qw-kzE" firstAttribute="bottom" secondItem="fPD-rO-ZgU" secondAttribute="bottom" id="7R3-kt-ANX"/> <constraint firstItem="SyC-Qw-kzE" firstAttribute="bottom" secondItem="fPD-rO-ZgU" secondAttribute="bottom" id="7R3-kt-ANX"/>
<constraint firstItem="n3b-MP-wOW" firstAttribute="leading" secondItem="fPD-rO-ZgU" secondAttribute="leading" id="E1C-E8-97R"/>
<constraint firstItem="n3b-MP-wOW" firstAttribute="trailing" secondItem="fPD-rO-ZgU" secondAttribute="trailing" id="I4g-uI-OU6"/>
<constraint firstItem="fTK-nk-bN9" firstAttribute="leading" secondItem="fPD-rO-ZgU" secondAttribute="leading" id="KDZ-vt-s13"/> <constraint firstItem="fTK-nk-bN9" firstAttribute="leading" secondItem="fPD-rO-ZgU" secondAttribute="leading" id="KDZ-vt-s13"/>
<constraint firstItem="a7Y-B6-f0Q" firstAttribute="top" secondItem="fPD-rO-ZgU" secondAttribute="top" constant="10" id="L4o-KM-D1O"/> <constraint firstItem="a7Y-B6-f0Q" firstAttribute="top" secondItem="fPD-rO-ZgU" secondAttribute="top" constant="10" id="L4o-KM-D1O"/>
<constraint firstItem="cxl-Av-gEU" firstAttribute="bottom" secondItem="a7Y-B6-f0Q" secondAttribute="bottom" constant="7" id="Lur-Ax-w8w"/> <constraint firstItem="cxl-Av-gEU" firstAttribute="bottom" secondItem="a7Y-B6-f0Q" secondAttribute="bottom" constant="7" id="Lur-Ax-w8w"/>
@@ -1477,6 +1522,7 @@
<constraint firstItem="5ML-g4-686" firstAttribute="leading" secondItem="23B-pX-ODs" secondAttribute="leading" constant="5" id="Na5-Wr-DSa"/> <constraint firstItem="5ML-g4-686" firstAttribute="leading" secondItem="23B-pX-ODs" secondAttribute="leading" constant="5" id="Na5-Wr-DSa"/>
<constraint firstItem="SyC-Qw-kzE" firstAttribute="top" secondItem="a7Y-B6-f0Q" secondAttribute="bottom" constant="10" id="Nyh-j8-zuL"/> <constraint firstItem="SyC-Qw-kzE" firstAttribute="top" secondItem="a7Y-B6-f0Q" secondAttribute="bottom" constant="10" id="Nyh-j8-zuL"/>
<constraint firstItem="fPD-rO-ZgU" firstAttribute="trailing" secondItem="ygH-wj-cLk" secondAttribute="trailing" id="Pyd-Eq-Pwe"/> <constraint firstItem="fPD-rO-ZgU" firstAttribute="trailing" secondItem="ygH-wj-cLk" secondAttribute="trailing" id="Pyd-Eq-Pwe"/>
<constraint firstItem="n3b-MP-wOW" firstAttribute="bottom" relation="lessThanOrEqual" secondItem="fPD-rO-ZgU" secondAttribute="bottom" id="UgR-R8-f7G"/>
<constraint firstItem="fPD-rO-ZgU" firstAttribute="trailing" secondItem="fTK-nk-bN9" secondAttribute="trailing" id="XRW-xO-sGx"/> <constraint firstItem="fPD-rO-ZgU" firstAttribute="trailing" secondItem="fTK-nk-bN9" secondAttribute="trailing" id="XRW-xO-sGx"/>
<constraint firstItem="cxl-Av-gEU" firstAttribute="top" secondItem="23B-pX-ODs" secondAttribute="top" id="Y0G-Ua-UcP"/> <constraint firstItem="cxl-Av-gEU" firstAttribute="top" secondItem="23B-pX-ODs" secondAttribute="top" id="Y0G-Ua-UcP"/>
<constraint firstItem="QHo-nZ-miK" firstAttribute="centerX" secondItem="fPD-rO-ZgU" secondAttribute="centerX" id="ZkK-bD-6Ys"/> <constraint firstItem="QHo-nZ-miK" firstAttribute="centerX" secondItem="fPD-rO-ZgU" secondAttribute="centerX" id="ZkK-bD-6Ys"/>
@@ -1491,6 +1537,7 @@
<constraint firstItem="ygH-wj-cLk" firstAttribute="top" secondItem="cxl-Av-gEU" secondAttribute="bottom" id="rb7-EW-WCc"/> <constraint firstItem="ygH-wj-cLk" firstAttribute="top" secondItem="cxl-Av-gEU" secondAttribute="bottom" id="rb7-EW-WCc"/>
<constraint firstItem="fPD-rO-ZgU" firstAttribute="trailing" secondItem="cxl-Av-gEU" secondAttribute="trailing" id="usz-Hi-BR2"/> <constraint firstItem="fPD-rO-ZgU" firstAttribute="trailing" secondItem="cxl-Av-gEU" secondAttribute="trailing" id="usz-Hi-BR2"/>
<constraint firstItem="fPD-rO-ZgU" firstAttribute="bottom" secondItem="fTK-nk-bN9" secondAttribute="bottom" constant="-20" id="vmC-a4-Yy3"/> <constraint firstItem="fPD-rO-ZgU" firstAttribute="bottom" secondItem="fTK-nk-bN9" secondAttribute="bottom" constant="-20" id="vmC-a4-Yy3"/>
<constraint firstItem="n3b-MP-wOW" firstAttribute="top" secondItem="cxl-Av-gEU" secondAttribute="bottom" constant="10" id="xGm-9v-fwc"/>
</constraints> </constraints>
</view> </view>
<tabBarItem key="tabBarItem" title="MY LIST" image="HeartIcon" id="dhn-IV-GcD"/> <tabBarItem key="tabBarItem" title="MY LIST" image="HeartIcon" id="dhn-IV-GcD"/>
@@ -1510,17 +1557,21 @@
<outlet property="karaokeViewBtn" destination="MNq-YB-EUG" id="nhX-tu-YWQ"/> <outlet property="karaokeViewBtn" destination="MNq-YB-EUG" id="nhX-tu-YWQ"/>
<outlet property="noDataStack" destination="QHo-nZ-miK" id="mA1-FT-iQl"/> <outlet property="noDataStack" destination="QHo-nZ-miK" id="mA1-FT-iQl"/>
<outlet property="scrollView" destination="SyC-Qw-kzE" id="0xd-Wb-TU1"/> <outlet property="scrollView" destination="SyC-Qw-kzE" id="0xd-Wb-TU1"/>
<outlet property="shimmerStack" destination="n3b-MP-wOW" id="taO-4R-ZPG"/>
<outlet property="webSeriesBtn" destination="zNj-21-nce" id="Tkc-4Z-odt"/> <outlet property="webSeriesBtn" destination="zNj-21-nce" id="Tkc-4Z-odt"/>
<outlet property="webSeriesCV" destination="6Y6-vJ-OYT" id="FRf-D2-kxM"/> <outlet property="webSeriesCV" destination="6Y6-vJ-OYT" id="FRf-D2-kxM"/>
<outlet property="webSeriesEnglishStack" destination="vZT-j7-NyY" id="HG5-LW-alT"/> <outlet property="webSeriesEnglishStack" destination="vZT-j7-NyY" id="HG5-LW-alT"/>
<outlet property="webSeriesHindiBtn" destination="PHL-y5-hHs" id="5Ez-Te-6El"/> <outlet property="webSeriesHindiBtn" destination="PHL-y5-hHs" id="5Ez-Te-6El"/>
<outlet property="webSeriesHindiCV" destination="aW7-x8-HRh" id="eJM-QC-gIw"/> <outlet property="webSeriesHindiCV" destination="aW7-x8-HRh" id="eJM-QC-gIw"/>
<outlet property="webSeriesHindiStack" destination="h1g-o9-Qbb" id="cbP-E3-4Bc"/> <outlet property="webSeriesHindiStack" destination="h1g-o9-Qbb" id="cbP-E3-4Bc"/>
<outletCollection property="shimmerView" destination="zVG-vD-Pa9" collectionClass="NSMutableArray" id="zku-q7-DXa"/>
<outletCollection property="shimmerView" destination="5PD-9x-fXz" collectionClass="NSMutableArray" id="JrO-dN-fRP"/>
<outletCollection property="shimmerView" destination="LMU-lo-nNz" collectionClass="NSMutableArray" id="Va8-vH-tav"/>
</connections> </connections>
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="lPK-ME-Nlb" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="lPK-ME-Nlb" sceneMemberID="firstResponder"/>
</objects> </objects>
<point key="canvasLocation" x="2198.5507246376815" y="977.67857142857133"/> <point key="canvasLocation" x="2197.6744186046512" y="977.2532188841202"/>
</scene> </scene>
<!--EXPLORE WOKA--> <!--EXPLORE WOKA-->
<scene sceneID="taU-OT-R2P"> <scene sceneID="taU-OT-R2P">

View File

@@ -36,7 +36,7 @@ class MyListVM{
} }
setupCell() setupCell()
Utilities.startProgressHUD() startShimmer(load: true)
getFavouriteListing() getFavouriteListing()
vc.karaokeViewBtn.roundCorner() vc.karaokeViewBtn.roundCorner()
@@ -46,6 +46,18 @@ class MyListVM{
vc.webSeriesHindiBtn.roundCorner() vc.webSeriesHindiBtn.roundCorner()
} }
func startShimmer(load : Bool){
vc.shimmerView.forEach { shimmer in
if load{
shimmer.gradientColorOne = UIColor.lightGray.cgColor
shimmer.startShimmer()
}else{
shimmer.stopShimmer()
}
}
vc.shimmerStack.isHidden = !load
}
@objc func viewPush(notification: Notification){ @objc func viewPush(notification: Notification){
if let userInfo = notification.userInfo, let action = userInfo["action"] as? TopViewPush { if let userInfo = notification.userInfo, let action = userInfo["action"] as? TopViewPush {
switch action { switch action {
@@ -134,6 +146,7 @@ class MyListVM{
case 0: case 0:
self.refreshControl.endRefreshing() self.refreshControl.endRefreshing()
Utilities.dismissProgressHUD() Utilities.dismissProgressHUD()
self.startShimmer(load: false)
self.vc.toast(msg: data.message ?? "Unrecognised error" , time: 2) self.vc.toast(msg: data.message ?? "Unrecognised error" , time: 2)
// MyListDataTemp.shareInstance.webSeriesHindi.removeAll() // MyListDataTemp.shareInstance.webSeriesHindi.removeAll()
MyListDataTemp.shareInstance.favListingData = nil MyListDataTemp.shareInstance.favListingData = nil
@@ -148,6 +161,7 @@ class MyListVM{
case 1: case 1:
self.refreshControl.endRefreshing() self.refreshControl.endRefreshing()
Utilities.dismissProgressHUD() Utilities.dismissProgressHUD()
self.startShimmer(load: false)
guard let data = data.data?.result else{return} guard let data = data.data?.result else{return}
MyListDataTemp.shareInstance.favListingData = nil MyListDataTemp.shareInstance.favListingData = nil
// MyListDataTemp.shareInstance.webSeriesHindi.removeAll() // MyListDataTemp.shareInstance.webSeriesHindi.removeAll()
@@ -218,6 +232,7 @@ class MyListVM{
guard let self else{return} guard let self else{return}
self.refreshControl.endRefreshing() self.refreshControl.endRefreshing()
Utilities.dismissProgressHUD() Utilities.dismissProgressHUD()
self.startShimmer(load: false)
checkNil() checkNil()
if MyListDataTemp.shareInstance.favListingData?.showData == nil { if MyListDataTemp.shareInstance.favListingData?.showData == nil {
MyListDataTemp.shareInstance.favListingData = FavouriteListingDM.ResultData(totalRecords: nil, showData: FavouriteListingDM.ResultData.ShowData(hindi: [],english: []),videoData: [],gameData: [],singKaraokeData: [],audioData: []) MyListDataTemp.shareInstance.favListingData = FavouriteListingDM.ResultData(totalRecords: nil, showData: FavouriteListingDM.ResultData.ShowData(hindi: [],english: []),videoData: [],gameData: [],singKaraokeData: [],audioData: [])

View File

@@ -30,8 +30,15 @@ class JWKaraokePlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate
var audioPlayer = AVPlayer() var audioPlayer = AVPlayer()
var videoID = Int()
var vm = JWKaraokePlayerVM() var vm = JWKaraokePlayerVM()
deinit{
NotificationCenter.default.removeObserver(self,name: UIApplication.didEnterBackgroundNotification, object: nil)
NotificationCenter.default.removeObserver(self,name: UIApplication.willEnterForegroundNotification, object: nil)
}
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
vm.vc = self vm.vc = self
@@ -43,7 +50,11 @@ class JWKaraokePlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate
playerView.allowsPictureInPicturePlayback = false playerView.allowsPictureInPicturePlayback = false
playerView.captionStyle = .none playerView.captionStyle = .none
self.view.bringSubviewToFront(outerStack) self.view.bringSubviewToFront(outerStack)
self.view.bringSubviewToFront(backButton) self.view.bringSubviewToFront(backButton)
// Add observers
NotificationCenter.default.addObserver(self,selector: #selector(appDidEnterBackground),name: UIApplication.didEnterBackgroundNotification,object: nil)
NotificationCenter.default.addObserver(self,selector: #selector(appWillEnterForeground),name: UIApplication.willEnterForegroundNotification,object: nil)
} }
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
@@ -129,7 +140,20 @@ class JWKaraokePlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate
PersistentStorage.shared.addKaraokeCount(postID: postID) PersistentStorage.shared.addKaraokeCount(postID: postID)
} }
self.player.stop() self.player.stop()
self.dismiss(animated: true) if let postID = vm.postID{
Utilities.startProgressHUD(msg: "Syncing...")
let duration = DateFormatterLib.dateDifferenceINT(date1: vm.startTimeStamp, date2: Date())
AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.karaokeVideo.rawValue, duration: duration, catID: 0) { isDone in
if isDone{
K.GVar.reloadContinueKaraoke = true
Utilities.dismissProgressHUD()
self.dismiss(animated: true)
}else{
Utilities.dismissProgressHUD()
self.dismiss(animated: true)
}
}
}
} }
@IBAction func retryBtnTapped(_ sender: LocalisedElementsButton) { @IBAction func retryBtnTapped(_ sender: LocalisedElementsButton) {
@@ -140,12 +164,35 @@ class JWKaraokePlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate
vm.setupKaraoke() vm.setupKaraoke()
} }
// MARK: - App LifeCycle HAndler
@objc func appDidEnterBackground() {
//when app goes in background make a count
vm.updateKaraokeVideoView()
self.player.pause()
self.playBtn.isEnabled = false
if isRecording {
vm.stopRecording()
//make sure the interfacebehaviour is enabbled && updated the record btn title and image
self.interfaceBehavior = .normal
startRecordBtn.setTitle("Start Recording", for: .normal)
isRecording = false
}
}
@objc func appWillEnterForeground() {
//reset the start time
vm.startTimeStamp = Date()
self.player.play()
}
// MARK: - JWPlayerViewControllerDelegate // MARK: - JWPlayerViewControllerDelegate
override func jwplayer(_ player: any JWPlayer, didFinishLoadingWithTime loadTime: TimeInterval) { override func jwplayer(_ player: any JWPlayer, didFinishLoadingWithTime loadTime: TimeInterval) {
super.jwplayer(player, didFinishLoadingWithTime: loadTime) super.jwplayer(player, didFinishLoadingWithTime: loadTime)
print("LoadTime", loadTime) print("LoadTime", loadTime)
DispatchQueue.main.async { [weak self] in DispatchQueue.main.async { [weak self] in
guard let self else{return} guard let self else{return}
vm.setupKaraoke() vm.setupKaraoke()
@@ -241,6 +288,9 @@ extension JWKaraokePlayerVC {
// self.setDeviceOrientation(orientation: .portrait) // self.setDeviceOrientation(orientation: .portrait)
self.player.stop() self.player.stop()
self.dismiss(animated: true) self.dismiss(animated: true)
vm.updateKaraokeVideoView()
print("playerViewControllerWillGoFullScreen") print("playerViewControllerWillGoFullScreen")
return nil return nil
} }
@@ -257,13 +307,13 @@ extension JWKaraokePlayerVC {
} }
func playerViewControllerDidDismissFullScreen(_ controller: JWPlayerViewController) { func playerViewControllerDidDismissFullScreen(_ controller: JWPlayerViewController) {
print("playerViewControllerDidDismissFullScreen") // print("playerViewControllerDidDismissFullScreen")
//
self.dismissTapped?() // self.dismissTapped?()
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { _ in // Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { _ in
self.player.stop() // self.player.stop()
controller.dismiss(animated: true) // controller.dismiss(animated: true)
} // }
} }
} }

View File

@@ -65,6 +65,13 @@ class KaraokeListingVC: UIViewController {
vm.updateTableHeight() vm.updateTableHeight()
} }
override func viewDidAppear(_ animated: Bool) {
if K.GVar.reloadContinueKaraoke{
K.GVar.reloadContinueKaraoke = false
self.vm.getContinueWatching()
}
}
@IBAction func loadMoreBtnTapped(_ sender: LocalisedElementsButton) { @IBAction func loadMoreBtnTapped(_ sender: LocalisedElementsButton) {
PersistentStorage.shared.addOthersCount() PersistentStorage.shared.addOthersCount()
loadMoreBtn.isHidden = true loadMoreBtn.isHidden = true

View File

@@ -26,7 +26,10 @@ class JWKaraokePlayerVM{
var startTime : TimeInterval? var startTime : TimeInterval?
var endTime : TimeInterval? var endTime : TimeInterval?
var startTimeStamp = Date()
func initView(){ func initView(){
startTimeStamp = Date()
vc.downloadRecordingBtn.isEnabled = false vc.downloadRecordingBtn.isEnabled = false
hideShowKaraoke(isLoading: true) hideShowKaraoke(isLoading: true)
} }
@@ -85,6 +88,19 @@ class JWKaraokePlayerVM{
} }
} }
// MARK: - App LifeCycle HAndler
func updateKaraokeVideoView(){
if let postID {
let duration = DateFormatterLib.dateDifferenceINT(date1: startTimeStamp, date2: Date())
AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.karaokeVideo.rawValue, duration: duration, catID: 0) { isDone in
if isDone{
K.GVar.reloadContinueKaraoke = true
}
}
}
}
// MARK: - AudioRecording // MARK: - AudioRecording
func setupAudio() { func setupAudio() {

View File

@@ -0,0 +1,45 @@
//
// AuthFuncUserVideoView.swift
// WOKA
//
// Created by Bilal on 16/08/2024.
//
import Foundation
import Alamofire
extension AuthFunc{
func userVideoView(postID : Int, postType : Int, duration : Int, catID : Int, onCompletion : @escaping (Bool) -> Void){
let headers : HTTPHeaders = ["access-token" : AuthFunc.shareInstance.getAccessToken(),
"device-id": AuthFunc.shareInstance.getDeviceUUID()]
let params : Parameters = ["post_id" : postID,
"post_type" : postType,
"total_watched_duration" : duration,
"device_type" : "2", //1- android, 2 - iOS
"category_id": catID]
NetworkManager.shareInstance.apiRequest(url: APIEndPoints.Analytics.user_video_view, method: .post,parameters: params,headers: headers) { (result : Result<CommonResponseModel, NetworkManager.APIError>) in
switch result{
case .success(let data):
switch data.success{
case 0:
/*
Error
*/
Utilities.dismissProgressHUD()
onCompletion(false)
case 1:
Utilities.dismissProgressHUD()
print("Updated PostType:- \(postType)")
onCompletion(true)
default:
onCompletion(false)
}
case .failure(let error):
Utilities.dismissProgressHUD()
print(error)
onCompletion(false)
}
}
}
}

View File

@@ -144,6 +144,7 @@ struct APIEndPoints {
struct Analytics{ struct Analytics{
static let user_clicks = makeURL(path: "v2/user_clicks") static let user_clicks = makeURL(path: "v2/user_clicks")
static let user_video_view = makeURL(path: "user_video_view")
} }
// Helper method to construct full URL from base URL and path // Helper method to construct full URL from base URL and path

View File

@@ -15,7 +15,6 @@ import CoreData
enum PersistentStorageEnum : String{ enum PersistentStorageEnum : String{
case UserClicks case UserClicks
case click_counts case click_counts
case category_id case category_id
case post_id case post_id
@@ -41,25 +40,6 @@ enum PostType: Int {
case home = 16 case home = 16
} }
//enum PostType: String {
// case series = "1"
// case season = "2"
// case episode = "3"
// case video = "4"
//// case paint = "5"
// case game = "6"
// case audio = "7"
// case karaokeVideo = "8"
// case shopProduct = "9"
//// case parentalVideo = "10"
//// case article = "11"
// case liveTV = "12"
// case FM = "13"
// case teaser = "14"
// case others = "15"
// case home = "16"
//}
struct UserClickData { struct UserClickData {
let clickCounts: Int let clickCounts: Int
let categoryId: Int let categoryId: Int
@@ -67,6 +47,13 @@ struct UserClickData {
let postType: Int let postType: Int
} }
//struct UserVideoViewData {
// let postId: Int
// let postType: Int
// let watchedDuration: Double
// let categoryId: Int
//}
final class PersistentStorage final class PersistentStorage
{ {
@@ -126,18 +113,18 @@ final class PersistentStorage
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: PersistentStorageEnum.UserClicks.rawValue) let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: PersistentStorageEnum.UserClicks.rawValue)
// fetchRequest.fetchLimit = 1 // fetchRequest.fetchLimit = 1
// fetchRequest.predicate = NSPredicate(format: "id == %d" ,id) // fetchRequest.predicate = NSPredicate(format: "id == %d" ,id)
fetchRequest.predicate = NSPredicate(format: "\(key.rawValue) == %@" ,clicksData.postType.toString()) fetchRequest.predicate = NSPredicate(format: "\(key.rawValue) == %@ AND post_id == %@" ,clicksData.postType.toString(),clicksData.postId.toString())
do { do {
guard let result = try managedContext.fetch(fetchRequest) as? [UserClicks] else {return} guard let result = try managedContext.fetch(fetchRequest) as? [UserClicks] else {return}
if result.isEmpty{ if result.isEmpty{
//create //create
PersistentStorage.shared.createData(data: clicksData) PersistentStorage.shared.createData(data: clicksData)
print("create") print("create, In Exist")
}else{ }else{
//update //update
let objectUpdate = result[0] as NSManagedObject let objectUpdate = result[0] as NSManagedObject
print("Update") print("Update, In Exist")
objectUpdate.setValue(result.first!.click_counts + Int64(clicksData.clickCounts), forKey: "click_counts") objectUpdate.setValue(result.first!.click_counts + Int64(clicksData.clickCounts), forKey: "click_counts")
do{ do{
try managedContext.save() try managedContext.save()
@@ -216,7 +203,7 @@ final class PersistentStorage
//We need to create a context from this container //We need to create a context from this container
let managedContext = PersistentStorage.shared.context let managedContext = PersistentStorage.shared.context
let fetchRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "UserClicks") let fetchRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "UserClicks")
fetchRequest.fetchLimit = 4 fetchRequest.fetchLimit = 10
do { do {
guard let result = try managedContext.fetch(fetchRequest) as? [UserClicks] else {return} guard let result = try managedContext.fetch(fetchRequest) as? [UserClicks] else {return}
result.forEach { clicks in result.forEach { clicks in
@@ -238,7 +225,7 @@ final class PersistentStorage
// let path = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) // let path = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
// debugPrint(path[0]) // debugPrint(path[0])
let fetchRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "UserClicks") let fetchRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "UserClicks")
fetchRequest.fetchLimit = 4 fetchRequest.fetchLimit = 15
do { do {
guard let result = try managedContext.fetch(fetchRequest) as? [UserClicks] else {return} guard let result = try managedContext.fetch(fetchRequest) as? [UserClicks] else {return}
var userClicks = [ClicksAnalytics]() var userClicks = [ClicksAnalytics]()
@@ -275,73 +262,8 @@ final class PersistentStorage
debugPrint("Failed to delete data:", error) debugPrint("Failed to delete data:", error)
} }
} }
// func updateData(){
// //We need to create a context from this container
// let managedContext = PersistentStorage.shared.context
//
//
// let fetchRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "UserClicks")
// fetchRequest.predicate = NSPredicate(format: "uuid = %@", "2")
// do
// {
// let test = try managedContext.fetch(fetchRequest)
//
// let objectUpdate = test[0] as! NSManagedObject
// objectUpdate.setValue("Bilal Ahmed Khan New Name", forKey: "name")
// do{
// try managedContext.save()
// self.retrieveData()
// }
// catch
// {
// print(error)
// }
// }
// catch
// {
// print(error)
// }
//
// }
// func deleteData(){ // MARK: - Handle Clicks For UserClicks
// //We need to create a context from this container
// let managedContext = PersistentStorage.shared.context
//
// let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "UserClicks")
//// fetchRequest.fetchLimit = 1
//// fetchRequest.predicate = NSPredicate(format: "uuid = %@ AND uuid = %@", "1", "1")
// fetchRequest.predicate = NSPredicate(format: "post_id = %@", "11")
//
// do
// {
// let test = try managedContext.fetch(fetchRequest)
//
// let objectToDelete = test[0] as! NSManagedObject
//// test.forEach { obbject in
//// managedContext.delete(obbject as! NSManagedObject)
//// }
// managedContext.delete(test.first as! NSManagedObject)
//// managedContext.delete(objectToDelete)
//
// do{
// try managedContext.save()
//// self.createData()
// self.retrieveData()
// }
// catch
// {
// print(error)
// }
//
// }
// catch
// {
// print(error)
// }
// }
// MARK: - Handle Clicks
func addOthersCount(){ func addOthersCount(){
let userClicks = UserClickData(clickCounts: 1, categoryId: 0, postId: 0, postType: PostType.others.rawValue) let userClicks = UserClickData(clickCounts: 1, categoryId: 0, postId: 0, postType: PostType.others.rawValue)
@@ -389,4 +311,51 @@ final class PersistentStorage
let userClicks = UserClickData(clickCounts: 1, categoryId: catID, postId: postID, postType: postType.rawValue) let userClicks = UserClickData(clickCounts: 1, categoryId: catID, postId: postID, postType: postType.rawValue)
PersistentStorage.shared.checkWebSeries(clicksData: userClicks) PersistentStorage.shared.checkWebSeries(clicksData: userClicks)
} }
// MARK: - Handling UserViewView CRUD
// func createVideoViewData(data : UserVideoViewData){
//
// //We need to create a context from this container
// let managedContext = PersistentStorage.shared.context
//
// let videoData = UserVideoView(context: managedContext)
// videoData.post_id = Int64(data.postId)
// videoData.post_type = Int64(data.postType)
// videoData.total_watched_duration = data.watchedDuration
// videoData.category_id = Int64(data.categoryId)
//
// do {
// try managedContext.save()
// retrieveData(postID: data.postId, catID: data.categoryId, postType: data.postType)
// } catch let error as NSError {
// print("Could not save. \(error), \(error.userInfo)")
// }
// }
//
// func retrieveVideoViewData(postID : Int?, catID : Int?, postType : Int) {
//
// //We need to create a context from this container
// let managedContext = PersistentStorage.shared.context
//
// let path = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
// // debugPrint(path[0])
// let fetchRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "UserVideoView")
//
// fetchRequest.predicate = NSPredicate(format: "post_id == %@ AND category_id == %@ AND post_type == %@" ,postID?.toString() ?? "0", catID?.toString() ?? "0" ,postType.toString())
//
// do {
// guard let result = try managedContext.fetch(fetchRequest) as? [UserClicks] else {return}
// result.forEach { clicks in
// print("VideoView:- ","ID:-" , PostType(rawValue: Int(clicks.post_type))!, "CatID:- ", clicks.category_id, "PostID:- ", clicks.post_id , "Count:-", clicks.click_counts)
// }
// }
// catch let error
// {
// debugPrint(error)
// }
// }
// MARK: - Handle Clicks For UserVideoView
} }

View File

@@ -1098,19 +1098,19 @@
<cells/> <cells/>
</collectionView> </collectionView>
<stackView hidden="YES" opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="Nqj-wh-mOZ"> <stackView hidden="YES" opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="Nqj-wh-mOZ">
<rect key="frame" x="113.66666666666669" y="295.66666666666669" width="166" height="245.66666666666669"/> <rect key="frame" x="93.666666666666686" y="295.66666666666669" width="206" height="245.66666666666669"/>
<subviews> <subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="SupportGirlImage" translatesAutoresizingMaskIntoConstraints="NO" id="aKI-uI-tys"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="SupportGirlImage" translatesAutoresizingMaskIntoConstraints="NO" id="aKI-uI-tys">
<rect key="frame" x="0.0" y="0.0" width="166" height="166"/> <rect key="frame" x="0.0" y="0.0" width="206" height="166"/>
</imageView> </imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="No Blogs Found" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="h4b-OB-vin" customClass="LocalisedElementsLabel" customModule="WOKA" customModuleProvider="target"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="No Notification Found" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="h4b-OB-vin" customClass="LocalisedElementsLabel" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="0.0" y="176" width="166" height="24"/> <rect key="frame" x="0.0" y="176" width="206" height="24"/>
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="20"/> <fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="20"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="JCl-tp-aCA"> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="JCl-tp-aCA">
<rect key="frame" x="0.0" y="210" width="166" height="35.666666666666657"/> <rect key="frame" x="0.0" y="210" width="206" height="35.666666666666657"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" title="Button"/> <state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="plain"> <buttonConfiguration key="configuration" style="plain">
@@ -1319,7 +1319,7 @@
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor> </systemColor>
<systemColor name="systemBrownColor"> <systemColor name="systemBrownColor">
<color red="0.63529411759999999" green="0.51764705879999995" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color red="0.63529411764705879" green="0.51764705882352946" blue="0.36862745098039218" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor> </systemColor>
</resources> </resources>
</document> </document>

View File

@@ -41,7 +41,7 @@ class MoreVC: UIViewController {
@IBAction func playTrailerBtnTapped(_ sender: LocalisedElementsButton) { @IBAction func playTrailerBtnTapped(_ sender: LocalisedElementsButton) {
PersistentStorage.shared.addTrailerCount() PersistentStorage.shared.addTrailerCount()
let item = JwPlayerItemCreate(url: APIEndPoints.StaticURLs.masilaUrl, poster: nil, titles: "Masila") let item = JwPlayerItemCreate(url: APIEndPoints.StaticURLs.masilaUrl, poster: nil, titles: "Masila")
JWPlayerManager.shared.presentPlayer(from: self, playerItems: [item], contentType: .trailer) JWPlayerManager.shared.presentPlayer(from: self, playerItems: [item], contentType: .trailer, videoIDs: [0])
} }
} }
@@ -256,45 +256,45 @@ extension MoreVC : UICollectionViewDelegateFlowLayout{
} }
class VideoAVPlayer { //class VideoAVPlayer {
//
var player: AVPlayer? // var player: AVPlayer?
var playerObserver: NSKeyValueObservation? // var playerObserver: NSKeyValueObservation?
var status = PlayerStatus.loading // var status = PlayerStatus.loading
//
init(url: URL) { // init(url: URL) {
self.player = AVPlayer(url: url) // self.player = AVPlayer(url: url)
observePlayer() // observePlayer()
} // }
//
private func observePlayer() { // private func observePlayer() {
playerObserver = player?.observe(\.timeControlStatus, options: [.new, .old], changeHandler: { [weak self] player, change in // playerObserver = player?.observe(\.timeControlStatus, options: [.new, .old], changeHandler: { [weak self] player, change in
guard let self = self else { return } // guard let self = self else { return }
switch player.timeControlStatus { // switch player.timeControlStatus {
case .playing: // case .playing:
print("Player is playing") // print("Player is playing")
self.status = .play // self.status = .play
case .paused: // case .paused:
print("Player is paused") // print("Player is paused")
self.status = .pause // self.status = .pause
case .waitingToPlayAtSpecifiedRate: // case .waitingToPlayAtSpecifiedRate:
print("Player is waiting to play at specified rate") // print("Player is waiting to play at specified rate")
self.status = .loading // self.status = .loading
@unknown default: // @unknown default:
print("Unknown player status") // print("Unknown player status")
} // }
}) // })
} // }
//
deinit { // deinit {
playerObserver?.invalidate() // playerObserver?.invalidate()
} // }
//
func play() { // func play() {
player?.play() // player?.play()
} // }
//
func pause() { // func pause() {
player?.pause() // player?.pause()
} // }
} //}

View File

@@ -9,7 +9,7 @@ import UIKit
import JWPlayerKit import JWPlayerKit
import AVKit import AVKit
class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate { class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate{
@IBOutlet weak var backButton: UIButton! @IBOutlet weak var backButton: UIButton!
var previousScale: CGFloat = 1.0 var previousScale: CGFloat = 1.0
@@ -19,8 +19,17 @@ class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate {
var config: JWPlayerConfiguration! var config: JWPlayerConfiguration!
var dismissTapped: (() -> Void)? var dismissTapped: (() -> Void)?
var videoIndex : Int? var videoIndex : Int?
var isFullScreenBtn = false var isFullScreenBtn = false
var vm = PlayerVM()
deinit {
NotificationCenter.default.removeObserver(self,name: UIApplication.didEnterBackgroundNotification, object: nil)
NotificationCenter.default.removeObserver(self,name: UIApplication.willEnterForegroundNotification, object: nil)
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask { override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .allButUpsideDown return .allButUpsideDown
} }
@@ -31,40 +40,20 @@ class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
vm.vc = self
vm.initView()
// rotateView(to: .pi / 2) // Example: 90 degrees rotation // rotateView(to: .pi / 2) // Example: 90 degrees rotation
//bring back button to the front //bring back button to the front
self.view.bringSubviewToFront(backButton) self.view.bringSubviewToFront(backButton)
// NotificationCenter.default.addObserver(self, selector: #selector(appDidEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(appDidEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
// NotificationCenter.default.addObserver(self, selector: #selector(appWillEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(appWillEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
} }
// MARK: - Notification Center Handlers
@objc func appDidEnterBackground() {
// Code to execute when the app enters the background
print("App entered background PlayerVC")
if UIApplication.topViewController() == self{
player.stop()
}
}
@objc func appWillEnterForeground() {
// Code to execute when the app enters the foreground
print("App will enter foreground PlayerVC")
if UIApplication.topViewController() == self{
player.play()
}
}
// func rotateView(to angle: CGFloat) { // func rotateView(to angle: CGFloat) {
// // Apply rotation to the view's transform // // Apply rotation to the view's transform
// view.transform = CGAffineTransform(rotationAngle: angle) // view.transform = CGAffineTransform(rotationAngle: angle)
// } // }
@objc func applicationDidBecomeActive() {
// self.setDeviceOrientation(orientation: .landscapeRight)
}
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
@@ -88,77 +77,147 @@ class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate {
} }
@IBAction func backBtnTapped(_ sender: UIButton) { @IBAction func backBtnTapped(_ sender: UIButton) {
handleBackAction()
}
func handleBackAction(){
self.interfaceBehavior = .hidden
self.player.stop()
if contentType == .liveStream{
self.dismissTapped?()
}
appDelegate.deviceOrientation = .portrait
updateClicks()
let value = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
UIViewController.attemptRotationToDeviceOrientation()
}
func updateClicks(){
switch contentType { switch contentType {
case .liveStream: case .liveStream:
PersistentStorage.shared.addLiveTVCount() if let postID = vm.videoIDs.first {
// case .webSeries: let duration = DateFormatterLib.dateDifferenceINT(date1: vm.startTimeStamp, date2: Date())
//// PersistentStorage.shared.addOthersCount() let totalDuration = duration + vm.totalVideoViewTime
AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.liveTV.rawValue, duration: totalDuration, catID: 0) { _ in}
vm.handleBackAction()
}
case .webSeries:
if let catID = vm.catID, vm.currentPlayingIndex >= 0 && vm.currentPlayingIndex < (vm.videoIDs.count - 1) {
let postID = vm.videoIDs[vm.currentPlayingIndex]
let duration = DateFormatterLib.dateDifferenceINT(date1: vm.startTimeStamp, date2: Date())
let totalDuration = duration + vm.totalVideoViewTime
Utilities.startProgressHUD(msg: K.ConstantString.sync)
AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.episode.rawValue, duration: totalDuration, catID: catID) { [weak self] isDone in
guard let self else{return}
if isDone{
Utilities.dismissProgressHUD()
vm.handleBackAction()
K.GVar.reloadContinueWebSeries = true
}else{
Utilities.dismissProgressHUD()
vm.handleBackAction()
}
}
} else {
vm.handleBackAction()
}
case .trailer: case .trailer:
PersistentStorage.shared.addTrailerCount() let duration = DateFormatterLib.dateDifferenceINT(date1: vm.startTimeStamp, date2: Date())
// case .continueWatching: let totalDuration = duration + vm.totalVideoViewTime
// <#code#> AuthFunc.shareInstance.userVideoView(postID: 0, postType: PostType.episode.rawValue, duration: totalDuration, catID: 0) { _ in}
// case .audioBooks: vm.handleBackAction()
// <#code#> case .continueWatching:
// case .games: if let catID = vm.catID,let postID = vm.videoIDs.first{
// <#code#> let duration = DateFormatterLib.dateDifferenceINT(date1: vm.startTimeStamp, date2: Date())
// case .songs: let totalDuration = duration + vm.totalVideoViewTime
// <#code#> Utilities.startProgressHUD(msg: K.ConstantString.sync)
case nil: AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.episode.rawValue, duration: totalDuration, catID: catID) { [weak self] isDone in
guard let self else{return}
if isDone{
Utilities.dismissProgressHUD()
vm.handleBackAction()
K.GVar.reloadContinueWebSeries = true
}else{
Utilities.dismissProgressHUD()
vm.handleBackAction()
}
}
} else {
vm.handleBackAction()
}
case .audioBooks:
if let postID = vm.videoIDs.first {
let duration = DateFormatterLib.dateDifferenceINT(date1: vm.startTimeStamp, date2: Date())
let totalDuration = duration + vm.totalVideoViewTime
Utilities.startProgressHUD(msg: K.ConstantString.sync)
AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.audio.rawValue, duration: totalDuration, catID: 0) { [weak self] isDone in
guard let self else{
Utilities.dismissProgressHUD()
return
}
if isDone{
Utilities.dismissProgressHUD()
vm.handleBackAction()
}else{
Utilities.dismissProgressHUD()
vm.handleBackAction()
}
}
}
case .games:
break
case .songs:
break
default:
vm.handleBackAction()
}
}
// MARK: - App LifeCycle Handling
@objc func appDidEnterBackground() {
print("App entered background PlayerVC")
player.pause()
//Update uservideo view
switch contentType {
case .liveStream:
vm.updateUserView()
case .webSeries:
vm.updateUserView()
case .trailer:
vm.updateUserView()
case .continueWatching:
vm.updateUserView()
case .audioBooks:
vm.updateUserView()
case .games:
break
case .songs:
break break
default: default:
break break
} }
} }
@objc func appWillEnterForeground() {
print("App will enter foreground PlayerVC")
//Reset StartTimestamp
vm.startTimeStamp = Date()
player.play()
}
// MARK: - Handle Screen Transition // MARK: - Handle Screen Transition
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator) super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: nil) { _ in coordinator.animate(alongsideTransition: nil) { [weak self] _ in
self.checkOrientation() guard let self else{return}
} vm.checkOrientation()
}
private func checkOrientation() {
let isPortrait = UIScreen.main.bounds.size.width < UIScreen.main.bounds.size.height
if isPortrait {
print("Device is in portrait mode")
Timer.scheduledTimer(withTimeInterval: 0.4, repeats: false) { _ in
self.dismiss(animated: true)
}
} else {
print("Device is in landscape mode")
if isFullScreenBtn{
appDelegate.deviceOrientation = .portrait
let value = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
UIViewController.attemptRotationToDeviceOrientation()
}
} }
} }
// MARK: - JWPlayerViewControllerDelegate // MARK: - JWPlayerViewControllerDelegate
// override func jwplayerPlaylistHasCompleted(_ player: any JWPlayer) {
// print("PlayList Over")
// }
// this will give index
override func jwplayer(_ player: any JWPlayer, didLoadPlaylistItem item: JWPlayerItem, at index: UInt) {
super.jwplayer(player, didLoadPlaylistItem: item, at: index)
print("didLoadPlaylistItem ", index)
vm.currentPlayingIndex = Int(index)
}
override func jwplayer(_ player: any JWPlayer, didFinishLoadingWithTime loadTime: TimeInterval) { override func jwplayer(_ player: any JWPlayer, didFinishLoadingWithTime loadTime: TimeInterval) {
super.jwplayer(player, didFinishLoadingWithTime: loadTime) super.jwplayer(player, didFinishLoadingWithTime: loadTime)
print("LoadTime", loadTime) print("LoadTime", loadTime)
@@ -194,8 +253,6 @@ class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate {
case nil: case nil:
break break
} }
print("IsReady") print("IsReady")
} }
@@ -211,19 +268,19 @@ class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate {
DispatchQueue.main.async { DispatchQueue.main.async {
Utilities.alertWithBtnCancelCompletion(title: "Error", msgBody: message, okBtnStr: "Connect", vc: self) { [weak self] isDone in Utilities.alertWithBtnCancelCompletion(title: "Error", msgBody: message, okBtnStr: "Connect", vc: self) { [weak self] isDone in
guard let self else{ guard let self else{
self?.handleBackAction() self?.vm.handleBackAction()
return return
} }
if isDone{ if isDone{
self.player.configurePlayer(with: config) self.player.configurePlayer(with: config)
self.player.play() self.player.play()
}else{ }else{
self.handleBackAction() self.vm.handleBackAction()
} }
} }
} }
} }
override func jwplayer(_ player: JWPlayer, encounteredWarning code: UInt, message: String) { override func jwplayer(_ player: JWPlayer, encounteredWarning code: UInt, message: String) {
super.jwplayer(player, encounteredWarning: code, message: message) super.jwplayer(player, encounteredWarning: code, message: message)
//Handle the reconnecting of video here //Handle the reconnecting of video here
@@ -250,7 +307,7 @@ class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate {
override func jwplayer(_ player: JWPlayer, didPauseWithReason reason: JWPauseReason) { override func jwplayer(_ player: JWPlayer, didPauseWithReason reason: JWPauseReason) {
super.jwplayer(player, didPauseWithReason: reason) super.jwplayer(player, didPauseWithReason: reason)
if reason == .interaction{ if reason == .interaction{
updateClicks() vm.updateClicks()
} }
// Implement custom behavior // Implement custom behavior
} }
@@ -259,10 +316,10 @@ class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate {
override func jwplayer(_ player: JWPlayer, isPlayingWithReason reason: JWPlayReason) { override func jwplayer(_ player: JWPlayer, isPlayingWithReason reason: JWPlayReason) {
super.jwplayer(player, isPlayingWithReason: reason) super.jwplayer(player, isPlayingWithReason: reason)
if reason == .interaction{ if reason == .interaction{
updateClicks() vm.updateClicks()
} }
} }
} }
// MARK: - Full Screen Handling // MARK: - Full Screen Handling
@@ -289,13 +346,19 @@ extension PlayerVC {
} }
func playerViewControllerWillDismissFullScreen(_ controller: JWPlayerViewController) { func playerViewControllerWillDismissFullScreen(_ controller: JWPlayerViewController) {
switch contentType {
case .audioBooks,.liveStream,.webSeries, .continueWatching, .trailer:
vm.updateUserView()
default:
break
}
print("playerViewControllerWillDismissFullScreen") print("playerViewControllerWillDismissFullScreen")
} }
func playerViewControllerDidDismissFullScreen(_ controller: JWPlayerViewController) { func playerViewControllerDidDismissFullScreen(_ controller: JWPlayerViewController) {
print("playerViewControllerDidDismissFullScreen") print("playerViewControllerDidDismissFullScreen")
appDelegate.deviceOrientation = .portrait appDelegate.deviceOrientation = .portrait
updateClicks() vm.updateClicks()
let value = UIInterfaceOrientation.portrait.rawValue let value = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(value, forKey: "orientation") UIDevice.current.setValue(value, forKey: "orientation")
UIViewController.attemptRotationToDeviceOrientation() UIViewController.attemptRotationToDeviceOrientation()
@@ -327,7 +390,7 @@ extension PlayerVC {
} }
func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, relatedItemBeganPlaying item: JWPlayerKit.JWPlayerItem, atIndex index: Int, withMethod method: JWPlayerKit.JWRelatedMethod) { func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, relatedItemBeganPlaying item: JWPlayerKit.JWPlayerItem, atIndex index: Int, withMethod method: JWPlayerKit.JWRelatedMethod) {
print("Item ", item) print("Item ", item, index)
} }
} }

View File

@@ -128,6 +128,8 @@ class ThemeOneVC: UIViewController {
let sb = UIStoryboard(name: K.StoryBoard.theme, bundle: nil) let sb = UIStoryboard(name: K.StoryBoard.theme, bundle: nil)
let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Home.userNotificationVC) as! UserNotificationVC let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Home.userNotificationVC) as! UserNotificationVC
self.navigationController?.pushViewController(vcPush, animated: true) self.navigationController?.pushViewController(vcPush, animated: true)
PersistentStorage.shared.sendDataToServer()
} }
@IBAction func radioBtnTapped(_ sender: UIButton) { @IBAction func radioBtnTapped(_ sender: UIButton) {

View File

@@ -6,6 +6,7 @@
// //
import UIKit import UIKit
import AVFAudio
class ThemeTwoVC: UIViewController { class ThemeTwoVC: UIViewController {
@@ -44,6 +45,9 @@ class ThemeTwoVC: UIViewController {
override func viewDidAppear(_ animated: Bool) { override func viewDidAppear(_ animated: Bool) {
K.GVar.topView = .theme2 K.GVar.topView = .theme2
if let player = vm.avPlayer{
player.play()
}
} }
override func viewDidLayoutSubviews() { override func viewDidLayoutSubviews() {
@@ -72,7 +76,7 @@ class ThemeTwoVC: UIViewController {
@IBAction func playTrailer(_ sender: LocalisedElementsButton) { @IBAction func playTrailer(_ sender: LocalisedElementsButton) {
PersistentStorage.shared.addOthersCount() PersistentStorage.shared.addOthersCount()
let item = JwPlayerItemCreate(url: APIEndPoints.StaticURLs.masilaUrl, poster: nil, titles: "Masila") let item = JwPlayerItemCreate(url: APIEndPoints.StaticURLs.masilaUrl, poster: nil, titles: "Masila")
JWPlayerManager.shared.presentPlayer(from: self, playerItems: [item], contentType: .trailer) JWPlayerManager.shared.presentPlayer(from: self, playerItems: [item], contentType: .trailer, videoIDs: [0])
} }
} }

View File

@@ -41,9 +41,12 @@ class MoreVM{
vc.songTableView.showsVerticalScrollIndicator = false vc.songTableView.showsVerticalScrollIndicator = false
vc.songTableView.showsHorizontalScrollIndicator = false vc.songTableView.showsHorizontalScrollIndicator = false
vc.homeBtn.addTapGesture { vc.homeBtn.addTapGesture { [weak self] in
self.vc.dismiss(animated: true) { guard let self else{return}
PersistentStorage.shared.addOthersCount() DispatchQueue.main.async{
self.vc.dismiss(animated: true) {
PersistentStorage.shared.addOthersCount()
}
} }
} }
} }

View File

@@ -0,0 +1,172 @@
//
// PlayerVM.swift
// WOKA
//
// Created by Bilal on 16/08/2024.
//
import UIKit
class PlayerVM{
weak var vc : PlayerVC!
// this will map the start time
var startTimeStamp = Date()
var totalVideoViewTime = 0
// this will come from webseries, audiobooks, live tv
var videoIDs = [Int]()
// this will come only for webseries
var catID : Int?
// this will store the index of the item playing
var currentPlayingIndex = 0
func initView(){
switch vc.contentType {
case .liveStream, .trailer, .continueWatching, .audioBooks:
startTimeStamp = Date()
// case .games:
// <#code#>
// case .songs:
// <#code#>
case nil:
break
default:
break
}
}
// MARK: - Update UserVideo View
func updateUserView(){
switch vc.contentType {
case .liveStream:
if let postID = videoIDs.first {
let duration = DateFormatterLib.dateDifferenceINT(date1: startTimeStamp, date2: Date())
let totalDuration = duration + totalVideoViewTime
startTimeStamp = Date()
AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.liveTV.rawValue, duration: totalDuration, catID: 0) { isDone in
if isDone{
K.GVar.reloadContinueAudioBooks = true
}else{
}
}
}
case .webSeries:
if let catID = catID, currentPlayingIndex >= 0 && currentPlayingIndex < (videoIDs.count - 1) {
let postID = videoIDs[currentPlayingIndex]
let duration = DateFormatterLib.dateDifferenceINT(date1: startTimeStamp, date2: Date())
let totalDuration = duration + totalVideoViewTime
startTimeStamp = Date()
AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.episode.rawValue, duration: totalDuration, catID: catID) { isDone in
if isDone{
K.GVar.reloadContinueWebSeries = true
}
}
}
case .trailer:
let duration = DateFormatterLib.dateDifferenceINT(date1: startTimeStamp, date2: Date())
let totalDuration = duration + totalVideoViewTime
AuthFunc.shareInstance.userVideoView(postID: 0, postType: PostType.episode.rawValue, duration: totalDuration, catID: 0) { _ in}
case .continueWatching:
if let catID = catID , let postID = videoIDs.first{
let duration = DateFormatterLib.dateDifferenceINT(date1: startTimeStamp, date2: Date())
let totalDuration = duration + totalVideoViewTime
startTimeStamp = Date()
AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.episode.rawValue, duration: totalDuration, catID: catID) { isDone in
if isDone{
K.GVar.reloadContinueWebSeries = true
}
}
}
case .audioBooks:
if let postID = videoIDs.first {
let duration = DateFormatterLib.dateDifferenceINT(date1: startTimeStamp, date2: Date())
let totalDuration = duration + totalVideoViewTime
startTimeStamp = Date()
AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.audio.rawValue, duration: totalDuration, catID: 0) { isDone in
if isDone{
K.GVar.reloadContinueAudioBooks = true
}else{
}
}
}
// case .games:
// <#code#>
// case .songs:
// <#code#>
case nil:
break
default:
break
}
}
// MARK: - Handle Back btn tap, and update clicks
func handleBackAction(){
self.vc.interfaceBehavior = .hidden
self.vc.player.stop()
if vc.contentType == .liveStream{
self.vc.dismissTapped?()
}
appDelegate.deviceOrientation = .portrait
updateClicks()
let value = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
UIViewController.attemptRotationToDeviceOrientation()
}
func updateClicks(){
switch vc.contentType {
case .liveStream:
PersistentStorage.shared.addLiveTVCount()
// case .webSeries:
//// PersistentStorage.shared.addOthersCount()
case .trailer:
PersistentStorage.shared.addTrailerCount()
// case .continueWatching:
// <#code#>
// case .audioBooks:
// <#code#>
// case .games:
// <#code#>
// case .songs:
// <#code#>
case nil:
break
default:
break
}
}
// MARK: - Orientation check
func checkOrientation() {
let isPortrait = UIScreen.main.bounds.size.width < UIScreen.main.bounds.size.height
if isPortrait {
print("Device is in portrait mode")
Timer.scheduledTimer(withTimeInterval: 0.4, repeats: false) { _ in
self.vc.dismiss(animated: true)
}
} else {
print("Device is in landscape mode")
if vc.isFullScreenBtn{
appDelegate.deviceOrientation = .portrait
let value = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
UIViewController.attemptRotationToDeviceOrientation()
}
}
}
}

View File

@@ -205,8 +205,6 @@ class ThemeOneVM{
vcPush.modalPresentationStyle = .fullScreen vcPush.modalPresentationStyle = .fullScreen
vcPush.modalTransitionStyle = .crossDissolve vcPush.modalTransitionStyle = .crossDissolve
self.vc.present(vcPush, animated: true) self.vc.present(vcPush, animated: true)
// PersistentStorage.shared.sendDataToServer()
} }
/* /*
1 = series, 2 = season, 3= episode, 4 = video, 5 = paint, 6 = game, 7 = audio, 8 = kareoke video, 9 = shop product, 10 = parental video, 11 = article, 12 = live TV, 13 = FM, 14 = teaser, 15 others, 16 = Home 1 = series, 2 = season, 3= episode, 4 = video, 5 = paint, 6 = game, 7 = audio, 8 = kareoke video, 9 = shop product, 10 = parental video, 11 = article, 12 = live TV, 13 = FM, 14 = teaser, 15 others, 16 = Home
@@ -441,6 +439,9 @@ class ThemeOneVM{
vc.config = config vc.config = config
vc.dismissTapped = self.tapped vc.dismissTapped = self.tapped
vc.contentType = .liveStream vc.contentType = .liveStream
if let streamID = AuthFunc.shareInstance.staticURLs?.liveData?.first?.id{
vc.vm.videoIDs = [streamID]
}
vc.modalPresentationStyle = .fullScreen vc.modalPresentationStyle = .fullScreen
vc.modalTransitionStyle = .crossDissolve vc.modalTransitionStyle = .crossDissolve

View File

@@ -19,13 +19,45 @@ class WokaFMVC: UIViewController {
@IBOutlet weak var activityIndicator: UIActivityIndicatorView! @IBOutlet weak var activityIndicator: UIActivityIndicatorView!
var vm = WokaFMVM() var vm = WokaFMVM()
deinit {
vm.playerItem.removeObserver(self, forKeyPath: "status")
vm.player.removeObserver(self, forKeyPath: "timeControlStatus")
vm.playerItem.removeObserver(self, forKeyPath: "isPlaybackBufferEmpty")
vm.playerItem.removeObserver(self, forKeyPath: "isPlaybackLikelyToKeepUp")
vm.player?.pause()
NotificationCenter.default.removeObserver(self,name: UIApplication.didEnterBackgroundNotification, object: nil)
// Deactivate the audio session if needed
do {
try AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
} catch {
print("Failed to deactivate audio session: \(error.localizedDescription)")
}
}
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
vm.vc = self vm.vc = self
vm.initView() vm.initView()
NotificationCenter.default.addObserver(self,selector: #selector(appDidEnterBackground),name: UIApplication.didEnterBackgroundNotification,object: nil)
} }
// MARK: - App LifeCycle HAndler
@objc func appDidEnterBackground() {
if let postID = AuthFunc.shareInstance.staticURLs?.liveFmData?.id {
let duration = DateFormatterLib.dateDifferenceINT(date1: vm.startTimeStamp, date2: Date())
AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.FM.rawValue, duration: duration, catID: 0) { [weak self] isDone in
guard let self else{return}
if isDone{
vm.startTimeStamp = Date()
}
}
}
}
@IBAction func playBtnTapped(_ sender: UIButton) { @IBAction func playBtnTapped(_ sender: UIButton) {
PersistentStorage.shared.addRadioCount() PersistentStorage.shared.addRadioCount()
if sender == playBtn{ if sender == playBtn{
@@ -71,6 +103,10 @@ class WokaFMVC: UIViewController {
@IBAction func closeBtnTapped(_ sender: UIButton) { @IBAction func closeBtnTapped(_ sender: UIButton) {
PersistentStorage.shared.addRadioCount() PersistentStorage.shared.addRadioCount()
if let postID = AuthFunc.shareInstance.staticURLs?.liveFmData?.id {
let duration = DateFormatterLib.dateDifferenceINT(date1: vm.startTimeStamp, date2: Date())
AuthFunc.shareInstance.userVideoView(postID: postID, postType: PostType.FM.rawValue, duration: duration, catID: 0) { _ in}
}
self.dismiss(animated: true) self.dismiss(animated: true)
} }
@@ -151,22 +187,6 @@ class WokaFMVC: UIViewController {
} }
} }
} }
deinit {
vm.playerItem.removeObserver(self, forKeyPath: "status")
vm.player.removeObserver(self, forKeyPath: "timeControlStatus")
vm.playerItem.removeObserver(self, forKeyPath: "isPlaybackBufferEmpty")
vm.playerItem.removeObserver(self, forKeyPath: "isPlaybackLikelyToKeepUp")
vm.player?.pause()
// Deactivate the audio session if needed
do {
try AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
} catch {
print("Failed to deactivate audio session: \(error.localizedDescription)")
}
}
} }

View File

@@ -15,7 +15,10 @@ class WokaFMVM{
var player: AVPlayer! var player: AVPlayer!
var playerItem: AVPlayerItem! var playerItem: AVPlayerItem!
var startTimeStamp = Date()
func initView(){ func initView(){
startTimeStamp = Date()
vc.mainView.roundCorners(radius: 10, corners: [.topLeft, .topRight]) vc.mainView.roundCorners(radius: 10, corners: [.topLeft, .topRight])
let color1 = #colorLiteral(red: 0.5921568627, green: 0.2588235294, blue: 0.8941176471, alpha: 1) let color1 = #colorLiteral(red: 0.5921568627, green: 0.2588235294, blue: 0.8941176471, alpha: 1)
let color2 = #colorLiteral(red: 0.368627451, green: 0.1215686275, blue: 0.768627451, alpha: 1) let color2 = #colorLiteral(red: 0.368627451, green: 0.1215686275, blue: 0.768627451, alpha: 1)

View File

@@ -81,7 +81,6 @@
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" image="speaker.wave.1.fill" catalog="system"/> <state key="normal" image="speaker.wave.1.fill" catalog="system"/>
<connections> <connections>
<action selector="playBtnTapped:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="YJE-XF-HOm"/>
<action selector="volumeBtnTapped:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="bZA-9P-p0X"/> <action selector="volumeBtnTapped:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="bZA-9P-p0X"/>
</connections> </connections>
</button> </button>

View File

@@ -64,8 +64,8 @@ class ContinueWatchingVC: UIViewController {
} }
@IBAction func watchBtnTapped(_ sender: LocalisedElementsButton) { @IBAction func watchBtnTapped(_ sender: LocalisedElementsButton) {
guard let watchData else{return} guard let watchData ,let showID = watchData.id else{return}
if let showID = watchData.id, let catID = self.categoryID{ if let catID = self.categoryID{
PersistentStorage.shared.addWebSeries(catID: catID, postID: showID, postType: .episode) PersistentStorage.shared.addWebSeries(catID: catID, postID: showID, postType: .episode)
} }
@@ -88,7 +88,7 @@ class ContinueWatchingVC: UIViewController {
playerItem.url = url playerItem.url = url
} }
JWPlayerManager.shared.presentPlayer(from: self, playerItems: [playerItem], startIndex: 0, contentType: .continueWatching) JWPlayerManager.shared.presentPlayer(from: self, playerItems: [playerItem], startIndex: 0, contentType: .continueWatching,videoIDs: [showID], catID: categoryID)
} }

View File

@@ -107,7 +107,7 @@ class WebSeriesSeasonVC: UIViewController {
playerItems.append(JwPlayerItemCreate(url: url, poster: seasonData.thumbnailPath, titles: hindiData.title)) playerItems.append(JwPlayerItemCreate(url: url, poster: seasonData.thumbnailPath, titles: hindiData.title))
} }
JWPlayerManager.shared.presentPlayer(from: self, playerItems: playerItems, startIndex: 0, contentType: .trailer) JWPlayerManager.shared.presentPlayer(from: self, playerItems: playerItems, startIndex: 0, contentType: .trailer, videoIDs: [0])
} }
@IBAction func loadMoreBtnTapped(_ sender: LocalisedElementsButton) { @IBAction func loadMoreBtnTapped(_ sender: LocalisedElementsButton) {
@@ -186,53 +186,7 @@ extension WebSeriesSeasonVC : TableViewSRC{
playerItems.append(JwPlayerItemCreate(url: url, poster: teaserData.thumbnailPath, titles: hindiData.title)) playerItems.append(JwPlayerItemCreate(url: url, poster: teaserData.thumbnailPath, titles: hindiData.title))
} }
JWPlayerManager.shared.presentPlayer(from: self, playerItems: playerItems, startIndex: indexPath.row, contentType: .trailer) JWPlayerManager.shared.presentPlayer(from: self, playerItems: playerItems, startIndex: indexPath.row, contentType: .trailer, videoIDs: [0])
// let builder = JWPlayerConfigurationBuilder()
//
// do {
// let playlist: [JSONObject] = [
// [
// "file": "https://cdn.jwplayer.com/manifests/gzIo9zlJ.m3u8",
// "title": "First Video Title"
// ],
// [
// "file": "https://cdn.jwplayer.com/manifests/pDu0xxUh.m3u8", // replace with the second video URL
// "title": "Second Video Title",
//
// ]
// ]
//
// let json: JSONObject = [
// "playlist": playlist,
// "playlistIndex": 1,
// "videoGravity" : "resize"
// ]
//
// try builder.configuration(json: json).build()
//
// let config = try builder.configuration(json: json).build()
// let sb = UIStoryboard(name: K.StoryBoard.theme, bundle: nil)
// let vc = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Theme.playerVC) as! PlayerVC
//
// vc.config = config
// vc.contentType = .liveStream
// vc.modalPresentationStyle = .fullScreen
// vc.modalTransitionStyle = .crossDissolve
//
// DispatchQueue.main.async { [weak self] in
// guard let self else{return}
// // Present the PlayerVC
// self.present(vc, animated: false) { [weak self] in
//
// }
// }
//// player.configurePlayer(with: config)
// } catch {
// // Handle build errors
// print("Failed to build JWPlayer configuration: \(error.localizedDescription)")
// }
case self.episodeTableView: case self.episodeTableView:
let episodeData = vm.seasonEpisodeData let episodeData = vm.seasonEpisodeData
@@ -240,10 +194,15 @@ extension WebSeriesSeasonVC : TableViewSRC{
if let showID = episodeData[indexPath.row].id, let catID = self.vm.categoryID{ if let showID = episodeData[indexPath.row].id, let catID = self.vm.categoryID{
PersistentStorage.shared.addWebSeries(catID: catID, postID: showID, postType: .episode) PersistentStorage.shared.addWebSeries(catID: catID, postID: showID, postType: .episode)
} }
var videoIDs = [Int]()
for i in episodeData{ for i in episodeData{
var url = String() var url = String()
guard let englishData = i.contentMoreDetails?.filter({$0.languageMasterID == 1}).first, let hindiData = i.contentMoreDetails?.filter({$0.languageMasterID == 2}).first else{return} guard let englishData = i.contentMoreDetails?.filter({$0.languageMasterID == 1}).first, let hindiData = i.contentMoreDetails?.filter({$0.languageMasterID == 2}).first else{return}
if let id = i.id{
videoIDs.append(id)
}
/* /*
Based on selected Category language update the url Based on selected Category language update the url
*/ */
@@ -263,7 +222,7 @@ extension WebSeriesSeasonVC : TableViewSRC{
} }
} }
JWPlayerManager.shared.presentPlayer(from: self, playerItems: playerItems, startIndex: indexPath.row, contentType: .webSeries) JWPlayerManager.shared.presentPlayer(from: self, playerItems: playerItems, startIndex: indexPath.row, contentType: .webSeries, videoIDs: videoIDs, catID: vm.categoryID)
default: default:
break break
} }
@@ -317,11 +276,16 @@ extension WebSeriesSeasonVC : TableViewSRC{
}else{ }else{
playerItems.append(JwPlayerItemCreate(url: url, poster: teaserData.thumbnailPath, titles: hindiData.title)) playerItems.append(JwPlayerItemCreate(url: url, poster: teaserData.thumbnailPath, titles: hindiData.title))
} }
JWPlayerManager.shared.presentPlayer(from: self, playerItems: playerItems,startIndex: indexPath.row, contentType: .trailer) JWPlayerManager.shared.presentPlayer(from: self, playerItems: playerItems,startIndex: indexPath.row, contentType: .trailer, videoIDs: [0])
case self.episodeTableView: case self.episodeTableView:
let episodeData = vm.seasonEpisodeData let episodeData = vm.seasonEpisodeData
var videoIDs = [Int]()
for i in episodeData{ for i in episodeData{
var url = String() var url = String()
if let id = i.id{
videoIDs.append(id)
}
guard let englishData = i.contentMoreDetails?.filter({$0.languageMasterID == 1}).first, let hindiData = i.contentMoreDetails?.filter({$0.languageMasterID == 2}).first else{return} guard let englishData = i.contentMoreDetails?.filter({$0.languageMasterID == 1}).first, let hindiData = i.contentMoreDetails?.filter({$0.languageMasterID == 2}).first else{return}
/* /*
Based on selected Category language update the url Based on selected Category language update the url
@@ -342,7 +306,7 @@ extension WebSeriesSeasonVC : TableViewSRC{
} }
} }
JWPlayerManager.shared.presentPlayer(from: self, playerItems: playerItems, startIndex: indexPath.row, contentType: .webSeries) JWPlayerManager.shared.presentPlayer(from: self, playerItems: playerItems, startIndex: indexPath.row, contentType: .webSeries, videoIDs: videoIDs,catID: vm.categoryID)
default: default:
break break
} }

View File

@@ -38,6 +38,8 @@ class WebSeriesVC: UIViewController {
var vm = WebSeriesVM() var vm = WebSeriesVM()
private var isFirstLoad = true
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
vm.vc = self vm.vc = self
@@ -45,6 +47,8 @@ class WebSeriesVC: UIViewController {
vm.initView() vm.initView()
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default) navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage() navigationController?.navigationBar.shadowImage = UIImage()
isFirstLoad = false
} }
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
@@ -70,6 +74,19 @@ class WebSeriesVC: UIViewController {
self.navigationController?.setColor(color: .black) self.navigationController?.setColor(color: .black)
} }
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if !isFirstLoad{
if K.GVar.reloadContinueWebSeries{
K.GVar.reloadContinueWebSeries = false
vm.getContinueWatching()
}
}else{
K.GVar.reloadContinueWebSeries = false
}
}
override func viewDidLayoutSubviews() { override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews() super.viewDidLayoutSubviews()
vm.updateTableHeight() vm.updateTableHeight()
@@ -78,7 +95,7 @@ class WebSeriesVC: UIViewController {
// MARK: - Tap Handler // MARK: - Tap Handler
@IBAction func playTrailer(_ sender: LocalisedElementsButton) { @IBAction func playTrailer(_ sender: LocalisedElementsButton) {
let item = JwPlayerItemCreate(url: APIEndPoints.StaticURLs.masilaUrl, poster: nil, titles: "Masila") let item = JwPlayerItemCreate(url: APIEndPoints.StaticURLs.masilaUrl, poster: nil, titles: "Masila")
JWPlayerManager.shared.presentPlayer(from: self, playerItems: [item], contentType: .trailer) JWPlayerManager.shared.presentPlayer(from: self, playerItems: [item], contentType: .trailer, videoIDs: [0])
PersistentStorage.shared.addTrailerCount() PersistentStorage.shared.addTrailerCount()
} }

View File

@@ -29,7 +29,7 @@ class JWPlayerManager {
private init() {} private init() {}
func presentPlayer(from viewController: UIViewController,playerItems : [JwPlayerItemCreate], startIndex: Int = 0, contentType : VideoContentType , completion: (() -> Void)? = nil) { func presentPlayer(from viewController: UIViewController,playerItems : [JwPlayerItemCreate], startIndex: Int = 0, contentType : VideoContentType , videoIDs : [Int],catID : Int? = nil, completion: (() -> Void)? = nil) {
let sb = UIStoryboard(name: K.StoryBoard.theme, bundle: nil) let sb = UIStoryboard(name: K.StoryBoard.theme, bundle: nil)
let playerVC = sb.instantiateViewController(identifier: K.StoryBoardID.Theme.playerVC) as! PlayerVC let playerVC = sb.instantiateViewController(identifier: K.StoryBoardID.Theme.playerVC) as! PlayerVC
@@ -133,7 +133,8 @@ class JWPlayerManager {
playerVC.videoIndex = startIndex playerVC.videoIndex = startIndex
playerVC.contentType = contentType playerVC.contentType = contentType
playerVC.config = finalConfig playerVC.config = finalConfig
playerVC.vm.videoIDs = videoIDs
playerVC.vm.catID = catID
playerVC.modalPresentationStyle = .fullScreen playerVC.modalPresentationStyle = .fullScreen
playerVC.modalTransitionStyle = .crossDissolve playerVC.modalTransitionStyle = .crossDissolve
// Present the PlayerVC // Present the PlayerVC