- Made login ID PAss dynamic with config in the network claass singleton

- Handled session expired globally
- Added Deactiovate account api, handled the logic.
- Handled the deactivate account on login.
- Made a view to handle privacy policy and terms and condition url, also it will handle the rich text file.
- Completed terms and condition, Privacy policy, disclaimer
- Fixed the issue of live TV going to Streaming Screen. Landscape and potrait handled
This commit is contained in:
Bilal
2024-06-07 21:04:29 +05:30
parent 5fdd255130
commit d6540e9f2e
27 changed files with 525 additions and 223 deletions

View File

@@ -156,6 +156,8 @@
9C7939152C0F23AA00F5D6E6 /* NsNotificationExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C7939142C0F23AA00F5D6E6 /* NsNotificationExtension.swift */; };
9C7939172C0F23E900F5D6E6 /* LinkTypeEnum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C7939162C0F23E900F5D6E6 /* LinkTypeEnum.swift */; };
9C7939192C0F345000F5D6E6 /* ContactSupportVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C7939182C0F345000F5D6E6 /* ContactSupportVC.swift */; };
9C8C4FAE2C1315410017DD3B /* WebViewVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C8C4FAD2C1315410017DD3B /* WebViewVC.swift */; };
9C8C4FB02C1328060017DD3B /* Disclaimer.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 9C8C4FAF2C1328060017DD3B /* Disclaimer.rtf */; };
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 */; };
@@ -354,6 +356,8 @@
9C7939142C0F23AA00F5D6E6 /* NsNotificationExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NsNotificationExtension.swift; sourceTree = "<group>"; };
9C7939162C0F23E900F5D6E6 /* LinkTypeEnum.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkTypeEnum.swift; sourceTree = "<group>"; };
9C7939182C0F345000F5D6E6 /* ContactSupportVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactSupportVC.swift; sourceTree = "<group>"; };
9C8C4FAD2C1315410017DD3B /* WebViewVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewVC.swift; sourceTree = "<group>"; };
9C8C4FAF2C1328060017DD3B /* Disclaimer.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = Disclaimer.rtf; sourceTree = "<group>"; };
9C9BEEC62BEE1BBF004ECC2F /* CollectionViewCenteredFlowLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionViewCenteredFlowLayout.swift; sourceTree = "<group>"; };
9CA7C6BF2C1093E500D73742 /* ProfileVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileVC.swift; sourceTree = "<group>"; };
9CA7C6C12C1095B600D73742 /* ProfileVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileVM.swift; sourceTree = "<group>"; };
@@ -475,6 +479,7 @@
52BC3BE12C0E02EE002FACA6 /* FaqVC.swift */,
9C7939182C0F345000F5D6E6 /* ContactSupportVC.swift */,
9CA7C6BF2C1093E500D73742 /* ProfileVC.swift */,
9C8C4FAD2C1315410017DD3B /* WebViewVC.swift */,
);
path = Controller;
sourceTree = "<group>";
@@ -820,6 +825,7 @@
9C27E16E2BDB866500EC1DA9 /* CellIdentifier.swift */,
525954182BE8CC3400191286 /* ConstantString.swift */,
524C42302C0499560016A11C /* NotificationCenterReloads.swift */,
9C8C4FAF2C1328060017DD3B /* Disclaimer.rtf */,
);
path = "Constants K";
sourceTree = "<group>";
@@ -1215,6 +1221,7 @@
52C6E01C2BE383C000E22D59 /* YourIntrestCell.xib in Resources */,
52C6E0262BE3B46A00E22D59 /* SelectAvatarCell.xib in Resources */,
52C8B0712BDA7512003B51D0 /* PassingCloud.json in Resources */,
9C8C4FB02C1328060017DD3B /* Disclaimer.rtf in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1382,6 +1389,7 @@
5222426A2BFC7AFC0085C632 /* SideMenuVC.swift in Sources */,
9CBCB29D2BE4D6BB007D7934 /* LoginVM.swift in Sources */,
524C42312C0499560016A11C /* NotificationCenterReloads.swift in Sources */,
9C8C4FAE2C1315410017DD3B /* WebViewVC.swift in Sources */,
52BC3BE22C0E02EE002FACA6 /* FaqVC.swift in Sources */,
5272FCE52BDFDC8C000ECB1D /* UserDetailsRegisterVM.swift in Sources */,
525954272BE9178F00191286 /* UserDataDM.swift in Sources */,
@@ -1645,7 +1653,7 @@
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen.storyboard;
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait";
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
INFOPLIST_KEY_UIUserInterfaceStyle = Light;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
@@ -1683,7 +1691,7 @@
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen.storyboard;
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait";
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
INFOPLIST_KEY_UIUserInterfaceStyle = Light;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;

View File

@@ -142,7 +142,7 @@
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ium-M5-1Q9">
<rect key="frame" x="0.0" y="0.0" width="323" height="30"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="WOKA" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="jJ7-vb-Tw5">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="WOKA" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="jJ7-vb-Tw5" customClass="LocalisedElementsLabel" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="323" height="30"/>
<fontDescription key="fontDescription" name="Exo2-Bold" family="Exo 2" pointSize="18"/>
<color key="textColor" name="TextDarkBlue"/>
@@ -182,7 +182,7 @@
</view>
</subviews>
</stackView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2hO-Cj-GYn">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2hO-Cj-GYn" customClass="LocalisedElementsLabel" customModule="WOKA" customModuleProvider="target">
<rect key="frame" x="15" y="81" width="323" height="0.0"/>
<fontDescription key="fontDescription" name="Exo2-Regular" family="Exo 2" pointSize="16"/>
<color key="textColor" red="0.035294117649999998" green="0.0" blue="0.36470588240000001" alpha="1" colorSpace="calibratedRGB"/>

View File

@@ -14,10 +14,10 @@ enum YesNoMode{
class YesNoAlertVC: UIViewController {
@IBOutlet weak var yesBtn: UIButton!
@IBOutlet weak var noBtn: UIButton!
@IBOutlet weak var content: UILabel!
@IBOutlet weak var mainTitle: UILabel!
@IBOutlet weak var yesBtn: LocalisedElementsButton!
@IBOutlet weak var noBtn: LocalisedElementsButton!
@IBOutlet weak var content: LocalisedElementsLabel!
@IBOutlet weak var mainTitle: LocalisedElementsLabel!
// Properties
var contentLabel = String()
@@ -38,19 +38,19 @@ class YesNoAlertVC: UIViewController {
}
func updateUI(){
self.content.text = contentLabel
self.content.text = contentLabel.localized(loc: AuthFunc.shareInstance.languageSelected.rawValue)
//If the title is provided then set it
if let mainTitleText{
self.mainTitle.text = mainTitleText
self.mainTitle.text = mainTitleText.localized(loc: AuthFunc.shareInstance.languageSelected.rawValue)
}
if let yesBtnText{
self.yesBtn.setTitle(yesBtnText, for: .normal)
self.yesBtn.setTitle(yesBtnText.localized(loc: AuthFunc.shareInstance.languageSelected.rawValue), for: .normal)
}
if let noBtnText{
self.yesBtn.setTitle(noBtnText, for: .normal)
self.noBtn.setTitle(noBtnText.localized(loc: AuthFunc.shareInstance.languageSelected.rawValue), for: .normal)
}
}

View File

@@ -116,6 +116,7 @@ class UserIntrestVC: UIViewController {
let sb = UIStoryboard(name: K.StoryBoard.authenticationSB, bundle: nil)
let vc = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Authentication.selectAvatarVC) as! SelectAvatarVC
vc.vm.createChildAccount = self.vm.createChildAccount
self.navigationController?.pushViewController(vc, animated: true)
}
}

View File

@@ -24,7 +24,7 @@ struct UserDataDM: Codable {
let childDetail: ChildDetail?
let language: Language?
let alreadyLoggedIn: Bool?
let isDeactive : Bool?
enum CodingKeys: String, CodingKey {
case id, username, fullname, birthdate, email, avtar
// case gender
@@ -35,6 +35,7 @@ struct UserDataDM: Codable {
case childDetail = "child_detail"
case language
case alreadyLoggedIn = "already_logged_in"
case isDeactive = "is_deactive"
}
}

View File

@@ -80,6 +80,25 @@ class LoginVM{
case 1:
Utilities.dismissProgressHUD()
guard let dataResult = data.data?.result, let loginStatus = dataResult.alreadyLoggedIn else{return}
if let deactivated = dataResult.isDeactive , deactivated == true{
let sb = UIStoryboard(name: K.StoryBoard.customAlerts, bundle: nil)
let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.CustomAlerts.yesNoAlertVC) as! YesNoAlertVC
vcPush.mainTitleText = "Activate WOKA Account"
vcPush.contentLabel = "Would you like to reactivate your account?"
vcPush.onDoneBlock = { mode in
switch mode{
case .yes:
//If user clicked to proceed on login. Call the api.
self.proceedLogin(activate: true)
case .no:
print("no")
}
}
vcPush.modalPresentationStyle = .overCurrentContext
vcPush.modalTransitionStyle = .crossDissolve
self.vc.present(vcPush, animated: true)
return
}
if loginStatus == true{ // user is already loginned in other device
let sb = UIStoryboard(name: K.StoryBoard.customAlerts, bundle: nil)
let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.CustomAlerts.yesNoAlertVC) as! YesNoAlertVC
@@ -88,7 +107,7 @@ class LoginVM{
switch mode{
case .yes:
//If user clicked to proceed on login. Call the api.
self.proceedLogin()
self.proceedLogin(activate: false)
case .no:
print("no")
}
@@ -117,10 +136,11 @@ class LoginVM{
/*
After all checks do the api call
*/
func proceedLogin(){
func proceedLogin(activate : Bool){
let params: Parameters = [
"username": vc.userNameTF.text!,
"password": vc.passwordTF.text!
"password": vc.passwordTF.text!,
"is_activate" : activate ? "1" : "0" // if activate send 1
]
let header : HTTPHeaders = ["device-id" : AuthFunc.shareInstance.getDeviceUUID(),
"Accept-Language" : AuthFunc.shareInstance.languageSelected == .english ? "English" : "Hindi"]
@@ -174,7 +194,7 @@ class LoginVM{
Utilities.dismissProgressHUD()
guard let dataUser = data.data else{return}
self.vc.toast(msg: data.message ?? "Unrecognised error" , time: 2) {
let userDataConverted = UserDataDM.ResultData(id: nil, username: dataUser.username, fullname: dataUser.fullname, birthdate: nil, email: nil, avtar: nil, userType: "3", languageMasterID: nil, lastLogin: nil, rememberToken: nil, childDetail: nil, language: nil, alreadyLoggedIn: nil)
let userDataConverted = UserDataDM.ResultData(id: nil, username: dataUser.username, fullname: dataUser.fullname, birthdate: nil, email: nil, avtar: nil, userType: "3", languageMasterID: nil, lastLogin: nil, rememberToken: nil, childDetail: nil, language: nil, alreadyLoggedIn: nil, isDeactive: nil)
AuthFunc.shareInstance.loginDefaults(data: userDataConverted)
}
default:

View File

@@ -88,16 +88,25 @@ class SelectAvatarVM{
/*
Set UserType
*/
if AuthFunc.shareInstance.userType == .adult{
AuthFunc.shareInstance.regData.user_type = "2"
}else{
if let createChildAccount{
AuthFunc.shareInstance.regData.user_type = "1"
/*
In Add child will be 1
*/
AuthFunc.shareInstance.regData.add_child = "1"
}else{
/*
In Reg Add child will be 0
*/
AuthFunc.shareInstance.regData.add_child = "0"
if AuthFunc.shareInstance.userType == .adult{
AuthFunc.shareInstance.regData.user_type = "2"
}else{
AuthFunc.shareInstance.regData.user_type = "1"
}
}
/*
In Reg Add child will be 0
*/
AuthFunc.shareInstance.regData.add_child = "0"
/*
Set Language id
@@ -126,7 +135,7 @@ class SelectAvatarVM{
vcPush.mainTitleText = "Error".localized(loc: AuthFunc.shareInstance.languageSelected.rawValue)
vcPush.yesBtnText = "Retry?".localized(loc: AuthFunc.shareInstance.languageSelected.rawValue)
vcPush.onDoneBlock = { isDone in
self.getAvatarListing()
self.registerUser()
}
vcPush.modalPresentationStyle = .overCurrentContext
vcPush.modalTransitionStyle = .crossDissolve
@@ -135,7 +144,10 @@ class SelectAvatarVM{
case 1:
Utilities.dismissProgressHUD()
AuthFunc.shareInstance.regData = UserRegPostModel()
self.vc.toast(msg: data.message ?? "Something" , time: 2)
self.vc.toast(msg: data.message ?? "Something" , time: 2) {
guard let data = data.data?.result else{return}
AuthFunc.shareInstance.loginDefaults(data: data)
}
default:
break
}

View File

@@ -17,12 +17,15 @@ class UserIntrestVM{
var createChildAccount : Bool?
func initView(){
let loc = Locale(identifier: "hi")
self.vc.datePicker.locale = loc
if AuthFunc.shareInstance.languageSelected == .hindi{
let loc = Locale(identifier: "hi")
self.vc.datePicker.locale = loc
}
/*
Setting the minimum and maximum date as per user type
*/
if AuthFunc.shareInstance.userType == .adult{
if AuthFunc.shareInstance.userType == .adult && createChildAccount == nil{
vc.datePicker.minimumDate = Calendar.current.date(byAdding: .year, value: -150, to: Date())
vc.datePicker.maximumDate = Calendar.current.date(byAdding: .year, value: -16, to: Date())
vc.boyText.text = "MALE".localized(loc: AuthFunc.shareInstance.languageSelected.rawValue)

View File

@@ -0,0 +1,24 @@
{\rtf1\ansi\ansicpg1252\cocoartf2761
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\froman\fcharset0 Times-Bold;\f1\froman\fcharset0 Times-Roman;}
{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
{\*\expandedcolortbl;;\cssrgb\c0\c0\c0;}
\margl1440\margr1440\vieww9000\viewh8400\viewkind0
\deftab720
\pard\pardeftab720\sa240\partightenfactor0
\f0\b\fs24 \cf0 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2 THE USER AGREES AND UNDERSTANDS THAT THE PLATFORM IS PROVIDED BY US ON AN \'93AS IS\'94 AND \'93AS AVAILABLE\'94 BASIS AND WE MAKE NO REPRESENTATIONS OR WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, AS TO THE OPERATION OF THE PLATFORM OR THE INFORMATION AND CONTENT INCLUDED ON THE PLATFORM. YOU EXPRESSLY AGREE THAT YOUR USE OF THE PLATFORM IS AT YOUR SOLE RISK.\
\f1\b0 \
\f0\b TO THE FULLEST EXTENT PERMISSIBLE BY APPLICABLE LAW, WE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED. WE DO NOT WARRANT THAT THE PLATFORM, ITS SERVERS, OR EMAIL/OTHER COMMUNICATION SENT FROM THE PLATFORM ARE FREE OF VIRUSES OR OTHER HARMFUL COMPONENTS. WE WILL NOT BE LIABLE FOR ANY DAMAGES OF ANY KIND ARISING FROM THE USE OF THE PLATFORM, INCLUDING, BUT NOT LIMITED TO DIRECT, INDIRECT, INCIDENTAL, PUNITIVE, AND CONSEQUENTIAL DAMAGES.\
\f1\b0 \
\f0\b ALL INTERACTION, COMMUNICATION, DEALING, OR TRANSACTION BETWEEN THE USERS AND THE THIRD-PARTY PROVIDER IN RESPECT OF ANY PRODUCTS/SERVICES OFFERED BY THE THIRD-PARTY PROVIDER IS A SEPARATE AND INDEPENDENT TRANSACTION BETWEEN THE USER AND SUCH THIRD-PARTY PROVIDER WITHOUT ANY LIABILITY ACCRUING TO OR ON US FOR ANY MATTERS ARISING OUT OF OR IN RELATION TO THE SAME. THE USER EXPRESSLY AGREES AND ACKNOWLEDGES TO HOLD HARMLESS US IN RESPECT OF ANY COST, CLAIMS, DAMAGE, LOSS, OR EXPENSES ACCRUED, SUFFERED, INCURRED BY US OR ANY THIRD PARTY ARISING OUT OF OR IN CONNECTION WITH ANY SUCH COMMUNICATION, INTERACTION, DEALINGS, AND TRANSACTIONS BETWEEN THE USER AND THIRD-PARTY PROVIDERS. THE USER ACKNOWLEDGES THAT WE DO NOT HAVE ANY CONTROL OVER SUCH DEALINGS AND TRANSACTIONS AND PLAYS NO DETERMINATIVE ROLE IN THE PERFORMANCE IN RESPECT OF THE SAME AND WE SHALL NOT BE LIABLE FOR THE OUTCOMES OF SUCH COMMUNICATION, INTERACTION, DEALINGS, AND TRANSACTIONS BETWEEN THE USERS AND THE THIRD-PARTY PROVIDERS.\
\f1\b0 \
\f0\b WE DO NOT WARRANT, ENDORSE, GUARANTEE, OR ASSUME RESPONSIBILITY FOR ANY PRODUCT OR SERVICE ADVERTISED OR OFFERED BY A THIRD-PARTY PROVIDER IN ANY MANNER AND WE WILL NOT BE A PARTY TO OR IN ANY WAY BE RESPONSIBLE FOR ANY TRANSACTION BETWEEN YOU AND SUCH PARTY PROVIDER. AS WITH THE PURCHASE OF A PRODUCT OR SERVICE THROUGH ANY MEDIUM THROUGH SUCH THIRD-PARTY PROVIDER, YOU SHOULD USE YOUR BEST JUDGMENT AND EXERCISE CAUTION WHERE APPROPRIATE.
\f1\b0 \
}

View File

@@ -134,7 +134,7 @@ class OnBoardVM{
guard let dataUser = data.data else{return}
self.vc.toast(msg: data.message ?? "Unrecognised error" , time: 2) {
let userDataConverted = UserDataDM.ResultData(id: nil, username: dataUser.username, fullname: dataUser.fullname, birthdate: nil, email: nil, avtar: nil, userType: "3", languageMasterID: nil, lastLogin: nil, rememberToken: nil, childDetail: nil, language: nil, alreadyLoggedIn: nil)
let userDataConverted = UserDataDM.ResultData(id: nil, username: dataUser.username, fullname: dataUser.fullname, birthdate: nil, email: nil, avtar: nil, userType: "3", languageMasterID: nil, lastLogin: nil, rememberToken: nil, childDetail: nil, language: nil, alreadyLoggedIn: nil, isDeactive: nil)
AuthFunc.shareInstance.loginDefaults(data: userDataConverted)
}
default:

View File

@@ -48,6 +48,7 @@ extension K{
static let faqVC = "FaqVC"
static let contactSupportVC = "ContactSupportVC"
static let profileVC = "ProfileVC"
static let webViewVC = "WebViewVC"
}
}
}

View File

@@ -422,6 +422,9 @@
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" title="Terms &amp; Condition"/>
<connections>
<action selector="btnTapped:" destination="yYJ-KT-PYn" eventType="touchUpInside" id="Phz-fk-pyq"/>
</connections>
</button>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="aK7-70-qf3">
<rect key="frame" x="141" y="0.0" width="1" height="20"/>
@@ -436,6 +439,9 @@
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" title="Privacy Policy"/>
<connections>
<action selector="btnTapped:" destination="yYJ-KT-PYn" eventType="touchUpInside" id="qgj-PT-Nyw"/>
</connections>
</button>
</subviews>
<constraints>
@@ -463,6 +469,9 @@
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" title="Disclaimer"/>
<connections>
<action selector="btnTapped:" destination="yYJ-KT-PYn" eventType="touchUpInside" id="xCn-c0-VEh"/>
</connections>
</button>
</subviews>
</stackView>
@@ -533,13 +542,16 @@
<outlet property="addChildBtn" destination="ol4-co-NoI" id="utf-rG-dMo"/>
<outlet property="avatarImage" destination="9zy-xC-ddd" id="efq-RR-ZHd"/>
<outlet property="deactivateBtn" destination="QgY-e1-Fgb" id="ZaU-v0-APM"/>
<outlet property="disclaimerBtn" destination="DDe-vK-Hd2" id="0Xa-lw-KkC"/>
<outlet property="faqBtn" destination="6cu-a4-KbY" id="6ac-ts-oiw"/>
<outlet property="languageControl" destination="dR3-t9-4tw" id="3Jd-0j-YA7"/>
<outlet property="logoutBtn" destination="mCq-h5-pMf" id="bkx-Ld-3gQ"/>
<outlet property="myOrderBtn" destination="YDN-fb-TJo" id="0dt-xK-kKP"/>
<outlet property="privacyPolicyBtn" destination="ASm-Yq-13l" id="Yso-6e-CLb"/>
<outlet property="profileBtn" destination="cF2-pJ-F1x" id="CjM-zm-ZGI"/>
<outlet property="scrollView" destination="iqc-o5-ovk" id="w7g-8R-7Su"/>
<outlet property="selectionMenuTrailingConstraint" destination="V31-3u-cFE" id="gJh-Kh-fu0"/>
<outlet property="termsConditionBtn" destination="2fp-NZ-TkX" id="Ard-Fh-8YP"/>
<outlet property="theme1" destination="eUd-z5-WmN" id="2jG-Ie-lWp"/>
<outlet property="theme2" destination="HCH-H0-TUd" id="YU1-tv-J8j"/>
<outlet property="themeOneCheckMark" destination="YDJ-OW-yab" id="gjk-WA-1yK"/>

View File

@@ -36,5 +36,9 @@
</array>
</dict>
</dict>
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
</dict>
</plist>

View File

@@ -2,9 +2,15 @@
"Hello" = "नमस्ते";
"Yes" = "हाँ";
"No" = "नहीं";
"Cancel" = "नहीं";
"Logout" = "लॉग आउट";
"Deactivate" = "निष्क्रिय करें";
"Error" = "गलती";
"Retry?" = "पुनः प्रयास करें?";
"Please wait..." = "कृपया प्रतीक्षा करें";
"Activate WOKA Account" = "WOKA खाता सक्रिय करें";
"Would you like to reactivate your account?" = "क्या आप अपना खाता पुनः सक्रिय करना चाहेंगे?रें";
/*
Login VC
@@ -168,6 +174,8 @@
"FULL NAME" = "पूरा नाम";
"EMAIL" = "ईमेल";
"Enter your child name" = "अपने बच्चे का नाम दर्ज करें";
"Deactivate WOKA Account" = "WOKA खाता निष्क्रिय करें";
"By clicking the button below, your account will be deactivated. Your data will be erased after one month." = "नीचे दिए गए बटन पर क्लिक करने से आपका अकाउंट निष्क्रिय हो जाएगा। एक महीने के बाद आपका डेटा मिटा दिया जाएगा।";
/*

View File

@@ -13,6 +13,12 @@ import JWPlayerKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var myOrientation: UIInterfaceOrientationMask = .portrait
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return myOrientation
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// enabling the IQKeyboard manager instance

View File

@@ -61,12 +61,13 @@ struct APIEndPoints {
static let guest_queries_store = makeURL(path: "guest_queries_store")
static let update_profile = makeURL(path: "update_profile")
static let user_logout = makeURL(path: "user_logout")
static let user_deactivate_account = makeURL(path: "user_deactivate_account")
}
// Other endpoint categories...
struct Links {
static let privacyPolicy = "https://www.simplitend.com/privacy-policy"
static let termsAndCondition = "https://www.simplitend.com/terms-and-conditions"
static let privacyPolicy = "https://www.wokaland.com/privacy-policy/"
static let termsAndCondition = "https://www.wokaland.com/terms/"
// Other links...
}

View File

@@ -26,5 +26,11 @@ class BaseResponseModel<T: Codable> : Codable, ResponseProtocol{
struct CommonResponseModel : Codable {
let sad : String?
let success: Int?
let message: String?
enum CodingKeys: String, CodingKey {
case success
case message
}
}

View File

@@ -47,27 +47,29 @@ class NetworkManager{
) {
// Stop monitoring network reachability
NetworkReachibility.shared.stopMonitoring()
let loginCred = getLoginIDPass()
// Execute the request on the specified queue
queue.async {
AF.request(url, method: method, parameters: parameters, encoding: encoding, headers: headers, requestModifier: { $0.timeoutInterval = 30 })
.authenticate(username: "admin", password: "Woka@1234")
.authenticate(username: loginCred.0, password: loginCred.1)
.validate(statusCode: 200..<300)
.responseDecodable(of: T.self) { response in
// alamofireLogger.request(response.da, didParseResponse: response)
switch response.result {
case .success(let value):
// Sucess = 4 menas user has logined in other device
/*
if Sucess == 4 menas user has logined in other device
*/
if value.success == 4{
if let topController = UIApplication.topViewController() {
Utilities.alertWithBtnCompletion(title: "Session Expired", msgBody: "Please Login Again", okBtnStr: "OK", vc: topController) { isDone in
AuthFunc.shareInstance.logout()
// UIApplication.setRootView(MainNavController.instantiate(from: .Main))
UIApplication.setRootView(LoginNavVC.instantiate(from: .AuthenticationSB))
}
}
return
}
// Handle successful response on the main thread
DispatchQueue.main.async {
completionHandler(.success(value))
@@ -119,6 +121,15 @@ class NetworkManager{
}
}
}
func getLoginIDPass()-> (String, String){
if let loginID = Bundle.main.infoDictionary?["API_KEY_ID"] as? String , let loginPaass = Bundle.main.infoDictionary?["API_KEY_PASS"] as? String{
let cleanedLoginID = loginID.trimmingCharacters(in: CharacterSet(charactersIn: "\""))
let cleanedLoginPass = loginPaass.trimmingCharacters(in: CharacterSet(charactersIn: "\""))
return (cleanedLoginID, cleanedLoginPass)
}
return ("","")
}
}

View File

@@ -58,7 +58,7 @@ class SplashVM{
func getUserData(){
if AuthFunc.shareInstance.getUserType() == 3{
//setusertype
AuthFunc.shareInstance.userData = UserDataDM.ResultData(id: nil, birthdate: nil, email: nil, avtar: nil, userType: "3", languageMasterID: nil, lastLogin: nil, rememberToken: nil, childDetail: nil, language: nil, alreadyLoggedIn: nil)
AuthFunc.shareInstance.userData = UserDataDM.ResultData(id: nil, birthdate: nil, email: nil, avtar: nil, userType: "3", languageMasterID: nil, lastLogin: nil, rememberToken: nil, childDetail: nil, language: nil, alreadyLoggedIn: nil, isDeactive: nil)
UIApplication.setRootView(SideMenuController.instantiate(from: .Home))
return
}

View File

@@ -0,0 +1,71 @@
//
// WebViewVC.swift
// WOKA
//
// Created by Bilal on 07/06/2024.
//
import UIKit
import WebKit
class WebViewVC: UIViewController, WKNavigationDelegate{
@IBOutlet weak var webView: WKWebView!
@IBOutlet weak var textView: UITextView!
var url : String?
var textContent : LinkTypeEnum?
var pageTitle = String()
override func viewDidLoad() {
super.viewDidLoad()
let color1 = #colorLiteral(red: 0.05490196078, green: 0.01176470588, blue: 0.3882352941, alpha: 1)
let color2 = #colorLiteral(red: 0.2802381199, green: 0.2150136895, blue: 0.8105520973, alpha: 1)
self.view.applyGradient(colors: [color1, color2], startPoint: CGPoint(x: 0, y: 0), endPoint: CGPoint(x: 0, y: 0.5))
self.webView.navigationDelegate = self
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()
self.title = pageTitle.capitalized
if let url {
Utilities.startProgressHUD()
webView.isHidden = false
let link = URL(string:url)!
let request = URLRequest(url: link)
webView.load(request)
Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { _ in
Utilities.dismissProgressHUD()
}
}
if let textContent, textContent == .disclaimer{
if let rtfPath = Bundle.main.url(forResource: "Disclaimer", withExtension: "rtf") {
do {
let rtfData = try Data(contentsOf: rtfPath)
let attributedString = try NSAttributedString(data: rtfData, options: [.documentType: NSAttributedString.DocumentType.rtf], documentAttributes: nil)
textView.text = attributedString.string
textView.font = FontCustom.shareInstance.customFont(fontName: .Exo2_Medium, size: 17)
textView.textContainerInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
textView.textColor = .white
self.textView.isHidden = false
} catch {
print("Error loading RTF file: \(error)")
}
}
}
}
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)
navigationController?.setNavigationBarHidden(true, animated: animated)
self.navigationController?.setColor(color: .black)
}
}

View File

@@ -613,6 +613,51 @@
</objects>
<point key="canvasLocation" x="2466.666666666667" y="-34.151785714285715"/>
</scene>
<!--Web ViewVC-->
<scene sceneID="mAM-Hq-Rtc">
<objects>
<viewController storyboardIdentifier="WebViewVC" id="Fcz-2D-xGA" customClass="WebViewVC" customModule="WOKA" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="7Ks-cK-Os4">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<wkWebView hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jya-sT-MQ9">
<rect key="frame" x="0.0" y="48" width="414" height="848"/>
<color key="backgroundColor" red="0.36078431370000003" green="0.38823529410000002" blue="0.4039215686" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<wkWebViewConfiguration key="configuration">
<audiovisualMediaTypes key="mediaTypesRequiringUserActionForPlayback" none="YES"/>
<wkPreferences key="preferences"/>
</wkWebViewConfiguration>
</wkWebView>
<textView hidden="YES" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" usesAttributedText="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Us0-ed-0Kh">
<rect key="frame" x="0.0" y="48" width="414" height="814"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<attributedString key="attributedText"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView>
</subviews>
<viewLayoutGuide key="safeArea" id="ICx-UO-zYD"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="jya-sT-MQ9" firstAttribute="top" secondItem="ICx-UO-zYD" secondAttribute="top" id="NSb-ey-kMY"/>
<constraint firstItem="ICx-UO-zYD" firstAttribute="trailing" secondItem="Us0-ed-0Kh" secondAttribute="trailing" id="NkS-QA-Ktx"/>
<constraint firstItem="ICx-UO-zYD" firstAttribute="trailing" secondItem="jya-sT-MQ9" secondAttribute="trailing" id="UvI-z1-MnJ"/>
<constraint firstAttribute="bottom" secondItem="jya-sT-MQ9" secondAttribute="bottom" id="Xfq-pK-9v2"/>
<constraint firstItem="jya-sT-MQ9" firstAttribute="leading" secondItem="ICx-UO-zYD" secondAttribute="leading" id="q3g-k7-pxO"/>
<constraint firstItem="ICx-UO-zYD" firstAttribute="bottom" secondItem="Us0-ed-0Kh" secondAttribute="bottom" id="r55-EP-Iub"/>
<constraint firstItem="Us0-ed-0Kh" firstAttribute="top" secondItem="ICx-UO-zYD" secondAttribute="top" id="uYI-Fv-pYD"/>
<constraint firstItem="Us0-ed-0Kh" firstAttribute="leading" secondItem="ICx-UO-zYD" secondAttribute="leading" id="ydt-su-n0x"/>
</constraints>
</view>
<connections>
<outlet property="textView" destination="Us0-ed-0Kh" id="ee9-fL-87k"/>
<outlet property="webView" destination="jya-sT-MQ9" id="TPo-bo-Mi1"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="cpC-U7-IvE" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="3296" y="-34"/>
</scene>
</scenes>
<designables>
<designable name="arD-av-w7V">

View File

@@ -30,6 +30,9 @@ class SideMenuVC: UIViewController {
@IBOutlet weak var myOrderBtn: UIButton!
@IBOutlet weak var addChildBtn: UIButton!
@IBOutlet weak var deactivateBtn: UIButton!
@IBOutlet weak var termsConditionBtn: UIButton!
@IBOutlet weak var privacyPolicyBtn: UIButton!
@IBOutlet weak var disclaimerBtn: UIButton!
@IBOutlet weak var avatarImage: UIImageView!
@IBOutlet weak var scrollView: UIScrollView!
@@ -70,6 +73,15 @@ class SideMenuVC: UIViewController {
case deactivateBtn:
self.sideMenuController?.hideMenu()
NotificationCenter.default.post(name: .linkPush, object: nil, userInfo: ["type": LinkTypeEnum.deactivate])
case termsConditionBtn:
self.sideMenuController?.hideMenu()
NotificationCenter.default.post(name: .linkPush, object: nil, userInfo: ["type": LinkTypeEnum.termsCondition])
case privacyPolicyBtn:
self.sideMenuController?.hideMenu()
NotificationCenter.default.post(name: .linkPush, object: nil, userInfo: ["type": LinkTypeEnum.privacyPolicy])
case disclaimerBtn:
self.sideMenuController?.hideMenu()
NotificationCenter.default.post(name: .linkPush, object: nil, userInfo: ["type": LinkTypeEnum.disclaimer])
default:
break
}
@@ -88,7 +100,6 @@ class SideMenuVC: UIViewController {
vm.logoutUser { isDone in
self.sideMenuController?.hideMenu()
AuthFunc.shareInstance.logout()
// UIApplication.setRootView(MainNavController.instantiate(from: .Main))
UIApplication.setRootView(LoginNavVC.instantiate(from: .AuthenticationSB))
}
case .no:

View File

@@ -5,6 +5,7 @@
import UIKit
import Alamofire
class TabBarVC: UITabBarController {
@@ -66,10 +67,13 @@ class TabBarVC: UITabBarController {
let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.CustomAlerts.yesNoAlertVC) as! YesNoAlertVC
vcPush.mainTitleText = "Deactivate WOKA Account"
vcPush.contentLabel = "By clicking the button below, your account will be deactivated. Your data will be erased after one month."
vcPush.onDoneBlock = { mode in
vcPush.yesBtnText = "Deactivate"
vcPush.noBtnText = "Cancel"
vcPush.onDoneBlock = { [unowned self] mode in
switch mode{
case .yes:
//If user clicked to proceed on login. Call the api.
//If user clicked nav him to login screen. Call the api.
deactivateAccount()
print("Yes")
case .no:
print("no")
@@ -78,6 +82,24 @@ class TabBarVC: UITabBarController {
vcPush.modalPresentationStyle = .overCurrentContext
vcPush.modalTransitionStyle = .crossDissolve
self.present(vcPush, animated: true)
case .termsCondition:
let sb = UIStoryboard(name: K.StoryBoard.sideBarNav, bundle: nil)
let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.SideBarNav.webViewVC) as! WebViewVC
vcPush.url = APIEndPoints.Links.termsAndCondition
vcPush.pageTitle = "Terms & Condition"
self.navigationController?.pushViewController(vcPush, animated: true)
case .privacyPolicy:
let sb = UIStoryboard(name: K.StoryBoard.sideBarNav, bundle: nil)
let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.SideBarNav.webViewVC) as! WebViewVC
vcPush.url = APIEndPoints.Links.privacyPolicy
vcPush.pageTitle = "Privacy Policy"
self.navigationController?.pushViewController(vcPush, animated: true)
case .disclaimer:
let sb = UIStoryboard(name: K.StoryBoard.sideBarNav, bundle: nil)
let vcPush = sb.instantiateViewController(withIdentifier: K.StoryBoardID.SideBarNav.webViewVC) as! WebViewVC
vcPush.pageTitle = "Disclaimer"
vcPush.textContent = .disclaimer
self.navigationController?.pushViewController(vcPush, animated: true)
}
}
}
@@ -127,30 +149,35 @@ class TabBarVC: UITabBarController {
UITabBarItem.appearance().setTitleTextAttributes(attributes, for: .normal)
}
// function to customize tab bar item icon size
// func customizeTabBarItemIconSize() {
// // Get a reference to the tab bar controller
// if let tabBarController = self.tabBarController {
// // Loop through each tab bar item
// for item in tabBarController.tabBar.items! {
// // Adjust the image insets to increase the icon size
// item.imageInsets = UIEdgeInsets(top: 4, left: 0, bottom: -8, right: 0)
// }
// }
// }
///Add tabbar item indicator uper line
// func addTabbarIndicatorView(index: Int, isFirstTime: Bool = false){
// guard let tabView = tabBar.items?[index].value(forKey: "view") as? UIView else {
// return
// }
// if !isFirstTime{
// upperLineView.removeFromSuperview()
// }
// upperLineView = UIView(frame: CGRect(x: tabView.frame.minX + spacing, y: tabView.frame.minY + 0.1, width: tabView.frame.size.width - spacing * 2, height: 4))
// upperLineView.backgroundColor = UIColor.systemPink
// tabBar.addSubview(upperLineView)
// }
// MARK: - Deactivate Account API Call
func deactivateAccount(){
let headers : HTTPHeaders = ["Accept-Language" : AuthFunc.shareInstance.languageSelected == .english ? "English" : "Hindi",
"access-token" : AuthFunc.shareInstance.getAccessToken()]
Utilities.startProgressHUD()
NetworkManager.shareInstance.apiRequest(url: APIEndPoints.SideBarNav.user_deactivate_account, method: .get,headers: headers) {(result : Result<BaseResponseModel<UserEmailVerifyDM>, NetworkManager.APIError>) in
switch result{
case .success(let data):
switch data.success{
case 0: // some error
Utilities.dismissProgressHUD()
self.toast(msg: data.message ?? "Unrecognised error" , time: 2)
case 1: // Success
Utilities.dismissProgressHUD()
self.toast(msg: data.message ?? "Deactivated Account Successfully.", time: 2) {
AuthFunc.shareInstance.logout()
UIApplication.setRootView(LoginNavVC.instantiate(from: .AuthenticationSB))
}
default:
Utilities.dismissProgressHUD()
self.toast(msg: K.ConstantString.unRecognised , time: 1)
}
case .failure(let error):
Utilities.dismissProgressHUD()
self.toast(msg: error.localizedDescription , time: 2)
}
}
}
// MARK: Private methods

View File

@@ -14,4 +14,7 @@ enum LinkTypeEnum {
case profile
case addChild
case deactivate
case termsCondition
case privacyPolicy
case disclaimer
}

View File

@@ -149,7 +149,7 @@
</constraints>
</imageView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="edI-4n-4AY">
<rect key="frame" x="19.333333333333329" y="58.333333333333336" width="167" height="114.33333333333331"/>
<rect key="frame" x="14.333333333333329" y="58.333333333333336" width="167" height="114.33333333333331"/>
<color key="backgroundColor" systemColor="systemGreenColor"/>
</view>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="LiveTVBorder" translatesAutoresizingMaskIntoConstraints="NO" id="FTD-lO-6ko">
@@ -165,10 +165,12 @@
<constraint firstItem="FTD-lO-6ko" firstAttribute="leading" secondItem="kzE-UE-7KK" secondAttribute="leading" id="MjF-Bf-i0B"/>
<constraint firstItem="bJW-hf-OzK" firstAttribute="width" secondItem="kzE-UE-7KK" secondAttribute="width" multiplier="0.65534" id="RPK-qk-aYn"/>
<constraint firstItem="bJW-hf-OzK" firstAttribute="top" secondItem="kzE-UE-7KK" secondAttribute="top" id="TfL-do-87D"/>
<constraint firstItem="edI-4n-4AY" firstAttribute="centerX" secondItem="kzE-UE-7KK" secondAttribute="centerX" constant="5" id="elb-rG-Jom"/>
<constraint firstItem="edI-4n-4AY" firstAttribute="centerX" secondItem="kzE-UE-7KK" secondAttribute="centerX" id="elb-rG-Jom"/>
<constraint firstAttribute="bottom" secondItem="FTD-lO-6ko" secondAttribute="bottom" id="hxq-jC-EkJ"/>
<constraint firstAttribute="bottom" secondItem="edI-4n-4AY" secondAttribute="bottom" constant="8" id="qG7-HL-AwT"/>
<constraint firstAttribute="trailing" secondItem="FTD-lO-6ko" secondAttribute="trailing" id="seE-xo-G4v"/>
<constraint firstAttribute="trailing" secondItem="edI-4n-4AY" secondAttribute="trailing" constant="14.33" id="vqi-fs-cpS"/>
<constraint firstItem="edI-4n-4AY" firstAttribute="leading" secondItem="kzE-UE-7KK" secondAttribute="leading" constant="14.33" id="yBa-gn-rzX"/>
</constraints>
</view>
<stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="Qfe-q3-rbY">
@@ -405,7 +407,6 @@
<constraint firstItem="kzE-UE-7KK" firstAttribute="height" secondItem="UEh-jl-IQp" secondAttribute="height" multiplier="0.212054" id="s5Y-TI-1sZ"/>
<constraint firstItem="ppi-HI-rj1" firstAttribute="height" secondItem="UEh-jl-IQp" secondAttribute="height" multiplier="0.535714" id="sLx-ty-T4s"/>
<constraint firstItem="sf9-me-n7i" firstAttribute="centerX" secondItem="vdl-cu-G32" secondAttribute="centerX" id="vZE-xF-UKh"/>
<constraint firstItem="edI-4n-4AY" firstAttribute="width" secondItem="UEh-jl-IQp" secondAttribute="width" multiplier="0.424936" id="zBP-Cg-rTK"/>
</constraints>
</view>
<tabBarItem key="tabBarItem" title="HOME" image="HomeIcon" selectedImage="HomeIcon" id="4Hm-tg-Heb"/>
@@ -621,7 +622,7 @@
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
<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>
</resources>
</document>

View File

@@ -3,153 +3,141 @@
// WOKA
//
// Created by MacBook Pro on 30/05/24.
//
import UIKit
import JWPlayerKit
import AVKit
class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate{
func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, relatedItemBeganPlaying item: JWPlayerKit.JWPlayerItem, atIndex index: Int, withMethod method: JWPlayerKit.JWRelatedMethod) {
}
class PlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate {
override func jwplayer(_ player: any JWPlayer, didFinishLoadingWithTime loadTime: TimeInterval) {
print("LoadTime " , loadTime)
self.player.play()
}
@IBOutlet weak var innerPlayerView: UIView!
var previousScale: CGFloat = 1.0
let backButton = UIButton(type: .system)
var config : JWPlayerConfiguration!
var dismissTapped : (() -> Void)?
var config: JWPlayerConfiguration!
var dismissTapped: (() -> Void)?
func rotateToLandsScapeDevice(){
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.myOrientation = .landscapeRight
if #available(iOS 16.0, *) {
let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: UIInterfaceOrientationMask.landscapeRight))
} else {
UIDevice.current.setValue(UIInterfaceOrientationMask.landscapeRight.rawValue, forKey: "orientation")
}
UIView.setAnimationsEnabled(true)
}
func rotateToPotraitScapeDevice(){
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.myOrientation = .portrait
if #available(iOS 16.0, *) {
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(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
UIView.setAnimationsEnabled(true)
}
override func viewDidLoad() {
super.viewDidLoad()
self.rotateToLandsScapeDevice()
self.delegate = self
self.transitionToFullScreen(animated: true)
//
// self.playerView.videoGravity = .resizeAspectFill
// let skinStylingBuilder = JWPlayerSkinBuilder()
// // Call methods on the builder to create your desired style.
// skinStylingBuilder.backgroundColor(UIColor.blue)
// skinStylingBuilder.fontColor(UIColor.red)
//// self.interfaceBehavior = .hidden
// self.playerView.captionStyle = .none
// // skinStylingBuilder.buttonsColor(UIColor.purple)
//
// let skinStyling = try? skinStylingBuilder.build()
// self.styling = skinStyling
player.configurePlayer(with: config)
// self.playerView.allowsPictureInPicturePlayback = true
// self.player.seek(to: 15)
NotificationCenter.default.addObserver(self, selector: #selector(applicationDidBecomeActive), name: UIApplication.willEnterForegroundNotification, object: nil)
// NotificationCenter.default.addObserver(self, selector: #selector(applicationDidBecomeActive), name: UIApplication.willEnterForegroundNotification, object: nil)
}
@objc func applicationDidBecomeActive() {
self.setDeviceOrientation(orientation: .landscapeRight)
}
// Handle device orientation change
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
if (size.width > self.view.frame.size.width) {
if size.width > self.view.frame.size.width {
print("Landscape")
} else {
DispatchQueue.main.async {
self.dismiss(animated: true)
// self.navigationController?.popViewController(animated: true)
}
}
}
// Action for back button tap
@objc func backButtonTapped() {
// Perform actions when the back button is tapped, such as dismissing the current view controller
setDeviceOrientation(orientation: .portrait)
// or
// dismiss(animated: true, completion: nil)
}
// @objc func backButtonTapped() {
// setDeviceOrientation(orientation: .portrait)
// }
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.isNavigationBarHidden = true
// self.transitionToFullScreen(animated: true)
}
override func viewWillDisappear(_ animated: Bool) {
// self.dismissFullScreen(animated: true)
super.viewWillDisappear(animated)
player.stop()
}
// MARK: - JWPlayerViewControllerDelegate
override func jwplayer(_ player: any JWPlayer, didFinishLoadingWithTime loadTime: TimeInterval) {
super.jwplayer(player, didFinishLoadingWithTime: loadTime)
print("LoadTime", loadTime)
self.player.play()
}
override func jwplayerIsReady(_ player: JWPlayer) {
super.jwplayerIsReady(player)
print("IsReady")
}
override func jwplayer(_ player: JWPlayer, failedWithSetupError code: UInt, message: String) {
super.jwplayer(player, failedWithSetupError: code, message: message)
print("Setup Error: \(code) - \(message)")
}
override func jwplayer(_ player: JWPlayer, failedWithError code: UInt, message: String) {
super.jwplayer(player, failedWithError: code, message: message)
print("Error: \(code) - \(message)")
}
override func jwplayer(_ player: JWPlayer, encounteredWarning code: UInt, message: String) {
super.jwplayer(player, encounteredWarning: code, message: message)
print("Warning: \(code) - \(message)")
}
override func jwplayer(_ player: JWPlayer, encounteredAdError code: UInt, message: String) {
super.jwplayer(player, encounteredAdError: code, message: message)
print("Ad Error: \(code) - \(message)")
}
override func jwplayer(_ player: JWPlayer, encounteredAdWarning code: UInt, message: String) {
super.jwplayer(player, encounteredAdWarning: code, message: message)
print("Ad Warning: \(code) - \(message)")
}
override func jwplayer(_ player: JWPlayer, isBufferingWithReason reason: JWBufferReason) {
super.jwplayer(player, isBufferingWithReason: reason)
player.play()
print("Buffering Reason:", reason)
}
override func jwplayer(_ player: JWPlayer, didPauseWithReason reason: JWPauseReason) {
super.jwplayer(player, didPauseWithReason: reason)
// Implement custom behavior
}
// MARK: - JWPlayerDelegate
// Player is ready
override func jwplayerIsReady(_ player: JWPlayer) {
super.jwplayerIsReady(player)
print("IsReady")
}
// Setup error
override func jwplayer(_ player: JWPlayer, failedWithSetupError code: UInt, message: String) {
super.jwplayer(player, failedWithSetupError: code, message: message)
}
// Error
override func jwplayer(_ player: JWPlayer, failedWithError code: UInt, message: String) {
super.jwplayer(player, failedWithError: code, message: message)
}
// Warning
override func jwplayer(_ player: JWPlayer, encounteredWarning code: UInt, message: String) {
super.jwplayer(player, encounteredWarning: code, message: message)
}
// Ad error
override func jwplayer(_ player: JWPlayer, encounteredAdError code: UInt, message: String) {
super.jwplayer(player, encounteredAdError: code, message: message)
}
// Ad warning
override func jwplayer(_ player: JWPlayer, encounteredAdWarning code: UInt, message: String) {
super.jwplayer(player, failedWithSetupError: code, message: message)
}
override func jwplayer(_ player: JWPlayer, isBufferingWithReason reason: JWBufferReason) {
player.play()
print("Reason ", reason)
}
}
// MARK: - Full Screen
// MARK: - Full Screen Handling
extension PlayerVC{
extension PlayerVC {
func playerViewControllerWillGoFullScreen(_ controller: JWPlayerViewController) -> JWFullScreenViewController? {
// controller.shouldEnterFullScreen = false
self.setDeviceOrientation(orientation: .portrait)
print("playerViewControllerWillGoFullScreen")
// self.dismiss(animated: false) {
// self.setDeviceOrientation(orientation: .portrait)
// }
return nil
}
@@ -161,50 +149,87 @@ extension PlayerVC{
func playerViewControllerWillDismissFullScreen(_ controller: JWPlayerViewController) {
print("playerViewControllerWillDismissFullScreen")
self.player.stop()
self.setDeviceOrientation(orientation: .portrait)
// self.setDeviceOrientation(orientation: .portrait)
// Timer.scheduledTimer(withTimeInterval: 0.4, repeats: false) { _ in
// controller.dismissFullScreen(animated: false) {
// self.dismissTapped?()
// }
// }
self.rotateToPotraitScapeDevice()
// self.dismiss
// self.setDeviceOrientation(orientation: .portrait)
// Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { _ in
// controller.dismiss(animated: false) {
// }
// self.setDeviceOrientation(orientation: .portrait)
// }
}
func playerViewControllerDidDismissFullScreen(_ controller: JWPlayerViewController) {
print("playerViewControllerDidDismissFullScreen")
Timer.scheduledTimer(withTimeInterval: 0.3, repeats: false) { _ in
self.navigationController?.popViewController(animated: true)
self.dismissTapped?()
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { _ in
self.player.stop()
controller.dismiss(animated: true)
}
// self.navigationController?.popViewController(animated: true)
}
}
// MARK: - JWPlayerViewController Delegate Funcs
extension PlayerVC{
func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, controlBarVisibilityChanged isVisible: Bool, frame: CGRect) {
// print("CC visible",isVisible)
isVisible ? (backButton.isHidden = false) : (backButton.isHidden = true)
}
func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, sizeChangedFrom oldSize: CGSize, to newSize: CGSize) {
}
func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, screenTappedAt position: CGPoint) {
}
func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, relatedMenuOpenedWithItems items: [JWPlayerKit.JWPlayerItem], withMethod method: JWPlayerKit.JWRelatedInteraction) {
print("Item ",items)
}
// func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, relatedItemBeganPlaying item: JWPlayerKit.JWPlayerItem, atIndex index: Int, withMethod method: JWPlayerKit.JWRelatedMethod) {
//
// func playerViewControllerWillGoFullScreen(_ controller: JWPlayerViewController) -> JWFullScreenViewController? {
// print("playerViewControllerWillGoFullScreen")
// return nil
// }
//
// func playerViewControllerDidGoFullScreen(_ controller: JWPlayerViewController) {
// print("playerViewControllerDidGoFullScreen")
// }
//
// func playerViewControllerWillDismissFullScreen(_ controller: JWPlayerViewController) {
// print("playerViewControllerWillDismissFullScreen")
// self.player.stop()
// self.dismissTapped?()
// self.setDeviceOrientation(orientation: .portrait)
// }
//
// func playerViewControllerDidDismissFullScreen(_ controller: JWPlayerViewController) {
// print("playerViewControllerDidDismissFullScreen")
// Timer.scheduledTimer(withTimeInterval: 0.3, repeats: false) { _ in
// self.navigationController?.popViewController(animated: true)
// }
// }
}
// MARK: - JWPlayerViewController Delegate Functions
extension PlayerVC {
func playerViewController(_ controller: JWPlayerViewController, relatedMenuClosedWithMethod method: JWRelatedInteraction){
print("Close")
func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, controlBarVisibilityChanged isVisible: Bool, frame: CGRect) {
backButton.isHidden = !isVisible
}
func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, sizeChangedFrom oldSize: CGSize, to newSize: CGSize) {
// Handle size change if necessary
}
func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, screenTappedAt position: CGPoint) {
// Handle screen tap if necessary
}
func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, relatedMenuOpenedWithItems items: [JWPlayerKit.JWPlayerItem], withMethod method: JWPlayerKit.JWRelatedInteraction) {
print("Related items:", items)
}
func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, relatedMenuClosedWithMethod method: JWRelatedInteraction) {
print("Related menu closed")
}
func playerViewController(_ controller: JWPlayerKit.JWPlayerViewController, relatedItemBeganPlaying item: JWPlayerKit.JWPlayerItem, atIndex index: Int, withMethod method: JWPlayerKit.JWRelatedMethod) {
print("Item ", item)
}
}
// MARK: - Orientation Handling
extension UIViewController {
@@ -222,15 +247,15 @@ extension UIInterfaceOrientationMask {
var toUIInterfaceOrientation: UIInterfaceOrientation {
switch self {
case .portrait:
return UIInterfaceOrientation.portrait
return .portrait
case .portraitUpsideDown:
return UIInterfaceOrientation.portraitUpsideDown
return .portraitUpsideDown
case .landscapeRight:
return UIInterfaceOrientation.landscapeRight
return .landscapeRight
case .landscapeLeft:
return UIInterfaceOrientation.landscapeLeft
return .landscapeLeft
default:
return UIInterfaceOrientation.unknown
return .unknown
}
}
}

View File

@@ -187,7 +187,7 @@ class ThemeOneVM{
let item = try JWPlayerItemBuilder()
.file(URL(string: self.liveStreamURL)!)
.title("Testing Title")
.posterImage(URL(string: "https://img.freepik.com/free-photo/painting-mountain-lake-with-mountain-background_188544-9126.jpg")!)
// .posterImage(URL(string: "https://img.freepik.com/free-photo/painting-mountain-lake-with-mountain-background_188544-9126.jpg")!)
// .mediaTracks([thumbnailTrack])
.build()
@@ -195,35 +195,36 @@ class ThemeOneVM{
let config = try JWPlayerConfigurationBuilder()
.playlist(items: [item])
.autostart(true)
.preload(.auto)
.repeatContent(true)
// .preload(.auto)
// .repeatContent(true)
.build()
vc.config = config
vc.dismissTapped = self.tapped
vc.modalPresentationStyle = .overFullScreen
Utilities.dismissProgressHUD()
self.vc.present(vc, animated: false) {
self.stopLiveStream()
vc.transitionToFullScreen(animated: true) {
print("FullScreen")
}
// vc.setDeviceOrientation(orientation: .landscapeRight)
}
// Utilities.dismissProgressHUD()
// self.vc.navigationController?.pushViewController(vc, animated: true)
// self.stopLiveStream()
}
catch {
// Handle Error
}
vc.dismissTapped = self.tapped
// vc.modalPresentationStyle = .overFullScreen
// self.vc.present(vc, animated: false) {
// self.stopLiveStream()
//// vc.transitionToFullScreen(animated: true) {
//// print("FullScreen")
//// }
//// vc.setDeviceOrientation(orientation: .landscapeRight)
// }
Utilities.dismissProgressHUD()
self.vc.navigationController?.pushViewController(vc, animated: true)
self.stopLiveStream()
}
}
func tapped(){
Timer.scheduledTimer(withTimeInterval: 0.2, repeats: false) { _ in
self.startLiveStream()
self.vc.liveTvPlayer.layoutIfNeeded()
}
print("Sadasd")
}