From b405c17a7a6ff79145b5c66e6c08ecf4551b0b18 Mon Sep 17 00:00:00 2001 From: Bilal Date: Fri, 5 Jul 2024 19:24:20 +0530 Subject: [PATCH] - started working on karaoke - made storyboard and module folder - create ui for listing of karaoke - added api for karaoke list, with data model - made ui dynamic for karaoke listing - Matched the continue watching data with the karaoke listing and decreased code - made custom player view for karaoke - added timer to show hide controls in player --- WOKA.xcodeproj/project.pbxproj | 72 ++ .../Assets.xcassets/Karaoke/Contents.json | 6 + .../Karaoke/Microphone.imageset/Contents.json | 23 + .../Microphone.imageset/Microphone.png | Bin 0 -> 1826 bytes .../Microphone.imageset/Microphone@2x.png | Bin 0 -> 3746 bytes .../Microphone.imageset/Microphone@3x.png | Bin 0 -> 1985 bytes WOKA/Audio Books/ContinueAudioCell.swift | 31 + WOKA/Constants K/StoryBoard.swift | 1 + WOKA/Constants K/StoryBoardID.swift | 8 + WOKA/Helpers/DateFormatterLib.swift | 1 + WOKA/Home/Controller/MyListVC.swift | 2 +- WOKA/Karaoke/Controller/AVPlayerVC.swift | 263 ++++++ .../Karaoke/Controller/KaraokeDetailsVC.swift | 174 ++++ .../Karaoke/Controller/KaraokeListingVC.swift | 233 +++++ WOKA/Karaoke/Karaoke.storyboard | 838 ++++++++++++++++++ .../Model/KaraokeContinueWatchingDM.swift | 19 + WOKA/Karaoke/Model/KaraokeListingDM.swift | 73 ++ WOKA/Karaoke/ViewModel/AVPlayerVM.swift | 17 + WOKA/Karaoke/ViewModel/KaraokeListingVM.swift | 241 +++++ .../hi.lproj/Localizable.strings | 6 + WOKA/Network Adapter/APIEndPoints.swift | 4 + WOKA/Theme/Base.lproj/Theme.storyboard | 65 +- WOKA/Theme/Controller/PlayerVC.swift | 2 +- WOKA/Theme/Controller/ThemeOneVC.swift | 1 + WOKA/Theme/ViewModel/ThemeOneVM.swift | 9 + .../View/WebSeriesShowListingCell.swift | 31 + 26 files changed, 2092 insertions(+), 28 deletions(-) create mode 100644 WOKA/Assets/Assets.xcassets/Karaoke/Contents.json create mode 100644 WOKA/Assets/Assets.xcassets/Karaoke/Microphone.imageset/Contents.json create mode 100644 WOKA/Assets/Assets.xcassets/Karaoke/Microphone.imageset/Microphone.png create mode 100644 WOKA/Assets/Assets.xcassets/Karaoke/Microphone.imageset/Microphone@2x.png create mode 100644 WOKA/Assets/Assets.xcassets/Karaoke/Microphone.imageset/Microphone@3x.png create mode 100644 WOKA/Karaoke/Controller/AVPlayerVC.swift create mode 100644 WOKA/Karaoke/Controller/KaraokeDetailsVC.swift create mode 100644 WOKA/Karaoke/Controller/KaraokeListingVC.swift create mode 100644 WOKA/Karaoke/Karaoke.storyboard create mode 100644 WOKA/Karaoke/Model/KaraokeContinueWatchingDM.swift create mode 100644 WOKA/Karaoke/Model/KaraokeListingDM.swift create mode 100644 WOKA/Karaoke/ViewModel/AVPlayerVM.swift create mode 100644 WOKA/Karaoke/ViewModel/KaraokeListingVM.swift diff --git a/WOKA.xcodeproj/project.pbxproj b/WOKA.xcodeproj/project.pbxproj index 4665eb2..70c0306 100644 --- a/WOKA.xcodeproj/project.pbxproj +++ b/WOKA.xcodeproj/project.pbxproj @@ -183,6 +183,9 @@ 9C0A85432BEE3EC90093783D /* NewPasswordVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C0A85422BEE3EC90093783D /* NewPasswordVM.swift */; }; 9C1C69FA2C106B290035B2C7 /* RSKPlaceholderTextView in Frameworks */ = {isa = PBXBuildFile; productRef = 9C1C69F92C106B290035B2C7 /* RSKPlaceholderTextView */; }; 9C1C69FC2C106C240035B2C7 /* ContactSupportVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C1C69FB2C106C240035B2C7 /* ContactSupportVM.swift */; }; + 9C21F81C2C37E1FA0050BFCC /* KaraokeContinueWatchingDM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C21F81B2C37E1FA0050BFCC /* KaraokeContinueWatchingDM.swift */; }; + 9C21F81E2C37E3CA0050BFCC /* AVPlayerVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C21F81D2C37E3CA0050BFCC /* AVPlayerVC.swift */; }; + 9C21F8222C382A580050BFCC /* AVPlayerVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C21F8212C382A580050BFCC /* AVPlayerVM.swift */; }; 9C27E1602BDB6ECA00EC1DA9 /* UserDefaultsStruct.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C27E15F2BDB6ECA00EC1DA9 /* UserDefaultsStruct.swift */; }; 9C27E1632BDB6F1900EC1DA9 /* AuthFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C27E1622BDB6F1900EC1DA9 /* AuthFunc.swift */; }; 9C27E1652BDB6FBC00EC1DA9 /* StoryBoardID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C27E1642BDB6FBC00EC1DA9 /* StoryBoardID.swift */; }; @@ -232,6 +235,11 @@ 9C9BEEC72BEE1BBF004ECC2F /* CollectionViewCenteredFlowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C9BEEC62BEE1BBF004ECC2F /* CollectionViewCenteredFlowLayout.swift */; }; 9CA7C6C02C1093E500D73742 /* ProfileVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CA7C6BF2C1093E500D73742 /* ProfileVC.swift */; }; 9CA7C6C22C1095B600D73742 /* ProfileVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CA7C6C12C1095B600D73742 /* ProfileVM.swift */; }; + 9CB3D0852C37BA530062869D /* Karaoke.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9CB3D0842C37BA530062869D /* Karaoke.storyboard */; }; + 9CB3D08B2C37BBA50062869D /* KaraokeListingVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CB3D08A2C37BBA50062869D /* KaraokeListingVC.swift */; }; + 9CB3D08D2C37CDD60062869D /* KaraokeListingVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CB3D08C2C37CDD50062869D /* KaraokeListingVM.swift */; }; + 9CB3D08F2C37D0D60062869D /* KaraokeListingDM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CB3D08E2C37D0D60062869D /* KaraokeListingDM.swift */; }; + 9CB3D0912C37D6930062869D /* KaraokeDetailsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CB3D0902C37D6930062869D /* KaraokeDetailsVC.swift */; }; 9CB4C5A92C118EF300737C00 /* NavBarColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CB4C5A82C118EF300737C00 /* NavBarColor.swift */; }; 9CBCB29B2BE4D614007D7934 /* LoginVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CBCB29A2BE4D614007D7934 /* LoginVC.swift */; }; 9CBCB29D2BE4D6BB007D7934 /* LoginVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CBCB29C2BE4D6BB007D7934 /* LoginVM.swift */; }; @@ -455,6 +463,9 @@ 9C0A85402BEE35670093783D /* ResetPassUserNameVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResetPassUserNameVM.swift; sourceTree = ""; }; 9C0A85422BEE3EC90093783D /* NewPasswordVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewPasswordVM.swift; sourceTree = ""; }; 9C1C69FB2C106C240035B2C7 /* ContactSupportVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactSupportVM.swift; sourceTree = ""; }; + 9C21F81B2C37E1FA0050BFCC /* KaraokeContinueWatchingDM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KaraokeContinueWatchingDM.swift; sourceTree = ""; }; + 9C21F81D2C37E3CA0050BFCC /* AVPlayerVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AVPlayerVC.swift; sourceTree = ""; }; + 9C21F8212C382A580050BFCC /* AVPlayerVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AVPlayerVM.swift; sourceTree = ""; }; 9C27E15F2BDB6ECA00EC1DA9 /* UserDefaultsStruct.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsStruct.swift; sourceTree = ""; }; 9C27E1622BDB6F1900EC1DA9 /* AuthFunc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthFunc.swift; sourceTree = ""; }; 9C27E1642BDB6FBC00EC1DA9 /* StoryBoardID.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryBoardID.swift; sourceTree = ""; }; @@ -493,6 +504,11 @@ 9C9BEEC62BEE1BBF004ECC2F /* CollectionViewCenteredFlowLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionViewCenteredFlowLayout.swift; sourceTree = ""; }; 9CA7C6BF2C1093E500D73742 /* ProfileVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileVC.swift; sourceTree = ""; }; 9CA7C6C12C1095B600D73742 /* ProfileVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileVM.swift; sourceTree = ""; }; + 9CB3D0842C37BA530062869D /* Karaoke.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Karaoke.storyboard; sourceTree = ""; }; + 9CB3D08A2C37BBA50062869D /* KaraokeListingVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KaraokeListingVC.swift; sourceTree = ""; }; + 9CB3D08C2C37CDD50062869D /* KaraokeListingVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KaraokeListingVM.swift; sourceTree = ""; }; + 9CB3D08E2C37D0D60062869D /* KaraokeListingDM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KaraokeListingDM.swift; sourceTree = ""; }; + 9CB3D0902C37D6930062869D /* KaraokeDetailsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KaraokeDetailsVC.swift; sourceTree = ""; }; 9CB4C5A82C118EF300737C00 /* NavBarColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavBarColor.swift; sourceTree = ""; }; 9CBCB29A2BE4D614007D7934 /* LoginVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginVC.swift; sourceTree = ""; }; 9CBCB29C2BE4D6BB007D7934 /* LoginVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginVM.swift; sourceTree = ""; }; @@ -658,6 +674,7 @@ 523ED25C2BDA2BC700CFED02 /* WOKA */ = { isa = PBXGroup; children = ( + 9CB3D0832C37BA470062869D /* Karaoke */, 526A436D2C36A96A00AE148F /* Games */, 52BFB52B2C33DA9700BAAE15 /* Audio Books */, 52DAC6462C21761700E2F85B /* WebSeries */, @@ -1347,6 +1364,53 @@ path = HTML; sourceTree = ""; }; + 9CB3D0832C37BA470062869D /* Karaoke */ = { + isa = PBXGroup; + children = ( + 9CB3D0892C37BA650062869D /* Model */, + 9CB3D0882C37BA630062869D /* View */, + 9CB3D0872C37BA610062869D /* ViewModel */, + 9CB3D0862C37BA5F0062869D /* Controller */, + 9CB3D0842C37BA530062869D /* Karaoke.storyboard */, + ); + path = Karaoke; + sourceTree = ""; + }; + 9CB3D0862C37BA5F0062869D /* Controller */ = { + isa = PBXGroup; + children = ( + 9CB3D08A2C37BBA50062869D /* KaraokeListingVC.swift */, + 9CB3D0902C37D6930062869D /* KaraokeDetailsVC.swift */, + 9C21F81D2C37E3CA0050BFCC /* AVPlayerVC.swift */, + ); + path = Controller; + sourceTree = ""; + }; + 9CB3D0872C37BA610062869D /* ViewModel */ = { + isa = PBXGroup; + children = ( + 9CB3D08C2C37CDD50062869D /* KaraokeListingVM.swift */, + 9C21F8212C382A580050BFCC /* AVPlayerVM.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; + 9CB3D0882C37BA630062869D /* View */ = { + isa = PBXGroup; + children = ( + ); + path = View; + sourceTree = ""; + }; + 9CB3D0892C37BA650062869D /* Model */ = { + isa = PBXGroup; + children = ( + 9CB3D08E2C37D0D60062869D /* KaraokeListingDM.swift */, + 9C21F81B2C37E1FA0050BFCC /* KaraokeContinueWatchingDM.swift */, + ); + path = Model; + sourceTree = ""; + }; 9CBCB2A62BE5104F007D7934 /* Home */ = { isa = PBXGroup; children = ( @@ -1557,6 +1621,7 @@ 9C834ED62C1C1F9200B29A9C /* Exo2-ExtraBold.ttf in Resources */, 9C834ED72C1C1F9200B29A9C /* Exo2-Regular.ttf in Resources */, 9C834ED82C1C1F9200B29A9C /* Exo2-Thin.ttf in Resources */, + 9CB3D0852C37BA530062869D /* Karaoke.storyboard in Resources */, 52C6E0262BE3B46A00E22D59 /* SelectAvatarCell.xib in Resources */, 52C8B0712BDA7512003B51D0 /* PassingCloud.json in Resources */, 9C8C4FB02C1328060017DD3B /* Disclaimer.rtf in Resources */, @@ -1693,6 +1758,7 @@ 52D2F3D82C24043D009E52FF /* ShimmerEffectView.swift in Sources */, 9C27E16F2BDB866500EC1DA9 /* CellIdentifier.swift in Sources */, 52BC3BF22C170264002FACA6 /* MoreVM.swift in Sources */, + 9CB3D08F2C37D0D60062869D /* KaraokeListingDM.swift in Sources */, 9CBE1B412C0F37B300CA6E61 /* DPDUIView+Extension.swift in Sources */, 9C27E1632BDB6F1900EC1DA9 /* AuthFunc.swift in Sources */, 9C0A85412BEE35670093783D /* ResetPassUserNameVM.swift in Sources */, @@ -1704,6 +1770,7 @@ 52B8D4D92C04A25E00ED65F3 /* UIViewController+Container.swift in Sources */, 9C834EDC2C1C26CD00B29A9C /* HtmlText.swift in Sources */, 527AC6F72C171C8F00434FB7 /* BlogsCell.swift in Sources */, + 9C21F81C2C37E1FA0050BFCC /* KaraokeContinueWatchingDM.swift in Sources */, 523ED25E2BDA2BC700CFED02 /* AppDelegate.swift in Sources */, 9C7939132C0EFCAE00F5D6E6 /* FaqVM.swift in Sources */, 52D774ED2BDFC13F001D87DE /* OTPVM.swift in Sources */, @@ -1766,6 +1833,7 @@ 9CBCB2A12BE4E50A007D7934 /* TextFieldPassword.swift in Sources */, 52BC3BEC2C16DF9F002FACA6 /* MyOrdersVC.swift in Sources */, 9C56E8482BDBEFAB00E4CA14 /* AssetColor.swift in Sources */, + 9C21F8222C382A580050BFCC /* AVPlayerVM.swift in Sources */, 52BFB5372C33E0C500BAAE15 /* AudioBookHomeVM.swift in Sources */, 9C0A85432BEE3EC90093783D /* NewPasswordVM.swift in Sources */, 526A43752C36AA4A00AE148F /* GamesListVC.swift in Sources */, @@ -1773,17 +1841,20 @@ 524C42332C049D590016A11C /* CustomizableSegmentControl.swift in Sources */, 9C535DB52C005A6D00DA6DCD /* KeyWindowFix.swift in Sources */, 9C9BEEC72BEE1BBF004ECC2F /* CollectionViewCenteredFlowLayout.swift in Sources */, + 9CB3D08D2C37CDD60062869D /* KaraokeListingVM.swift in Sources */, 5222426A2BFC7AFC0085C632 /* SideMenuVC.swift in Sources */, 527AC7012C182DCE00434FB7 /* TimeStringToSeconds.swift in Sources */, 9CBCB29D2BE4D6BB007D7934 /* LoginVM.swift in Sources */, 524C42312C0499560016A11C /* NotificationCenterReloads.swift in Sources */, 9C8C4FAE2C1315410017DD3B /* WebViewVC.swift in Sources */, 52BC3BE22C0E02EE002FACA6 /* FaqVC.swift in Sources */, + 9C21F81E2C37E3CA0050BFCC /* AVPlayerVC.swift in Sources */, 52A981D02C1AFEE8000E0BEC /* MyListVM.swift in Sources */, 5272FCE52BDFDC8C000ECB1D /* UserDetailsRegisterVM.swift in Sources */, 528E5F222C24660F00E33E4E /* SeasonCategoryCell.swift in Sources */, 525954272BE9178F00191286 /* UserDataDM.swift in Sources */, 9C27E1652BDB6FBC00EC1DA9 /* StoryBoardID.swift in Sources */, + 9CB3D08B2C37BBA50062869D /* KaraokeListingVC.swift in Sources */, 52FDBA782BFF23F4009D7AC7 /* TimePeriod.swift in Sources */, 527AC6FA2C17387300434FB7 /* SongBlogDM.swift in Sources */, 522A931C2C0DE9150098FE49 /* AboutUsVc.swift in Sources */, @@ -1801,6 +1872,7 @@ 52AC2D252C295A7900337473 /* TeaserDM.swift in Sources */, 9C535DC22C00B36900DA6DCD /* ThemeTwoVC.swift in Sources */, 9CA7C6C22C1095B600D73742 /* ProfileVM.swift in Sources */, + 9CB3D0912C37D6930062869D /* KaraokeDetailsVC.swift in Sources */, 52E214C72C2AD47F00BC2D29 /* EpisodeDetailsVC.swift in Sources */, 52D774F12BDFC53B001D87DE /* StringSubScript.swift in Sources */, 9CBE1B3F2C0F37B300CA6E61 /* DPDConstants.swift in Sources */, diff --git a/WOKA/Assets/Assets.xcassets/Karaoke/Contents.json b/WOKA/Assets/Assets.xcassets/Karaoke/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/WOKA/Assets/Assets.xcassets/Karaoke/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/WOKA/Assets/Assets.xcassets/Karaoke/Microphone.imageset/Contents.json b/WOKA/Assets/Assets.xcassets/Karaoke/Microphone.imageset/Contents.json new file mode 100644 index 0000000..4e91752 --- /dev/null +++ b/WOKA/Assets/Assets.xcassets/Karaoke/Microphone.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "Microphone.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Microphone@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Microphone@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/WOKA/Assets/Assets.xcassets/Karaoke/Microphone.imageset/Microphone.png b/WOKA/Assets/Assets.xcassets/Karaoke/Microphone.imageset/Microphone.png new file mode 100644 index 0000000000000000000000000000000000000000..804d2fb7e0db10f04890103477317079384837de GIT binary patch literal 1826 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 M07*qoM6N<$f?T&Y5&!@I literal 0 HcmV?d00001 diff --git a/WOKA/Assets/Assets.xcassets/Karaoke/Microphone.imageset/Microphone@3x.png b/WOKA/Assets/Assets.xcassets/Karaoke/Microphone.imageset/Microphone@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..e3bdad8e420a8d270fa119f90f66166b241c2d59 GIT binary patch literal 1985 zcmV;y2R`_TP)Px+dr3q=RCr$PosG2?H4uhpY(TLAg$5KFP-sA~0fhqmp#T*N5UvFXG@#IcU;`oz z2pxbGjQd`bOU#$-m+Vd^*~{jfdpN*uHhK2l$s{w$Wg5JQ$cIGq84-Q#e%>P@{F^T? ziOByvC89r=8Gj$P@Q5uF5rF-Ih^`aSrwiKnjEGK%=rJ?DUT}ZYTZV$}V1G?S-w+YN zuPspg17^Onwj#~@hk-64Q1t!CbZGVU1rc2v#q10LT|}Vnds>7u^#~E&8A0{kp^L~} zXHFV3Kdb&OGvBs)Sn4@lp?3i88FU5T4Z4VYKN0w$lj6FXnl8{q1g_w3oq+qt0z3v+ z`1Yp79J-tAJZa>m)WU;TbH&=1?*YB1SxLPVcr>PF&J?;+In*^$c|}B*EY)re9Wzb1 zh@%x#wOd1n%EQH~QQ*H~=J%}{V+LJBuu6!9s1b{)Cu0eHRMP?x0QzlaZoL$7DmY8% z@XO(!k6P|C^DT?USwe?tfr%NlJY(i77LBunKI$OqIlo}$OXm$b?B>WtnE4%x23jh8 z>8#JkNJ}C~2+cj5mWmgJ=&WX@X3*CtNJPGLQKh+R@Fm@3WmNrW65%?e>KljfgVg=(CN!5 zn>r;IZPI%Y5it7Og&9@W+_j*GKmq;0u5K9mRU-P`DOtsrZvp*kDr;(o{>A`VLdRgZ zq`d2FdPx?6x=k06?J9iHY>O$$ zB!J6@Y%R4l^-V+H2hu(R=~n&p?GB{7(s!k&9Gv9DXSeB^zTjb9n}&X!nI9+o-O)3= zlIhYTD?J2?+>?XVIv1EOnN_ycbH4UuE~ALtB%)v3Z7QjETFU@oa%gf_gNTftwflsb zuO+@vWTs)C6iV`%T9s%)55s9V00HXwUzt{R!^YRP)8hIAvAAX3UxSI+BWAv_wlP}J z!-W5rQ)=7A1oV>ilePU>dVg{!hJ*g6OYv6QIG_bR26`bA$iPmvn#7@{5Nq#C+G-Jj zco4uqQQIP;1sxzUn0lb!rnZty>nI4N;lzv4N-`o84WcRm40K!t`l$>=u=MIrA$rQp zm_EmLeMA$JOgwd_1ra0PCl!0H4L#n-l`}Eu$iWNgDE*wuW7DFRhOMde*u>;qNBHU( zoGx?(?H@g-@}GipXjFGqt3h`rCbZeeoV}PCP)FI`m=gw6jxW+r=2Wr({F~N>jz)$l z(b?_aA_D(+wa>faYsrF)<`n9i4OF2!wIj;ogV0brQr!-6(_KUeYP!4v+|pYygGM&k zK^}YLCZc{-m8%Y;6y8TW#4EfjAF9&JMa`yiy3@L1GU-UPaX8Bh7K z1w48Bg;P8hlq^imY*ue#siMj080zLFP&_=8P{H_|vuPBr!{2Gn9Rk|}@8ie0z5gPD zwxZ3xsH`Za>|aahv1^#M?~!T3iXM)9)oL4FG;-Fn83N9Zhu#Wa62>C6tb!1}R>zV9 zTH=5-bOMT>-Sp*-DZz39;4d+Qc)>Uj?c~_OXbIp=l9tS%XY4z`V<0e0G!ZZhIBNT0t?FxuXVi^B6E1Cb7e?)Kj$Pk$AWc2onFn|Zadhbn{;3)&&CXm$ z-PRin%<&;V_`)#0m~IX;hwc;)I||njAmTRo0rBT4HhBtT$qR7jv10(v9e|I;Ihd5A z1MV^9*8YDN=#gKJ*(f}eR9o-@03II6bNud$%sLJRR;U=8!tf_Dd~;zzcsPJ$3*IeUBMg7i5&ZUU%8nJVrb8O)%hus+GA2ZL z0X2(ZfQv0K&qo4nJ~>+Rb_%zspM5M_INfMirAH>Gbn?_>{dJLPh`P%_?W97+58Ol*3hkgm2oxU#0_fuMRSd52E8))paDy>4%IzIal=|dA7x+B zl9vIs-$", with: "").htmlToAttributedString{ + let sizeText = NSMutableAttributedString(attributedString: desc) + sizeText.setFontFace(font: FontCustom.shareInstance.customFont(fontName: .Exo2_Regular, size: 15),color: UIColor.appColor(.TextDarkBlue)!) + self.watchingDesc.attributedText = sizeText + } + } + }else{ + if let hindiData = karaokeData.contentMoreDetails?.filter({$0.languageMasterID == 2}).first{ + watchingTitle.text = hindiData.title + if let desc = hindiData.description?.replacingOccurrences(of: "
", with: "").htmlToAttributedString{ + let sizeText = NSMutableAttributedString(attributedString: desc) + sizeText.setFontFace(font: FontCustom.shareInstance.customFont(fontName: .Exo2_Regular, size: 15),color: UIColor.appColor(.TextDarkBlue)!) + self.watchingDesc.attributedText = sizeText + } + } + } + } + } + + func tapHandler(){ + + self.view.addTapGesture { + self.dismiss(animated: true) + } + + addView.addTapGesture { [weak self] in + guard let self else{return} + + if let karaokeData{ + guard let showID = karaokeData.id, let isFav = karaokeData.markAsFavourite, let postType = karaokeData.contentMoreDetails?.first?.postType else{return} + + if isFav { + LikeFavCommonFunc.shareInstance.removeFavourite(postID: showID, postType: postType, categoryID: 0, vc: self) { isDone in + self.karaokeData?.markAsFavourite = false + K.GVar.reloadMyList = true + self.delegate?.updateRows(id: showID, type: .favourite, isFav: false, isLike: nil) + self.initView() + } + }else{ + LikeFavCommonFunc.shareInstance.addFavourite(postID: showID, postType: postType, categoryID: 0, vc: self) { isDone in + self.karaokeData?.markAsFavourite = true + K.GVar.reloadMyList = true + self.delegate?.updateRows(id: showID, type: .favourite, isFav: true, isLike: nil) + self.initView() + } + } + } + } + + likeView.addTapGesture { [weak self] in + guard let self else{return} + + if let karaokeData{ + guard let showID = karaokeData.id, let isLiked = karaokeData.isLiked, let postType = karaokeData.contentMoreDetails?.first?.postType else{return} + + if isLiked{ + LikeFavCommonFunc.shareInstance.unlikePost(postID: showID, postType: postType, vc: self) { isDone in + self.karaokeData?.isLiked = false + K.GVar.reloadMyList = true + self.delegate?.updateRows(id: showID, type: .liked, isFav: nil, isLike: false) + self.initView() + } + }else{ + LikeFavCommonFunc.shareInstance.likePost(postID: showID, postType: postType, vc: self) { isDone in + self.karaokeData?.isLiked = true + K.GVar.reloadMyList = true + self.delegate?.updateRows(id: showID, type: .liked, isFav: nil, isLike: true) + self.initView() + } + } + } + } + + shareView.addTapGesture { + print("share") + } + } + + @IBAction func playNowBtnTapped(_ sender: LocalisedElementsButton) { + let sb = UIStoryboard(name: K.StoryBoard.Karaoke, bundle: nil) + let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Karaoke.aVPlayerVC) as! AVPlayerVC + if AuthFunc.shareInstance.getDefaultLanguage() == .english{ + if let englishData = karaokeData?.contentMoreDetails?.filter({$0.languageMasterID == 1}).first{ + vcPush.titleVideo = englishData.title + vcPush.videoURL = englishData.url + } + }else{ + if let hindiData = karaokeData?.contentMoreDetails?.filter({$0.languageMasterID == 2}).first{ + vcPush.titleVideo = hindiData.title + vcPush.videoURL = hindiData.url + } + } + self.present(vcPush, animated: true) + } + + @IBAction func closeBtnTapped(_ sender: UIButton) { + self.dismiss(animated: true) { + + } + } +} diff --git a/WOKA/Karaoke/Controller/KaraokeListingVC.swift b/WOKA/Karaoke/Controller/KaraokeListingVC.swift new file mode 100644 index 0000000..79e8b4a --- /dev/null +++ b/WOKA/Karaoke/Controller/KaraokeListingVC.swift @@ -0,0 +1,233 @@ +// +// KaraokeListingVC.swift +// WOKA +// +// Created by Bilal on 05/07/2024. +// + +import UIKit + +class KaraokeListingVC: UIViewController { + + @IBOutlet weak var headerView: ShimmerEffectView! + @IBOutlet weak var selectedShowView: ShimmerEffectView! + @IBOutlet weak var headerHeight: NSLayoutConstraint! + @IBOutlet weak var headerImage: UIImageView! + @IBOutlet weak var headerTitleLabel: UILabel! + + @IBOutlet weak var scrollView: UIScrollView! + + @IBOutlet weak var continueWatchingCV: UICollectionView! + @IBOutlet weak var continueWatchingStack: UIStackView! + + @IBOutlet weak var karaokeListingTableView: UITableView! + @IBOutlet weak var tableHeight: NSLayoutConstraint! + + var vm = KaraokeListingVM() + + override func viewDidLoad() { + super.viewDidLoad() + scrollView.delegate = self + vm.vc = self + vm.initView() + navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default) + navigationController?.navigationBar.shadowImage = UIImage() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.setNavigationBarHidden(false, animated: animated) + self.navigationController?.setColor(color: .white) + } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + self.navigationController?.setNavigationBarHidden(true, animated: animated) + } + + override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + + // Customize the navigation bar's appearance + self.navigationController?.setColor(color: .black) + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + vm.updateTableHeight() + } +} + +// MARK: - CollectionView Delegate and Data Source + +extension KaraokeListingVC : CollectionViewSRC{ + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return vm.continueWatchingData.count + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: K.CellIdentifier.AudioBooks.continueAudioCell, for: indexPath) as! ContinueAudioCell + let data = vm.continueWatchingData[indexPath.row] + cell.setKaraokeData(data: data) + + cell.btnTapped = { [self] (type) -> Void in + vm.updateFavLikes(type: type,id: vm.continueWatchingData[indexPath.row].id ?? 0) + } + return cell + } + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + + let data = vm.continueWatchingData[indexPath.row] + + /* + Updated the top header data + */ + vm.indexToLoad = vm.karaokeListData.firstIndex(where: {$0.id == data.id}) ?? 0 + vm.setHeaderData() + + let sb = UIStoryboard(name: K.StoryBoard.Karaoke, bundle: nil) + let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Karaoke.karaokeDetailsVC) as! KaraokeDetailsVC + vcPush.modalPresentationStyle = .overCurrentContext + vcPush.modalTransitionStyle = .crossDissolve + vcPush.karaokeData = data + vcPush.delegate = self + self.present(vcPush, animated: true) + + } + +} + +// MARK: - Collection Flow Layout + +extension KaraokeListingVC : UICollectionViewDelegateFlowLayout{ + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { + return 5 + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { + let inset: CGFloat = 10 + return UIEdgeInsets(top: 0, left: inset, bottom: 0, right: inset) + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { + return 0 // Space between cells + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + let widthPerItem = collectionView.frame.width - 30 // Adjust to your desired width + return CGSize(width: widthPerItem, height: 230) + } +} + +// MARK: - TableView DataSource , Delegates + +extension KaraokeListingVC : TableViewSRC{ + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return vm.karaokeListData.count == 0 ? 2 : vm.karaokeListData.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: K.CellIdentifier.WebSeries.webSeriesShowListingCell) as! WebSeriesShowListingCell + + if vm.karaokeListData.count == 0{ + cell.showShimmer() + }else{ + let data = vm.karaokeListData[indexPath.row] + cell.setKaraokeData(data: data) + cell.stopShimmer() + } + + cell.btnTapped = { [weak self] (type) -> Void in + guard let self , let id = vm.karaokeListData[indexPath.row].id else{return} + vm.updateFavLikes(type: type, id: id) + } + return cell + } + + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + /* + Updated the top header data + */ + vm.indexToLoad = indexPath.row + vm.setHeaderData() + + let data = vm.karaokeListData[indexPath.row] + + let sb = UIStoryboard(name: K.StoryBoard.Karaoke, bundle: nil) + let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Karaoke.karaokeDetailsVC) as! KaraokeDetailsVC + vcPush.modalPresentationStyle = .overCurrentContext + vcPush.modalTransitionStyle = .crossDissolve + vcPush.karaokeData = data + vcPush.delegate = self + self.present(vcPush, animated: true) + } +} + +extension KaraokeListingVC : ReloadAudioBooksFavLike{ + func updateRows(id: Int, type: FavCellCLick, isFav: Bool?, isLike: Bool?) { + if let isFav{ + if let continueDataIndex = vm.continueWatchingData.firstIndex(where:{$0.id == id}) { + vm.continueWatchingData[continueDataIndex].markAsFavourite = isFav + continueWatchingCV.reloadItems(at: [IndexPath(row: continueDataIndex, section: 0)]) + } + + if let audioListDataIndex = vm.karaokeListData.firstIndex(where:{$0.id == id}) { + vm.karaokeListData[audioListDataIndex].markAsFavourite = isFav + karaokeListingTableView.reloadRows(at: [IndexPath(row: audioListDataIndex, section: 0)],with: .none) + K.GVar.reloadMyList = true + } + } + + if let isLike{ + if let continueDataIndex = vm.continueWatchingData.firstIndex(where:{$0.id == id}) { + vm.continueWatchingData[continueDataIndex].isLiked = isLike + continueWatchingCV.reloadItems(at: [IndexPath(row: continueDataIndex, section: 0)]) + } + + if let audioListDataIndex = vm.karaokeListData.firstIndex(where:{$0.id == id}) { + vm.karaokeListData[audioListDataIndex].isLiked = isLike + karaokeListingTableView.reloadRows(at: [IndexPath(row: audioListDataIndex, section: 0)],with: .none) + K.GVar.reloadMyList = true + } + } + } + + +} +// MARK: - Animating scrollView + +extension KaraokeListingVC: UIScrollViewDelegate { + + func scrollViewDidScroll(_ scrollView: UIScrollView) { + + // Get the current vertical offset of the scroll view + let y = scrollView.contentOffset.y + + // Define the height range for the header view + let minHeaderHeight: CGFloat = 0.0 // Height at which the header becomes invisible + let maxHeaderHeight: CGFloat = 200.0 // Maximum height when fully visible + + // Calculate the new height for the header view based on the scroll position + let newHeaderHeight: CGFloat + if y < 0 { + // When scrolling up beyond the top, ensure the header view is fully expanded + newHeaderHeight = maxHeaderHeight + } else { + // Calculate the new height for the header view, ensuring it doesn't go below the minimum height + newHeaderHeight = max(minHeaderHeight, maxHeaderHeight - y) + } + + // Update the header view's height constraint with the new height + headerHeight.constant = newHeaderHeight + + // Animate the layout changes to smoothly transition the header height + UIView.animate(withDuration: 0.3) { + self.view.layoutIfNeeded() + } + } +} diff --git a/WOKA/Karaoke/Karaoke.storyboard b/WOKA/Karaoke/Karaoke.storyboard new file mode 100644 index 0000000..cc96791 --- /dev/null +++ b/WOKA/Karaoke/Karaoke.storyboard @@ -0,0 +1,838 @@ + + + + + + + + + + + + + + Exo2-Bold + + + Exo2-Medium + + + Exo2-Regular + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WOKA/Karaoke/Model/KaraokeContinueWatchingDM.swift b/WOKA/Karaoke/Model/KaraokeContinueWatchingDM.swift new file mode 100644 index 0000000..fb63b5c --- /dev/null +++ b/WOKA/Karaoke/Model/KaraokeContinueWatchingDM.swift @@ -0,0 +1,19 @@ +// +// KaraokeContinueWatchingDM.swift +// WOKA +// +// Created by Bilal on 05/07/2024. +// + +import Foundation + +// MARK: - KaraokeListingDM +struct KaraokeContinueWatchingDM: Codable { + let result: [KaraokeListingDM.KaraokeDatum]? + let totalRecords: Int? + + enum CodingKeys: String, CodingKey { + case result + case totalRecords = "total_records" + } +} diff --git a/WOKA/Karaoke/Model/KaraokeListingDM.swift b/WOKA/Karaoke/Model/KaraokeListingDM.swift new file mode 100644 index 0000000..efeb4fd --- /dev/null +++ b/WOKA/Karaoke/Model/KaraokeListingDM.swift @@ -0,0 +1,73 @@ +// +// KaraokeListingDM.swift +// WOKA +// +// Created by Bilal on 05/07/2024. +// + +import Foundation + +// MARK: - KaraokeListingDM +struct KaraokeListingDM: Codable { + let karaokeData: [KaraokeDatum]? + let totalRecords: Int? + + enum CodingKeys: String, CodingKey { + case karaokeData = "karaoke_data" + case totalRecords = "total_records" + } + + // MARK: - KaraokeDatum + struct KaraokeDatum: Codable { + let id: Int? + let title, description: String? + let videoURL: String? + let thumbnailPath: String? + let releaseDate: String? + let duration, categoryMasterID, ageRangeMasterID, genderMasterID: String? + let languageMasterID: Int? + let contentMoreDetails: [ContentMoreDetail]? +// let categoryData, ageRangeData, genderData: [JSONAny]? + var markAsFavourite, isLiked: Bool? + var viewsCount, likesCount, bookmarkCount: Int? + + enum CodingKeys: String, CodingKey { + case id, title, description + case videoURL = "video_url" + case thumbnailPath = "thumbnail_path" + case releaseDate = "release_date" + case duration + case categoryMasterID = "category_master_id" + case ageRangeMasterID = "age_range_master_id" + case genderMasterID = "gender_master_id" + case languageMasterID = "language_master_id" + case contentMoreDetails = "content_more_details" +// case categoryData = "category_data" +// case ageRangeData = "age_range_data" +// case genderData = "gender_data" + case markAsFavourite = "mark_as_favourite" + case isLiked = "is_liked" + case viewsCount = "views_count" + case likesCount = "likes_count" + case bookmarkCount = "bookmark_count" + } + } + + // MARK: - ContentMoreDetail + struct ContentMoreDetail: Codable { + let id, contentID, postType, languageMasterID: Int? + let title, description: String? + let url: String? + let tagsKeywords: String? + + enum CodingKeys: String, CodingKey { + case id + case contentID = "content_id" + case postType = "post_type" + case languageMasterID = "language_master_id" + case title, description, url + case tagsKeywords = "tags_keywords" + } + } +} + diff --git a/WOKA/Karaoke/ViewModel/AVPlayerVM.swift b/WOKA/Karaoke/ViewModel/AVPlayerVM.swift new file mode 100644 index 0000000..314c959 --- /dev/null +++ b/WOKA/Karaoke/ViewModel/AVPlayerVM.swift @@ -0,0 +1,17 @@ +// +// AVPlayerVM.swift +// WOKA +// +// Created by Bilal on 05/07/2024. +// + +import Foundation + +class AVPlayerVM{ + + weak var vc : AVPlayerVC! + + func initView(){ + + } +} diff --git a/WOKA/Karaoke/ViewModel/KaraokeListingVM.swift b/WOKA/Karaoke/ViewModel/KaraokeListingVM.swift new file mode 100644 index 0000000..7112d5c --- /dev/null +++ b/WOKA/Karaoke/ViewModel/KaraokeListingVM.swift @@ -0,0 +1,241 @@ +// +// KaraokeListingVM.swift +// WOKA +// +// Created by Bilal on 05/07/2024. +// + +import UIKit +import Alamofire + +class KaraokeListingVM{ + + weak var vc : KaraokeListingVC! + var karaokeListData = [KaraokeListingDM.KaraokeDatum]() + var continueWatchingData = [KaraokeListingDM.KaraokeDatum]() + var indexToLoad = 0 + + func initView(){ + setupCell() + let color1 = #colorLiteral(red: 0.8, green: 0.6078431373, blue: 0.1098039216, alpha: 1) + let color2 = #colorLiteral(red: 0.8, green: 0.2901960784, blue: 0.1098039216, alpha: 1) + vc.title = "KARAOKE".localized(loc: AuthFunc.shareInstance.languageSelected.rawValue) + vc.view.applyGradient(colors: [color2, color1], startPoint: CGPoint(x: 0, y: 0), endPoint: CGPoint(x: 0.8, y: 0)) + startShimmer() + getContinueWatching() + getKaraokeListing() + } + + func setupCell(){ + vc.continueWatchingCV.register(UINib(nibName: K.CellIdentifier.AudioBooks.continueAudioCell, bundle: nil), forCellWithReuseIdentifier: K.CellIdentifier.AudioBooks.continueAudioCell) + vc.continueWatchingCV.delegate = vc.self + vc.continueWatchingCV.dataSource = vc.self + + vc.karaokeListingTableView.register(UINib(nibName: K.CellIdentifier.WebSeries.webSeriesShowListingCell, bundle: nil), forCellReuseIdentifier: K.CellIdentifier.WebSeries.webSeriesShowListingCell) + vc.karaokeListingTableView.delegate = vc.self + vc.karaokeListingTableView.dataSource = vc.self + } + + func updateTableHeight(){ + self.vc.tableHeight.constant = self.vc.karaokeListingTableView.contentSize.height + 100 + self.vc.karaokeListingTableView.layoutIfNeeded() + self.vc.tableHeight.constant = self.vc.karaokeListingTableView.contentSize.height + } + + func setHeaderData(){ + let data = karaokeListData[indexToLoad] + + if let url = data.thumbnailPath{ + self.vc.headerImage.imageURL(url, color: .white) + } + + if AuthFunc.shareInstance.getDefaultLanguage() == .english{ + let englishData = data.contentMoreDetails?.filter({$0.languageMasterID == 1}).first + vc.headerTitleLabel.text = englishData?.title + }else{ + let hindiData = data.contentMoreDetails?.filter({$0.languageMasterID == 2}).first + vc.headerTitleLabel.text = hindiData?.title + } + } + + // MARK: - GetKaraoke Listing + + func getContinueWatching(){ + // Utilities.startProgressHUD() + let headers : HTTPHeaders = ["access-token" : AuthFunc.shareInstance.getAccessToken()] + let params : Parameters = ["post_type" : 8] // 8 - Karaoke + NetworkManager.shareInstance.apiRequest(url: APIEndPoints.WebSeries.continue_watching, method: .post,parameters: params,headers : headers) { [weak self](result : Result, NetworkManager.APIError>) in + switch result{ + case .success(let data): + guard let self else{ + Utilities.dismissProgressHUD() + return + } + switch data.success{ + case 0: + /* + Error + */ + Utilities.dismissProgressHUD() + // vc.toast(msg: data.message ?? "Unrecognised error" , time: 2) + self.vc.continueWatchingStack.isHidden = true + case 1: + Utilities.dismissProgressHUD() + guard let data = data.data?.result else{return} + if data.count == 0{ + self.vc.continueWatchingStack.isHidden = true + }else{ + self.vc.continueWatchingStack.isHidden = false + } + self.continueWatchingData = data.reversed() + self.vc.continueWatchingCV.reloadData() + default: + break + } + case .failure(let error): + guard let self else{ + Utilities.dismissProgressHUD() + return + } + Utilities.dismissProgressHUD() + self.vc.continueWatchingStack.isHidden = true + vc.toast(msg: error.localizedDescription , time: 2) + } + } + } + + func getKaraokeListing(){ +// Utilities.startProgressHUD() + let headers : HTTPHeaders = ["access-token" : AuthFunc.shareInstance.getAccessToken()] + NetworkManager.shareInstance.apiRequest(url: APIEndPoints.Karaoke.sing_karaoke_listing, method: .post,headers: headers) { [weak self](result : Result, NetworkManager.APIError>) in + switch result{ + case .success(let data): + guard let self else{ + Utilities.dismissProgressHUD() + return + } + switch data.success{ + case 0: + /* + Error + */ + Utilities.dismissProgressHUD() + vc.toast(msg: data.message ?? "Unrecognised error" , time: 2) + case 1: + Utilities.dismissProgressHUD() + guard let data = data.data?.karaokeData else{return} + self.karaokeListData.removeAll() + self.karaokeListData = data + self.vc.karaokeListingTableView.reloadData() + self.vc.tableHeight.constant = self.vc.karaokeListingTableView.contentSize.height + 100 + self.vc.karaokeListingTableView.layoutIfNeeded() + self.vc.tableHeight.constant = self.vc.karaokeListingTableView.contentSize.height + setHeaderData() + self.stopShimmer() + default: + break + } + case .failure(let error): + guard let self else{ + Utilities.dismissProgressHUD() + return + } + Utilities.dismissProgressHUD() + vc.toast(msg: error.localizedDescription , time: 2) + } + } + } + + func startShimmer(){ + vc.headerView.startShimmer() + vc.selectedShowView.startShimmer() + } + + func stopShimmer(){ + self.vc.headerView.stopShimmer() + self.vc.selectedShowView.stopShimmer() + } + + // MARK: - Update Fav Likes + + func updateFavLikes(type : FavCellCLick, id : Int){ + guard let data = karaokeListData.filter({$0.id == id}).first, let audioListIndex = karaokeListData.firstIndex(where: {$0.id == id}) else{return} + switch type { + case .favourite: + guard let isFav = data.markAsFavourite ,let postID = data.id,let postType = data.contentMoreDetails?.first?.postType else{return} + if isFav == true { + LikeFavCommonFunc.shareInstance.removeFavourite(postID: postID, postType: postType, categoryID: 0, vc: self.vc) { [unowned self] isDone in + if isDone{ + karaokeListData[audioListIndex].markAsFavourite = false + vc.karaokeListingTableView.reloadRows(at: [IndexPath(row: audioListIndex, section: 0)],with: .none) + K.GVar.reloadMyList = true + + /* + Check if the data is in continue watching + */ + if let continueWatchingIndex = continueWatchingData.firstIndex(where: { $0.id == id }){ + continueWatchingData[continueWatchingIndex].markAsFavourite = false + vc.continueWatchingCV.reloadItems(at: [IndexPath(row: continueWatchingIndex, section: 0)]) + } + } + } + }else{ + LikeFavCommonFunc.shareInstance.addFavourite(postID: postID, postType: postType, categoryID: 0, vc: self.vc) { [unowned self] isDone in + if isDone{ + karaokeListData[audioListIndex].markAsFavourite = true + vc.karaokeListingTableView.reloadRows(at: [IndexPath(row: audioListIndex, section: 0)],with: .none) + K.GVar.reloadMyList = true + + /* + Check if the data is in continue watching + */ + if let continueWatchingIndex = continueWatchingData.firstIndex(where: { $0.id == id }){ + continueWatchingData[continueWatchingIndex].markAsFavourite = true + vc.continueWatchingCV.reloadItems(at: [IndexPath(row: continueWatchingIndex, section: 0)]) + } + } + } + } + return + case .liked: + guard let isLiked = data.isLiked ,let postID = data.id,let postType = data.contentMoreDetails?.first?.postType else{return} + if isLiked{ + LikeFavCommonFunc.shareInstance.unlikePost(postID: postID, postType: postType, vc: self.vc) { [unowned self] isDone in + if isDone{ + karaokeListData[audioListIndex].isLiked = false + karaokeListData[audioListIndex].likesCount! -= 1 + vc.karaokeListingTableView.reloadRows(at: [IndexPath(row: audioListIndex, section: 0)],with: .none) + K.GVar.reloadMyList = true + + /* + Check if the data is in continue watching + */ + if let continueWatchingIndex = continueWatchingData.firstIndex(where: { $0.id == id }){ + continueWatchingData[continueWatchingIndex].isLiked = false + continueWatchingData[continueWatchingIndex].likesCount! -= 1 + vc.continueWatchingCV.reloadItems(at: [IndexPath(row: continueWatchingIndex, section: 0)]) + } + } + } + }else{ + LikeFavCommonFunc.shareInstance.likePost(postID: postID, postType: postType, vc: self.vc){ [unowned self] isDone in + if isDone{ + karaokeListData[audioListIndex].isLiked = true + karaokeListData[audioListIndex].likesCount! += 1 + vc.karaokeListingTableView.reloadRows(at: [IndexPath(row: audioListIndex, section: 0)],with: .none) + K.GVar.reloadMyList = true + + /* + Check if the data is in continue watching + */ + if let continueWatchingIndex = continueWatchingData.firstIndex(where: { $0.id == id }){ + continueWatchingData[continueWatchingIndex].isLiked = true + continueWatchingData[continueWatchingIndex].likesCount! += 1 + vc.continueWatchingCV.reloadItems(at: [IndexPath(row: continueWatchingIndex, section: 0)]) + } + } + } + } + } + } +} diff --git a/WOKA/Localized Module/hi.lproj/Localizable.strings b/WOKA/Localized Module/hi.lproj/Localizable.strings index 063f227..673cc83 100644 --- a/WOKA/Localized Module/hi.lproj/Localizable.strings +++ b/WOKA/Localized Module/hi.lproj/Localizable.strings @@ -243,3 +243,9 @@ Games */ "HAVE A FUN TIME" = "आनंद करने का समय"; + +/* + Karaoke + */ +"SING ALONG & DANCE" = "साथ गायें और नाचें"; +"SING NOW" = "अभी गायें"; diff --git a/WOKA/Network Adapter/APIEndPoints.swift b/WOKA/Network Adapter/APIEndPoints.swift index 4140375..154f2db 100644 --- a/WOKA/Network Adapter/APIEndPoints.swift +++ b/WOKA/Network Adapter/APIEndPoints.swift @@ -99,6 +99,10 @@ struct APIEndPoints { static let get_token_to_auth_player = makeURL(path: "get_token_to_auth_player") } + struct Karaoke{ + static let sing_karaoke_listing = makeURL(path: "sing_karaoke_listing") + } + // Other endpoint categories... struct Links { static let privacyPolicy = "https://www.wokaland.com/privacy-policy/" diff --git a/WOKA/Theme/Base.lproj/Theme.storyboard b/WOKA/Theme/Base.lproj/Theme.storyboard index d48130d..b48c3e7 100644 --- a/WOKA/Theme/Base.lproj/Theme.storyboard +++ b/WOKA/Theme/Base.lproj/Theme.storyboard @@ -314,28 +314,8 @@ - - - - - - - - - - - - - + @@ -364,23 +344,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + - + + - - - + + - @@ -458,6 +470,7 @@ + diff --git a/WOKA/Theme/Controller/PlayerVC.swift b/WOKA/Theme/Controller/PlayerVC.swift index 0d236a8..ac9d35e 100644 --- a/WOKA/Theme/Controller/PlayerVC.swift +++ b/WOKA/Theme/Controller/PlayerVC.swift @@ -41,7 +41,7 @@ class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate { let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: UIInterfaceOrientationMask.portrait)) } else { - UIDevice.current.setValue(UIInterfaceOrientationMask.landscapeRight.rawValue, forKey: "orientation") + UIDevice.current.setValue(UIInterfaceOrientationMask.portrait.rawValue, forKey: "orientation") } // UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation") UIView.setAnimationsEnabled(true) diff --git a/WOKA/Theme/Controller/ThemeOneVC.swift b/WOKA/Theme/Controller/ThemeOneVC.swift index 8d7cebf..4a6be72 100644 --- a/WOKA/Theme/Controller/ThemeOneVC.swift +++ b/WOKA/Theme/Controller/ThemeOneVC.swift @@ -29,6 +29,7 @@ class ThemeOneVC: UIViewController { @IBOutlet weak var moreStack: UIStackView! @IBOutlet weak var bottomArrow: UIImageView! @IBOutlet weak var gamesView: UIView! + @IBOutlet weak var karaokeView: UIView! var timer: Timer? diff --git a/WOKA/Theme/ViewModel/ThemeOneVM.swift b/WOKA/Theme/ViewModel/ThemeOneVM.swift index a06bad3..39b166f 100644 --- a/WOKA/Theme/ViewModel/ThemeOneVM.swift +++ b/WOKA/Theme/ViewModel/ThemeOneVM.swift @@ -144,6 +144,15 @@ class ThemeOneVM{ vc.navigationController?.pushViewController(vcPush, animated: true) } } + + vc.karaokeView.addTapGesture { [self] in + ViewButtonAnimation.sharedInstance.btnTapped(in: self.vc, view: self.vc.karaokeView) { [weak self] in + guard let self else{return} + let sb = UIStoryboard(name: K.StoryBoard.Karaoke, bundle: nil) + let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Karaoke.karaokeListingVC) as! KaraokeListingVC + vc.navigationController?.pushViewController(vcPush, animated: true) + } + } } // MARK: - Animate Clouds and LiveTV diff --git a/WOKA/WebSeries/View/WebSeriesShowListingCell.swift b/WOKA/WebSeries/View/WebSeriesShowListingCell.swift index f1ae44c..0a4011e 100644 --- a/WOKA/WebSeries/View/WebSeriesShowListingCell.swift +++ b/WOKA/WebSeries/View/WebSeriesShowListingCell.swift @@ -135,6 +135,37 @@ class WebSeriesShowListingCell: UITableViewCell { } } + func setKaraokeData(data: KaraokeListingDM.KaraokeDatum){ + //heart.fill , heart , hand.thumbsup.fill , hand.thumbsup + if AuthFunc.shareInstance.getDefaultLanguage() == .english{ + showTitle.text = data.contentMoreDetails?.filter({$0.languageMasterID == 1}).first?.title + }else{ + showTitle.text = data.contentMoreDetails?.filter({$0.languageMasterID == 2}).first?.title + } + totalLikes.text = data.likesCount?.toString() ?? "0" + + if let url = data.thumbnailPath{ + showThumbnail.imageURL(url) + } + + if let like = data.isLiked{ + switch like{ + case true: + likeBtn.setImage(UIImage(named: "LikeAdd"), for: .normal) + case false: + likeBtn.setImage(UIImage(named: "LikeRemove"), for: .normal) + } + } + + if let favourite = data.markAsFavourite{ + if favourite == true{ + favBtn.setImage(UIImage(named: "FavouriteAdd"), for: .normal) + }else{ + favBtn.setImage(UIImage(named: "FavouriteRemove"), for: .normal) + } + } + } + @IBAction func btnTapped(_ sender: UIButton) { switch sender{ case likeBtn: